# coding: utf-8

import typing
from collections import OrderedDict

from django.utils.translation import gettext_lazy as _


class Enum(object):
    keys: typing.Mapping

    @classmethod
    def get_by_key(cls, key):
        for item, item_key in cls.keys.items():
            if key == item_key:
                return item
        raise KeyError


class QS(Enum):
    DRAFT = 150
    BIDDING = 210
    REVIEW = 220
    CHECKOUT = 230
    SHIPPED = 240
    CLOSED = 250

    keys = OrderedDict(
        [
            (DRAFT, 'draft'),
            (BIDDING, 'bidding'),
            (REVIEW, 'review'),
            (CHECKOUT, 'checkout'),
            (SHIPPED, 'shipped'),
            (CLOSED, 'closed'),
        ]
    )

    i18n = OrderedDict(
        [
            (DRAFT, _('QUOTE_STATUS::DRAFT')),
            (BIDDING, _('QUOTE_STATUS::BIDDING')),
            (REVIEW, _('QUOTE_STATUS::REVIEW')),
            (CHECKOUT, _('QUOTE_STATUS::CHECKOUT')),
            (SHIPPED, _('QUOTE_STATUS::SHIPPED')),
            (CLOSED, _('QUOTE_STATUS::CLOSED')),
        ]
    )


class ES(QS):
    i18n = OrderedDict(
        [
            (QS.DRAFT, _('ENQUIRY_STATUS::DRAFT')),
            (QS.BIDDING, _('ENQUIRY_STATUS::BIDDING')),
            (QS.REVIEW, _('ENQUIRY_STATUS::REVIEW')),
            (QS.CHECKOUT, _('ENQUIRY_STATUS::CHECKOUT')),
            (QS.SHIPPED, _('ENQUIRY_STATUS::SHIPPED')),
            (QS.CLOSED, _('ENQUIRY_STATUS::CLOSED')),
        ]
    )


class QR(Enum):

    NONE = 1000
    DELIVERED = 1100
    DECLINED = 1300
    IGNORED = 1400
    CANCELLED = 1500

    keys = OrderedDict(
        [
            (NONE, 'none'),
            (DELIVERED, 'delivered'),
            (DECLINED, 'declined'),
            (IGNORED, 'ignored'),
            (CANCELLED, 'cancelled'),
        ]
    )

    i18n = OrderedDict(
        [
            (NONE, ''),
            (DELIVERED, _('QUOTE_REASON::DELIVERED')),
            (DECLINED, _('QUOTE_REASON::DECLINED')),
            (IGNORED, _('QUOTE_REASON::IGNORED')),
            (CANCELLED, _('QUOTE_REASON::CANCELLED')),
        ]
    )


class ER(QR):

    i18n = OrderedDict(
        [
            (QR.NONE, ''),
            (QR.DELIVERED, _('ENQUIRY_REASON::DELIVERED')),
            (QR.DECLINED, _('ENQUIRY_REASON::DECLINED')),
            (QR.IGNORED, _('ENQUIRY_REASON::IGNORED')),
            (QR.CANCELLED, _('ENQUIRY_REASON::CANCELLED')),
        ]
    )


class PRIORITY(Enum):
    MINOR = 100
    LOW = 200
    NORMAL = 300
    CRITICAL = 400
    BLOCKER = 500

    keys = OrderedDict(
        [
            (MINOR, 'minor'),
            (LOW, 'low'),
            (NORMAL, 'normal'),
            (CRITICAL, 'critical'),
            (BLOCKER, 'blocker'),
        ]
    )

    i18n = OrderedDict(
        [
            (MINOR, _('ENQUIRY_PRIORITY::MINOR')),
            (LOW, _('ENQUIRY_PRIORITY::LOW')),
            (NORMAL, _('ENQUIRY_PRIORITY::NORMAL')),
            (CRITICAL, _('ENQUIRY_PRIORITY::CRITICAL')),
            (BLOCKER, _('ENQUIRY_PRIORITY::BLOCKER')),
        ]
    )

    tracker = {'minor': LOW, 'trivial': MINOR}

    @classmethod
    def from_tracker(cls, key):
        try:
            return cls.tracker[key]
        except KeyError:
            return cls.get_by_key(key)


class RISK(Enum):
    UNKNOWN = 100
    FETCHING = 200
    LOW = 300
    MODERATE = 400
    HIGH = 500

    keys = OrderedDict(
        [
            (UNKNOWN, 'unknown'),
            (FETCHING, 'fetching'),
            (LOW, 'low'),
            (MODERATE, 'moderate'),
            (HIGH, 'high'),
        ]
    )

    i18n = OrderedDict(
        [
            (UNKNOWN, _('RISK::UNKNOWN')),
            (FETCHING, _('RISK::FETCHING')),
            (LOW, _('RISK::LOW')),
            (MODERATE, _('RISK::MODERATE')),
            (HIGH, _('RISK::HIGH')),
        ]
    )


class LINK(Enum):
    PROCU = 100
    TRACKER = 200

    keys = OrderedDict([(PROCU, 'procu'), (TRACKER, 'tracker')])

    i18n = OrderedDict(
        [(PROCU, _('LINK::PROCU')), (TRACKER, _('LINK::TRACKER'))]
    )


class ACCESS_SOURCE(Enum):
    TYPE = 100
    CFO = 200
    AUTHOR = 300
    ASSIGNEE = 400
    ACCESS = 500

    keys = OrderedDict(
        [
            (TYPE, 'type'),
            (CFO, 'cfo'),
            (AUTHOR, 'author'),
            (ASSIGNEE, 'assignee'),
            (ACCESS, 'access'),
        ]
    )

    i18n = OrderedDict(
        [
            (TYPE, _('ACCESS_SOURCE::TYPE')),
            (CFO, _('ACCESS_SOURCE::CFO')),
            (AUTHOR, _('ACCESS_SOURCE::AUTHOR')),
            (ASSIGNEE, _('ACCESS_SOURCE::ASSIGNEE')),
            (ACCESS, _('ACCESS_SOURCE::ACCESS')),
        ]
    )


class TAX(Enum):
    INCLUDED = 100
    EXCLUDED = 200
    UNTAXED = 300

    keys = OrderedDict(
        [(INCLUDED, 'included'), (EXCLUDED, 'excluded'), (UNTAXED, 'untaxed')]
    )

    i18n = OrderedDict(
        [
            (INCLUDED, _('TAX::INCLUDED')),
            (EXCLUDED, _('TAX::EXCLUDED')),
            (UNTAXED, _('TAX::UNTAXED')),
        ]
    )


class TAX_COMMON(TAX):
    i18n = OrderedDict(
        [
            (TAX.INCLUDED, _('TAX_COMMON::INCLUDED')),
            (TAX.EXCLUDED, _('TAX_COMMON::EXCLUDED')),
            (TAX.UNTAXED, _('TAX_COMMON::UNTAXED')),
        ]
    )


class PRICE(Enum):
    UNIT = 100
    TOTAL = 200

    keys = OrderedDict([(UNIT, 'unit'), (TOTAL, 'total')])

    i18n = OrderedDict([(UNIT, _('PRICE::UNIT')), (TOTAL, _('PRICE::TOTAL'))])


class PRICE_COMMON(PRICE):
    i18n = OrderedDict(
        [
            (PRICE.UNIT, _('PRICE_COMMON::UNIT')),
            (PRICE.TOTAL, _('PRICE_COMMON::TOTAL')),
        ]
    )


class SavingNote(Enum):
    NONE = 100
    CLOSED_NOT_DELIVERED = 200
    NO_WINNERS = 300
    MULTIPLE_WINNERS = 400
    PARTIAL_OFFERS = 500
    NON_TRIVIAL_WINNER = 600
    LESS_THAN_TWO_OFFERS = 700
    INVALID_PRICES = 800
    NEGATIVE_SAVING = 900

    keys = OrderedDict(
        [
            (NONE, 'none'),
            (CLOSED_NOT_DELIVERED, 'closed_not_delivered'),
            (NO_WINNERS, 'no_winners'),
            (MULTIPLE_WINNERS, 'multiple_winners'),
            (PARTIAL_OFFERS, 'partial_offers'),
            (NON_TRIVIAL_WINNER, 'non_trivial_winner'),
            (LESS_THAN_TWO_OFFERS, 'less_than_two_offers'),
            (INVALID_PRICES, 'invalid_prices'),
            (NEGATIVE_SAVING, 'negative_saving'),
        ]
    )

    i18n = OrderedDict(
        [
            (NONE, ''),
            (CLOSED_NOT_DELIVERED, _('SAVING_NOTE::CLOSED_NOT_DELIVERED')),
            (NO_WINNERS, _('SAVING_NOTE::NO_WINNERS')),
            (MULTIPLE_WINNERS, _('SAVING_NOTE::MULTIPLE_WINNERS')),
            (PARTIAL_OFFERS, _('SAVING_NOTE::PARTIAL_OFFERS')),
            (NON_TRIVIAL_WINNER, _('SAVING_NOTE::NON_TRIVIAL_WINNER')),
            (LESS_THAN_TWO_OFFERS, _('SAVING_NOTE::LESS_THAN_TWO_OFFERS')),
            (INVALID_PRICES, _('SAVING_NOTE::INVALID_PRICES')),
            (NEGATIVE_SAVING, _('SAVING_NOTE::NEGATIVE_SAVING')),
        ]
    )


class STATE(Enum):
    ACTIVE = 100
    NEEDINFO = 200

    keys = OrderedDict([(ACTIVE, 'active'), (NEEDINFO, 'needinfo')])

    i18n = OrderedDict(
        [(ACTIVE, _('STATE::ACTIVE')), (NEEDINFO, _('STATE::NEEDINFO'))]
    )
