import configuration as config
import json
import logging
from datetime import datetime

from pymongo import MongoClient, errors


def get_current_time():
    return datetime.now()


class TagParser:

    def __init__(self, site_data):
        self.site_json = site_data
        self.tags_json = dict()
        self.site_name = self.site_json['site_name']
        self.site_id = self.site_json['site_id']
        self.tags_json[self.site_name] = {"tags": {}}
        self.tags_json_pointer = self.tags_json[self.site_name]

    def get_tags(self):
        """
        driver module
        :return:
        """
        logging.info('Started parsing at : ', get_current_time())

        self.get_site_tags()
        logging.info('Finished parsing site level tags at : ', get_current_time())

        self.get_dept_tags()
        logging.info('Finished parsing department level tags at : ', get_current_time())

        self.get_line_tags()
        logging.info('Finished parsing line level tags at : ', get_current_time())

        self.get_equipment_tags()
        logging.info('Finished parsing equipment level tags at : ', get_current_time())

    def save_tags(self):
        """
        Module to save the tags as JSON file.
        :return:
        """
        file_name = f"site-tags/{self.site_name}-tags.json"
        with open(file_name, 'w') as fileObject:
            fileObject.write(json.dumps(self.tags_json))

    def get_dept_name(self, dept_id):
        """
        Module to return department name for the given department id.
        :param dept_id:
        :return: dept_name
        """
        for department in self.site_json['dept']:
            if dept_id == department['dept_id']:
                return department['dept_name']

    def get_line_name(self, line_id):
        """
        Module to return line name for the given line id.
        :param line_id:
        :return: line_name
        """
        for line in self.site_json['line']:
            if line_id == line['line_id']:
                return line['line_name']

    def get_site_tags(self):
        """
        Module to get all the site level tags.
        :return:
        """
        if self.site_json['site_info'].get('tags'):

            site_pointer = self.tags_json_pointer['tags']

            for tag in self.site_json['site_info']['tags']:
                if len(tag['value']) != 0:
                    if tag['label'] not in site_pointer.keys():
                        site_pointer[tag['label']] = ''
                    site_pointer[tag['label']] = f"{self.site_id}${tag['value']}"

        else:
            logging.warning('No Tags are available at site level.')

    def get_dept_tags(self):
        """
        Module to get all the department level tags.
        :return:
        """
        if self.site_json.get('dept'):
            for department in self.site_json['dept']:
                department_name = department['dept_name']
                department_id = department['dept_id']

                self.tags_json_pointer[department_name] = {"tags": {}}
                department_pointer = self.tags_json_pointer[department_name]['tags']

                if department.get('tags'):
                    for tag in department['tags']:
                        if len(tag['value']) != 0:
                            if tag['label'] not in department_pointer.keys():
                                department_pointer[tag['label']] = ''
                            department_pointer[
                                tag['label']] = f"{self.site_id}${department_id}${tag['value']}"

        else:
            logging.warning('No Tags available at department level.')

    def get_line_tags(self):
        """
        Module to get all the line level tags.
        :return:
        """
        if self.site_json.get('line') and self.site_json.get('dept'):
            """
            Case : if the site has department.
            """
            for line in self.site_json['line']:
                department_name = self.get_dept_name(line['dept_id'])
                line_name = line['line_name']
                line_id = line['line_id']
                department_id = line['dept_id']

                self.tags_json_pointer[department_name][line_name] = {"tags": {}}
                line_pointer = self.tags_json_pointer[department_name][line_name]['tags']

                if line.get('tags'):
                    for tag in line['tags']:
                        if len(tag['value']) != 0:
                            if tag['label'] not in line_pointer.keys():
                                line_pointer[tag['label']] = ''
                            line_pointer[
                                tag['label']] = f"{self.site_id}${department_id}${line_id}${tag['value']}"

        elif self.site_json.get('line'):
            """
            Case : if the site has line alone.
            """
            logging.warning('Writing line tags without department tag.')
            for line in self.site_json['line']:
                line_name = line['line_name']
                line_id = line['line_id']

                self.tags_json_pointer[line_name] = {"tags": {}}
                line_pointer = self.tags_json_pointer[line_name]['tags']

                if line.get('tags'):
                    for tag in line['tags']:
                        if len(tag['value']) != 0:
                            if tag['label'] not in line_pointer.keys():
                                line_pointer[tag['label']] = ''
                            line_pointer[
                                tag['label']] = f"{self.site_id}${line_id}${tag['value']}"

    def get_equipment_tags(self):
        """
        Module to get all equipment level tags.
        :return:
        """
        if self.site_json.get('equipment') and self.site_json.get('dept') and self.site_json.get('line'):
            """
            Case : if the site has department and line.
            """
            for equipment in self.site_json['equipment']:
                equipment_id = equipment['equipment_id']
                equipment_name = equipment['equipment_name']
                line_id = equipment['line_id']
                line_name = self.get_line_name(equipment['line_id'])
                department_id = equipment['dept_id']
                department_name = self.get_dept_name(equipment['dept_id'])

                self.tags_json_pointer[department_name][line_name][equipment_name] = {"tags": {}}
                equipment_pointer = self.tags_json_pointer[department_name][line_name][equipment_name]['tags']

                if equipment.get('tags'):
                    for tag in equipment['tags']:
                        if len(tag['value']) != 0:
                            if tag['label'] not in equipment_pointer.keys():
                                equipment_pointer[tag['label']] = ''
                            equipment_pointer[tag['label']] = \
                                f"{self.site_id}${department_id}${line_id}${equipment_id}${tag['value']}"

        elif self.site_json.get('equipment') and self.site_json.get('line'):
            """
            Case : if the site has line and not department.
            """
            logging.warning('Writing equipment tags without department tag.')
            for equipment in self.site_json['equipment']:
                if equipment.get('tags'):
                    equipment_id = equipment['equipment_id']
                    equipment_name = equipment['equipment_name']
                    line_id = equipment['line_id']
                    line_name = self.get_line_name(equipment['line_id'])

                    self.tags_json_pointer[line_name][equipment_name] = {"tags": {}}
                    equipment_pointer = self.tags_json_pointer[line_name][equipment_name]['tags']

                    if equipment.get('tags'):
                        for tag in equipment['tags']:
                            if len(tag['value']) != 0:
                                if tag['label'] not in \
                                        equipment_pointer.keys():
                                    equipment_pointer[tag['label']] = ''
                                equipment_pointer[tag['label']] = \
                                    f"{self.site_id}${line_id}${equipment_id}${tag['value']}"

        elif self.site_json.get('equipment') and self.site_json.get('dept'):
            """
            Case : if the site has department and not line.
            """
            logging.warning('Writing equipment tags without line tag.')
            for equipment in self.site_json['equipment']:
                equipment_id = equipment['equipment_id']
                equipment_name = equipment['equipment_name']
                department_id = equipment['dept_id']
                department_name = self.get_dept_name(equipment['dept_id'])

                self.tags_json_pointer[department_name][equipment_name] = {"tags": {}}
                equipment_pointer = self.tags_json_pointer[department_name][equipment_name]['tags']

                if equipment.get('tags'):
                    for tag in equipment['tags']:
                        if len(tag['value']) != 0:
                            if tag['label'] not in equipment_pointer.keys():
                                equipment_pointer[tag['label']] = ''
                            equipment_pointer[tag['label']] = \
                                f"{self.site_id}${department_id}${equipment_id}${tag['value']}"

        elif self.site_json.get('equipment'):
            """
            Case : if the site has equipments alone.
            """
            logging.warning('Writing equipment tags without department tag and line tag.')
            for equipment in self.site_json['equipment']:
                equipment_id = equipment['equipment_id']
                equipment_name = equipment['equipment_name']

                self.tags_json_pointer[equipment_name] = {"tags": {}}
                equipment_pointer = self.tags_json_pointer[equipment_name]['tags']

                if equipment.get('tags'):
                    for tag in equipment['tags']:
                        if len(tag['value']) != 0:
                            if tag['label'] not in equipment_pointer.keys():
                                equipment_pointer[tag['label']] = ''
                            equipment_pointer[tag['label']] = \
                                f"{self.site_id}${equipment_id}${tag['value']}"


if __name__ == '__main__':

    try:
        client = MongoClient(config.db_url, config.port)
        client.server_info()

        site_file = client[config.db_name][config.collection_name]

        for site in site_file.find({'site_id': config.site_id}):
            tags = TagParser(site)
            tags.get_tags()
            tags.save_tags()

    except errors.ServerSelectionTimeoutError:
        logging.critical('No Server found the given ip and port.')

    # f = open('orient.json', 'r')
    # tags = TagParser(json.loads(f.read()))
    # tags.get_tags()
    # tags.save_tags()
