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

from typing import List, Dict, Union

from pyesl.aggs import AggsBase
from pyesl.query import QueryBase


class ScriptField(AggsBase):
    """
    Field that generated by with
    just field:
    1. sql like: select
    1. sql like: select a+b as c
    2. pql like: a + b
    """
    BODY_TEMPLATE = {
        "alias_1": {
            "script": {
                "source": "doc['field.{field}'].value + doc['field.{field}'].value"
            }
        }
    }

    def __init__(
            self, fields: Dict[str, str], expr: str, alias: Union[str, None] = None,
            field_format: str = "doc['field.{field}'].value"):
        _name = alias or 'cal_{}'.format('#'.join(fields))
        self._fields_formatted = {}
        for key, field_name in fields.items():
            self._fields_formatted[key] = field_format.format(field=field_name)
        self._expr_formatted = expr.format(**self._fields_formatted)
        _body = {
            _name: {
                'script': {
                    'source': self._expr_formatted
                }
            }
        }
        super().__init__(_body, _name)


class ScriptFields(AggsBase):
    BODY_TEMPLATE = {
        "script_fields": {
            "alias_1": {
                "script": {
                    "source": "doc['field.{field}'].value + doc['field.{field}'].keyword"
                }
            },
            "alias_2": {
                "script": {
                    "source": "doc['field.{field}'].value + doc['field.{field}'].keyword"
                }
            }
        }
    }

    def __init__(self, script_field: List[ScriptField]):
        _body = {
            "script_fields": {}
        }
        _result_path = []
        for _f in script_field:
            _body['script_fields'][_f.name] = _f.body[_f.name]
            _result_path.append(_f.name)
        super().__init__(_body, 'sf_{}'.format('#'.join(_result_path)))
        self._result_path = _result_path


class Field(object):
    def __init__(self, name: str, ):
        self._name = name

    @property
    def name(self):
        return self._name


class SourceFields(QueryBase):
    """
    Original field of the data point
    """
    BODY_TEMPLATE = {
        "_source": {
            "includes": ["tag", "field", "ts", "metric"]
        }
    }

    def __init__(self, fields: List[Field]):
        _body = {
            "_source": {
                "includes": [_f.name for _f in fields]
            }
        }
        super().__init__(_body)


class Fields(object):
    def __init__(self, source_fields: SourceFields = None, script_fields: ScriptFields = None):
        self._source_fields = source_fields
        self._script_fields = script_fields

    @property
    def source_fields(self) -> SourceFields:
        return self._source_fields

    @property
    def script_fields(self) -> ScriptFields:
        return self._script_fields
