import os
import sys
import json
import datetime

runPath = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(runPath, ".."))

import redis

from settings.settings import Settings


class Cache():
    def __init__(self):
        st = Settings()
        self.settings = st.load()
        self.host = self.settings['redis_host']
        self.port = self.settings['redis_port']
        self.db = redis.StrictRedis(
            host=self.host,
            port=self.port,
            charset="utf-8",
            decode_responses=True
        )
        self.collection_tasks = self.settings['redis_collection_name'] + ':' + self.settings['redis_collection_tasks']
        self.collection_log = self.settings['redis_collection_name'] + ':' + self.settings['redis_collection_log']
        self.collection_cve = self.settings['redis_collection_name'] + ':' + self.settings['redis_collection_cve']
        self.collection_cpe = self.settings['redis_collection_name'] + ':' + self.settings['redis_collection_cpe']
        self.collection_cwe = self.settings['redis_collection_name'] + ':' + self.settings['redis_collection_cwe']
        self.collection_cpeother = self.settings['redis_collection_name'] + ':' + self.settings['redis_collection_cpeother']
        self.collection_whitelist = self.settings['redis_collection_name'] + ':' + self.settings['redis_collection_whitelist']
        self.collection_blacklist = self.settings['redis_collection_name'] + ':' + self.settings['redis_collection_blacklist']
        self.collection_info = self.settings['redis_collection_name'] + ':' + self.settings['redis_collection_info']
        self.collection_ranking = self.settings['redis_collection_name'] + ':' + self.settings['redis_collection_ranking']
        self.collection_via4 = self.settings['redis_collection_name'] + ':' + self.settings['redis_collection_via4']
        self.collection_capec = self.settings['redis_collection_name'] + ':' + self.settings['redis_collection_capec']
        self.complete_flag = self.settings['redis_complete_flag']

    @staticmethod
    def correct_dict(element):
        for key in element.keys():
            if type(element[key]) == type(datetime.datetime.now()):
                element[key] = element[key].strftime('%Y-%m-%dT%H:%M:%S.%f%zZ')
            if type(element[key]) == type('s'):
                element[key] = element[key].replace('"', '')

    def correct_types(self, task):
        if isinstance(task['data'], list):
            for every in task['data']:
                if isinstance(every, dict):
                    every = self.correct_dict(every)
        if isinstance(task['data'], dict):
            task['data'] = self.correct_dict(task['data'])
        if type(task['data']) == type(datetime.datetime.now()):
            task['data'] = task['data'].strftime('%Y-%m-%dT%H:%M:%S.%f%zZ')
        return task

    def connected(self):
        try:
            self.db.get(None)
        except (redis.ConnectionError, redis.BusyLoadingError):
            return False
        return True

    def set_complete_flag(self):
        if self.connected():
            return self.db.set(self.complete_flag, True)
        return None

    def get_complete_flag(self):
        if self.connected():
            return self.db.get(self.complete_flag)
        return None

    def drop_complete_flag(self):
        if self.connected():
            return self.db.set(self.complete_flag, False)
        return None

    def empty_tasks(self):
        if self.connected():
            return self.db.llen(self.collection_tasks) == 0
        return True

    def get_last_task(self):
        if self.connected():
            raw_task = self.db.lrange(
                self.collection_tasks,
                0,
                0
            )
            raw_task_ = raw_task[0]
            return raw_task_
        return None

    def delete_last_task(self):
        if self.connected():
            return self.db.lpop(
                self.collection_tasks
            )
        return None

    def clear_tasks_collection(self):
        if self.connected():
            return self.db.delete(
                self.collection_tasks
            )
        return None

    def clear_log_collection(self):
        if self.connected():
            return self.db.delete(
                self.collection_log
            )
        return None

    def push_item(self, item, collection):
        if self.connected():
            return self.db.rpush(
                collection,
                json.dumps(item)
            )
        return None

    def pop_item(self, collection):
        if self.connected():
            return json.loads(self.db.lpop(collection))
        return None

    def push_task(self, task):
        if self.connected():
            task = self.correct_types(task)
            self.db.rpush(
                self.collection_tasks,
                task
            )
        return None

    def pop_task(self):
        if self.connected():
            if self.db.llen(self.collection_tasks) > 0:
                return json.loads(
                    self.db.lpop(
                        self.collection_tasks
                ))
        return None

    def set_item(self, collection, item):
        if self.connected():
            return self.db.set(collection, item)
        return None

    def get_item(self, collection):
        if self.connected():
            return self.db.get(collection)
        return None

    def replicate(self, collection, data):
        if self.connected():
            pass
