# -*- coding: utf-8 -*-

from .client import client

import logging

logger = logging.getLogger("quartzbio")


class Annotator(object):
    """
    Runs the synchronous annotate endpoint against
    batches of results from a query.
    """

    CHUNK_SIZE = 100

    # Allows pre-setting a QuartzBioClient
    _client = None

    def __init__(self, fields, **kwargs):
        self._client = kwargs.pop("client", None) or self._client or client

        self.buffer = []
        self.fields = fields

        # Pop annotator_params from kwargs
        annotator_param_keys = [
            "annotator",
            "debug",
            "include_errors",
            "post_annotation_expression",
            "pre_annotation_expression",
        ]
        self.annotator_params = {}
        for key in annotator_param_keys:
            if key in kwargs:
                self.annotator_params[key] = kwargs.pop(key)

        self.data = kwargs.get("data")

    def annotate(self, records, **kwargs):
        """Annotate a set of records with stored fields.

        Args:
            records: A list or iterator (can be a Query object)
            chunk_size: The number of records to annotate at once (max 500).

        Returns:
            A generator that yields one annotated record at a time.
        """
        # Update annotator_params with any kwargs
        self.annotator_params.update(**kwargs)
        chunk_size = self.annotator_params.get("chunk_size", self.CHUNK_SIZE)

        chunk = []
        for i, record in enumerate(records):
            chunk.append(record)
            if (i + 1) % chunk_size == 0:
                for r in self._execute(chunk):
                    yield r
                chunk = []

        if chunk:
            for r in self._execute(chunk):
                yield r
            chunk = []

    def _execute(self, chunk):
        data = {
            "records": chunk,
            "fields": self.fields,
            "annotator_params": self.annotator_params,
            "data": self.data,
        }

        for r in self._client.post("/v1/annotate", data)["results"]:
            yield r


class Expression(object):
    """Runs a single QuartzBio expression."""

    # Allows pre-setting a QuartzBioClient
    _client = None

    def __init__(self, expr, **kwargs):
        self.expr = expr
        self._client = kwargs.get("client") or self._client or client

    def evaluate(self, data=None, data_type="string", is_list=False):
        """Evaluates the expression with the provided context and format."""
        payload = {
            "data": data,
            "expression": self.expr,
            "data_type": data_type,
            "is_list": is_list,
        }
        res = self._client.post("/v1/evaluate", payload)
        return res["result"]

    def __repr__(self):
        return '<Expression "{0}">'.format(self.expr)
