# Path: feature_toggle/exceptions.py
# class FeatureToggleAttributeAlreadyExists(Exception):
#     """
#     When trying to create a toggle attribute that already exists.
#     """
# 
#     def __init__(self, **kwargs):
#         msg = 'FeatureToggleAttribute already exists with data: {d}'.format(d=kwargs)
#         super(FeatureToggleAttributeAlreadyExists, self).__init__(self, msg)
# 
# Path: feature_toggle/constants.py
# class Attribute(Container):
# class Environment(Container):
#     def __init__(self):
#     def __init__(self):
# 
# Path: feature_toggle/utilities.py
# def django_model_choices_from_iterable(iterable):
#     try:
#         return tuple((x, x) for x in iterable)
#     except TypeError:
#         raise ValueError("must be an iterable")
# 
# def make_meanigful_id(string, length=10, cast_uppercase=True):
#     _short = meaningful_shorten(string, length=int(math.ceil(length * 0.4)))
#     _hash = cheap_hash(string + str(time.time()), length=int(math.ceil(length * 0.6)))
#     _id = '{s}{h}'.format(s=_short, h=_hash)[:length]
#     return _id.upper() if cast_uppercase else _id


from django.conf import settings
from django.db import models
from djutil.models import TimeStampedModel
from feature_toggle.exceptions import FeatureToggleAttributeAlreadyExists
from .constants import Environments, Attributes
from .utilities import django_model_choices_from_iterable, make_meanigful_id


ENV_CHOICES = django_model_choices_from_iterable(Environments)
ATTRIB_CHOICES = django_model_choices_from_iterable(Attributes)

ATTRIB_KEY_MAX_LENGTH = getattr(settings, 'FEATURE_TOGGLE_ATTRIB_KEY_MAX_LEN', 100)
ATTRIB_VAL_MAX_LENGTH = getattr(settings, 'FEATURE_TOGGLE_ATTRIB_VAL_MAX_LEN', 1000)


class FeatureToggle(TimeStampedModel):
    uid = models.CharField(max_length=20)
    name = models.CharField(max_length=20)
    environment = models.CharField(max_length=50, choices=ENV_CHOICES)
    is_active = models.BooleanField(default=True)
    start_date_time = models.DateTimeField(auto_now_add=True)
    end_date_time = models.DateTimeField(auto_now_add=True)  # todo: add 3 months from now by default
    time_bomb = models.BooleanField(default=False)

    class Meta:
        unique_together = (('name', 'environment'), ('uid',))
        managed = True

    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
        if not self.uid:
            self.uid = make_meanigful_id(self.name, length=5)
        super().save(force_insert, force_update, using, update_fields)

    def set_attribute(self, key, value=None, update_if_existing=True):
        attrib, created = self.attributes.get_or_create(key=key)
        if not created and not update_if_existing:

# Path: feature_toggle/exceptions.py
# class FeatureToggleAttributeAlreadyExists(Exception):
#     """
#     When trying to create a toggle attribute that already exists.
#     """
# 
#     def __init__(self, **kwargs):
#         msg = 'FeatureToggleAttribute already exists with data: {d}'.format(d=kwargs)
#         super(FeatureToggleAttributeAlreadyExists, self).__init__(self, msg)
# 
# Path: feature_toggle/constants.py
# class Attribute(Container):
# class Environment(Container):
#     def __init__(self):
#     def __init__(self):
# 
# Path: feature_toggle/utilities.py
# def django_model_choices_from_iterable(iterable):
#     try:
#         return tuple((x, x) for x in iterable)
#     except TypeError:
#         raise ValueError("must be an iterable")
# 
# def make_meanigful_id(string, length=10, cast_uppercase=True):
#     _short = meaningful_shorten(string, length=int(math.ceil(length * 0.4)))
#     _hash = cheap_hash(string + str(time.time()), length=int(math.ceil(length * 0.6)))
#     _id = '{s}{h}'.format(s=_short, h=_hash)[:length]
#     return _id.upper() if cast_uppercase else _id


# Path: feature_toggle/models.py
from django.conf import settings
from django.db import models
from djutil.models import TimeStampedModel
from feature_toggle.exceptions import FeatureToggleAttributeAlreadyExists
from .constants import Environments, Attributes
from .utilities import django_model_choices_from_iterable, make_meanigful_id



ENV_CHOICES = django_model_choices_from_iterable(Environments)
ATTRIB_CHOICES = django_model_choices_from_iterable(Attributes)

ATTRIB_KEY_MAX_LENGTH = getattr(settings, 'FEATURE_TOGGLE_ATTRIB_KEY_MAX_LEN', 100)
ATTRIB_VAL_MAX_LENGTH = getattr(settings, 'FEATURE_TOGGLE_ATTRIB_VAL_MAX_LEN', 1000)


class FeatureToggle(TimeStampedModel):
    uid = models.CharField(max_length=20)
    name = models.CharField(max_length=20)
    environment = models.CharField(max_length=50, choices=ENV_CHOICES)
    is_active = models.BooleanField(default=True)
    start_date_time = models.DateTimeField(auto_now_add=True)
    end_date_time = models.DateTimeField(auto_now_add=True)  # todo: add 3 months from now by default
    time_bomb = models.BooleanField(default=False)

    class Meta:
        unique_together = (('name', 'environment'), ('uid',))
        managed = True

    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
        if not self.uid:
            self.uid = make_meanigful_id(self.name, length=5)
        super().save(force_insert, force_update, using, update_fields)

    def set_attribute(self, key, value=None, update_if_existing=True):
        attrib, created = self.attributes.get_or_create(key=key)
        if not created and not update_if_existing:

            raise FeatureToggleAttributeAlreadyExists(**dict(key=key))