from collections import OrderedDict

from flyers.collections import Pair


class Multimap(dict):
    def __setitem__(self, key, value):
        if key not in self:
            dict.__setitem__(self, key, [value])
        else:
            self[key].append(value)


class SortedOrderedDict(object):

    def __init__(self, other=()):
        self.od = OrderedDict(other)

    def __setitem__(self, field, value):
        self.od[field] = value

    def __getitem__(self, field):
        return self.od[field]

    def __delitem__(self, field):
        del self.od[field]

    def __contains__(self, field) -> bool:
        return field in self.od

    def keys(self) -> list:
        return list(self.od.keys())

    def values(self) -> list:
        return list(self.od.values())

    def items(self) -> list:
        return [Pair(each[0], each[1]) for each in self.od.items()]

    def sort_by_key(self):
        self.sort(comparator=lambda pair: pair.key)

    def sort_by_value(self):
        self.sort(comparator=lambda pair: pair.val)

    def sort(self, comparator):
        self.od = OrderedDict(sorted(self.od.items(), key=lambda x: comparator(Pair(x[0], x[1]))))

    def __str__(self):
        return self.od.__str__()

    def __repr__(self):
        return self.od.__repr__()


def get_or_none(d: dict, func):
    try:
        return func(d)
    except KeyError:
        return None


def get_or_default(d: dict, k: str, default_val):
    if k not in d:
        return default_val
    return d[k]
