# coding: utf-8

from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

import logging
from cached_property import cached_property

from saas.library.python.nanny_rest.tickets_integration.tickets_integration_rule import TicketsIntegrationRule
from saas.library.python.nanny_rest.tickets_integration.instancectl_release_rule import InstancectlReleaseRule


class TicketsIntegration(object):
    LOGGER = logging.getLogger(__name__)

    def __init__(self, service_release_tickets_enabled, service_release_rules, instancectl_release_rule=None,
                 gencfg_release_rule=None, docker_release_rule=None):
        self.service_release_tickets_enabled = service_release_tickets_enabled
        self.gencfg_release_rule = gencfg_release_rule
        self.docker_release_rule = docker_release_rule

        if service_release_rules and isinstance(service_release_rules[0], TicketsIntegrationRule):
            self.service_release_rules = service_release_rules
        else:
            self.service_release_rules = [TicketsIntegrationRule(**rule) for rule in service_release_rules]

        if instancectl_release_rule is not None:
            if isinstance(instancectl_release_rule, InstancectlReleaseRule):
                self.instancectl_release_rule = instancectl_release_rule
            else:
                self.instancectl_release_rule = InstancectlReleaseRule(**instancectl_release_rule)
        else:
            self.instancectl_release_rule = InstancectlReleaseRule()

    def dict(self):
        full = {
            'service_release_tickets_enabled': self.service_release_tickets_enabled,
            'gencfg_release_rule': self.gencfg_release_rule,
            'docker_release_rule': self.docker_release_rule,
            'instancectl_release_rule': self.instancectl_release_rule.dict(),
            'service_release_rules': [rule.dict() for rule in self.service_release_rules]
        }
        return {k: v for k, v in full.items() if v is not None}

    @cached_property
    def hash_rule_dict(self):
        return {rule.__hash__(): rule for rule in self.service_release_rules}

    def add_rule(self, new_rule, replace_existing=False):
        rule_hash = new_rule.__hash__()
        if rule_hash in self.hash_rule_dict:
            old_rule = self.hash_rule_dict[rule_hash]
            if replace_existing:
                self.LOGGER.warning('Attention! Old rule %s will be replaced with %s', old_rule, new_rule)
                self.service_release_rules.remove(old_rule)
            else:
                raise DuplicateRuleException(old_rule, new_rule)

        self.service_release_rules.append(new_rule)
        del self.__dict__['hash_rule_dict']

    def ensure_rule(self, rule):
        try:
            self.add_rule(rule)
        except DuplicateRuleException as exc:
            self.LOGGER.warning('Possibly duplicate rules: %s vs %s', exc.old, exc.new)
            if exc.old != exc.new:
                raise DifferentRuleException(exc.old, exc.new)


class DuplicateRuleException(Exception):
    def __init__(self, old, new):
        self.old = old
        self.new = new

    def __str__(self):
        return 'Duplicated rules: {old} vs {new}'.format(old=self.old, new=self.new)


class DifferentRuleException(DuplicateRuleException):
    def __str__(self):
        return 'Not quite same rule already exist: {old} vs {new}'.format(old=self.old, new=self.new)
