import json
import math

from elasticsearch import Elasticsearch


class ElasticQuery:
    current_page = 0
    max_entries = -1
    size = 10

    def __init__(self):
        self.client = Elasticsearch("http://10.6.71.62:9200")
        self.final_query = {'query': {}}
        self.final_query['query']['bool'] = {}
        self.final_query['query']['bool']['must'] = []
        self.final_query['query']['bool']['filter'] = []

    def get_first_doc_number(self):
        return self.current_page * self.size

    def send(self, index):
        resp = self.client.search(
            index=index,
            body=self.final_query
        )
        self.max_entries = resp['hits']['total']['value']
        return self.size, resp['hits']['hits']

    def next(self):
        if self.max_entries == -1:
            return True
        if self.current_page * self.size >= self.max_entries:
            return False
        self.current_page += 1
        self.final_query["from"] = self.get_first_doc_number()
        return True

    def previous(self):
        if self.current_page == 0:
            return False
        self.current_page -= 1
        self.final_query["from"] = self.get_first_doc_number()
        return True

    def restart(self):
        self.current_page = 0
        self.final_query["from"] = 0

    def get_number_of_pages(self):
        if self.max_entries == -1:
            return -1
        return math.ceil(float(self.max_entries) / self.size)

    def match_from_timestamp(self, early_ts, late_ts):
        # 'gte': '2022-04-22T11:13:28',
        # 'lte': '2022-04-22T11:14:03'
        self.match_from_field('timestamp', early_ts, late_ts)
        return self

    def set_size(self, size):
        self.size = size
        self.final_query["size"] = size

    def match_from_field(self, field, early_ts, late_ts):
        condition = {'range': {field: {'gte': early_ts,
                                       'lte': late_ts}}}
        self.final_query['query']['bool']['must'].append(condition)
        return self

    def match_from_method(self, method):
        condition = {'term': {'method': method}}
        self.final_query['query']['bool']['filter'].append(condition)
        return self

    def match_all(self):
        self.final_query['query'] = {'match_all': {}}

    @staticmethod
    def from_string(query_str):
        query = ElasticQuery()
        query.final_query = json.loads(query_str)
        return query
