from elasticsearch import *
from elasticsearch_dsl import *
from os import path
import os

from elasticsearch_dsl.response import Response


def get_property():
    f = open(path.join(os.path.dirname(os.path.realpath(__file__)), '../../../../api.properties'))
    p = {}
    for line in f:
        if not line.startswith("#"):
            data = line.strip().split("=")
            p[data[0].strip()] = data[1].strip()
    return p


class DLIESConnector(object):
    def __init__(self):
        props = get_property()
        index_name = props['api.index']
        index_host = [x for x in props['es_index'].split(',')]

        self.client = Elasticsearch(hosts=index_host)
        self.index_name = index_name

    def create_pidType_query(self, value, start):
        args = {start + '.identifier.schema': value}
        return Q('nested', path=start + '.identifier', query=Q('bool', must=[Q('match', **args)]))

    def create_pid_query(self, value, start):
        args = {start + '.identifier.identifier': value.lower()}
        return Q('nested', path=start + '.identifier', query=Q('bool', must=[Q('match', **args)]))

    def create_typology_query(self, value):
        args = {'target.objectType': value}
        return Q('nested', path='target', query=Q('bool', must=[Q('match', **args)]))

    def create_dataSource_query(self, value):
        args = {'linkprovider.name': value}
        return Q('nested', path='linkprovider', query=Q('bool', must=[Q('match', **args)]))

    def create_publisher_query(self, value, start):
        args = {start + '.publisher.name': value}
        q = Q('nested', path=start + '.publisher', query=Q('bool', must=[Q('match', **args)]))
        return Q('nested', path=start, query=q)

    def list_datasources(self, ds_name=None):
        search_object = Search(using=self.client, index=self.index_name).doc_type('scholix')
        if ds_name:
            search_object = search_object.query(self.create_dataSource_query(ds_name))
        else:
            search_object = search_object.query()
        search_object.aggs.bucket('all_datasources', 'nested', path='linkprovider').bucket('all_names', 'terms',
                                                                                           field='linkprovider.name',
                                                                                           size=100)

        response = search_object.execute()
        if ds_name:
            return [dict(name=item.key, totalRelationships=item.doc_count) for item in
                    response.aggs.all_datasources.all_names.buckets if item.key == ds_name]
        return [dict(name=item.key, totalRelationships=item.doc_count) for item in
                response.aggs.all_datasources.all_names.buckets]

    def list_publisher(self, start, pub_name=None):
        search_object = Search(using=self.client, index=self.index_name).doc_type('scholix')
        if pub_name:
            search_object = search_object.query(self.create_publisher_query(pub_name, start))
        else:
            search_object = search_object.query()
        search_object.aggs.bucket('all_targets', 'nested', path=start).bucket('all_t_pubs', 'nested',
                                                                              path=start + '.publisher').bucket(
            'all_pubs', 'terms',
            field=start + '.publisher.name',
            size=1000000)

        response = search_object.execute()
        if pub_name:
            return [dict(name=item.key, totalRelationships=item.doc_count) for item in
                    response.aggs.all_targets.all_t_pubs.all_pubs.buckets if item.key == pub_name]
        return [dict(name=item.key, totalRelationships=item.doc_count) for item in
                response.aggs.all_targets.all_t_pubs.all_pubs.buckets]

    def links(self, provider=None, s_pid=None, t_pid=None, s_publisher=None, t_publisher=None, s_pid_type=None,
              t_pid_type=None, target_Type=None, page=0):
        queries = []
        if provider:
            queries.append(self.create_dataSource_query(provider))
        if s_pid:
            queries.append(self.create_pid_query(s_pid, 'source'))
        if t_pid:
            queries.append(self.create_pid_query(t_pid, 'target'))
        if s_publisher:
            queries.append(self.create_publisher_query(s_publisher, 'source'))
        if t_publisher:
            queries.append(self.create_publisher_query(t_publisher, 'target'))
        if s_pid_type:
            queries.append(self.create_pidType_query(s_pid_type, 'source'))
        if t_pid_type:
            queries.append(self.create_pidType_query(s_pid_type, 'target'))
        if target_Type:
            queries.append(self.create_typology_query(target_Type))
        q = None
        for item in queries:
            if not q:
                q = item
            else:
                q = q & item
        search_object = Search(using=self.client, index=self.index_name).doc_type('scholix').query(q)

        return search_object[page:page + 100].execute()


    def realtionToPid(self, pid, pidType=None, datasource=None, typology=None, page=0):
        if pidType:
            query = self.create_pid_pidType_query(pidType.lower(), pid.lower())
        else:
            query = self.create_source_pid_query(pid.lower())
        filters = []
        if datasource and len(datasource):
            filters.append(self.create_dataSource_query(datasource))
        if typology and len(typology):
            filters.append(self.create_typology_query(typology))
        search_object = Search(using=self.client, index=self.index_name).doc_type('scholix').query(query)

        if len(filters):
            search_object = search_object.filter(Q('bool', must=filters))
        return search_object[page:page + 100].execute()

    def realtionToTypology(self, typology, page=0):
        search_object = Search(using=self.client, index=self.index_name).doc_type('scholix').query(
            self.create_typology_query(typology))
        return search_object[page:page + 100].execute()


dli_index = DLIESConnector()
