from copy import deepcopy
from elasticsearch import Elasticsearch
from common.utility.args_parsing import BaseArgsParsing


class ESClient(BaseArgsParsing):
    LIST_KEYWORD = ['must', 'should']

    def conn(self, host=None, username=None, password=None, port=None):
        if username and password:
            self.es = Elasticsearch(f"http://{host}/", port=port, http_auth=(username, password))
        else:
            self.es = Elasticsearch(f"http://{host}/", port=port)
        return self.es

    def transform(self, data):
        body = {}
        for key in data:
            if (not key) or (not data.get(key)):
                continue
            values = data.get(key)
            if key in self.RESERVED_FIELD:
                continue
            itme = key.split("_")
            if len(itme) > 1:
                real_key = "_".join(itme[:-1])
                keyword = itme[-1].lower()
                if keyword in self.SUFFIX_KEYWORD:
                    self.build_suffix_keyword_args(body, real_key, keyword, data.get(key))
                    continue

            page, size = self.get_page_and_size(data)

    def build_suffix_keyword_args(self, body, key, keyword, value):
        if keyword == self.GT or keyword == self.GTE or keyword == self.LT or keyword == self.LTE:
            if 'query' in body.keys():
                pass
            else:
                body['query'] = {
                    "range": {
                        key: {
                            "gt": "2021-07-26T10:00:00Z",
                            'lt': "2021-07-26T10:02:00Z",
                        }
                    }
                }

    def build(self, body, keys, field, vaule):
        if body is None:
            body = {}
        if '.' in keys:
            itme = keys.split('.')
            key = itme[0]
            if isinstance(body, dict):
                if key in body.keys():
                    body[key] = self.build(body[key], '.'.join(itme[1:]), field, vaule)
                    return body
                else:
                    child_body = [] if key in self.LIST_KEYWORD else {}
                    body[key] = self.build(child_body, '.'.join(itme[1:]), field, vaule)
                    return body
            else:
                body.append({key: self.build({}, '.'.join(itme[1:]), field, vaule)})
                return body

        else:
            key = keys
            if isinstance(body, dict):
                if key in body.keys():
                    body[key][field] = vaule
                    return body[key]
                else:
                    return {
                        key: {
                            field: vaule
                        }
                    }
            else:
                body.append({key: {field: vaule}})
                return body

    def build2(self, body, keys, field, vaule):
        if body is None:
            body = {}
        if '.' in keys:
            itme = keys.split('.')
            key = itme[0]
            if key in body.keys():
                body[key] = self.build(body[key], '.'.join(itme[1:]), field, vaule)
                return body
            else:
                child_body = [] if key in self.LIST_KEYWORD else {}
                body[key] = self.build(child_body, '.'.join(itme[1:]), field, vaule)
                return body

        else:
            key = keys
            if isinstance(body, dict):
                if key in body.keys():
                    body[key][field] = vaule
                    return body[key]
                else:
                    return {
                        key: {
                            field: vaule
                        }
                    }
            else:
                body.append({key: {field: vaule}})
                return body

    def sort_(self, key, value, body=None):
        if not body:
            body = {}
        sort_data = {
            key: {
                'order': value
            }
        }
        if 'sort' in body.keys():
            body['sort'].append(sort_data)
        else:
            body['sort'] = [sort_data]
        return body

    def and_(self, key, value, body=None):

        body = self.build(body, 'query.bool.must.match_phrase', key, value)
        return body

    def or_(self, key, value, body=None):

        body = self.build(body, 'query.bool.should.match_phrase', key, value)
        return body

    def range_(self, key, kw, value, body=None):
        body = self.build(body, 'query.bool.must.range.' + key, kw, value)
        return body

    def not_(self, key, value, body=None):
        body = self.build(body, 'query.bool.must_not.match_phrase', key, value)
        return body


if __name__ == '__main__':
    es_client = ESClient()
    body = es_client.and_('series', 'P')
