# Copyright (c) 2006-2009 Nathan Binkert <nate@binkert.org>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

from __future__ import print_function
from __future__ import absolute_import

from bisect import bisect_left, bisect_right

class SortedDict(dict):
    def _get_sorted(self):
        return getattr(self, '_sorted', sorted)
    def _set_sorted(self, val):
        self._sorted = val
        self._del_keys()
    sorted = property(_get_sorted, _set_sorted)

    @property
    def _keys(self):
        try:
            return self._sorted_keys
        except AttributeError:
            _sorted_keys = self.sorted(dict.keys(self))
            self._sorted_keys = _sorted_keys
            return _sorted_keys

    def _left_eq(self, key):
        index = self._left_ge(self, key)
        if self._keys[index] != key:
            raise KeyError(key)
        return index

    def _right_eq(self, key):
        index = self._right_le(self, key)
        if self._keys[index] != key:
            raise KeyError(key)
        return index

    def _right_lt(self, key):
        index = bisect_left(self._keys, key)
        if index:
            return index - 1
        raise KeyError(key)

    def _right_le(self, key):
        index = bisect_right(self._keys, key)
        if index:
            return index - 1
        raise KeyError(key)

    def _left_gt(self, key):
        index = bisect_right(self._keys, key)
        if index != len(self._keys):
            return index
        raise KeyError(key)

    def _left_ge(self, key):
        index = bisect_left(self._keys, key)
        if index != len(self._keys):
            return index
        raise KeyError(key)

    def _del_keys(self):
        try:
            del self._sorted_keys
        except AttributeError:
            pass

    def __repr__(self):
        return 'SortedDict({%s})' % ', '.join('%r: %r' % item
                                              for item in self.items())
    def __setitem__(self, key, item):
        dict.__setitem__(self, key, item)
        self._del_keys()

    def __delitem__(self, key):
        dict.__delitem__(self, key)
        self._del_keys()

    def clear(self):
        self.data.clear()
        self._del_keys()

    def copy(self):
        t = type(self)
        return t(self)

    def keys(self):
        return self._keys

    def values(self):
        for k in self._keys:
            yield self[k]

    def items(self):
        for k in self._keys:
            yield k, self[k]

    def keyrange(self, start=None, end=None, inclusive=False):
        if start is not None:
            start = self._left_ge(start)

        if end is not None:
            if inclusive:
                end = self._right_le(end)
            else:
                end = self._right_lt(end)

        return iter(self._keys[start:end+1])

    def valuerange(self, *args, **kwargs):
        for k in self.keyrange(*args, **kwargs):
            yield self[k]

    def itemrange(self, *args, **kwargs):
        for k in self.keyrange(*args, **kwargs):
            yield k, self[k]

    def update(self, *args, **kwargs):
        dict.update(self, *args, **kwargs)
        self._del_keys()

    def setdefault(self, key, _failobj=None):
        try:
            return self[key]
        except KeyError:
            self[key] = _failobj

    def pop(self, key, *args):
        try:
            dict.pop(self, key)
            self._del_keys()
        except KeyError:
            if not args:
                raise
            return args[0]

    def popitem(self):
        try:
            key = self._keys[0]
            self._del_keys()
        except IndexError:
            raise KeyError('popitem(): dictionary is empty')
        else:
            return key, dict.pop(self, key)

    @classmethod
    def fromkeys(cls, seq, value=None):
        d = cls()
        for key in seq:
            d[key] = value
        return d

if __name__ == '__main__':
    def display(d):
        print(d)
        print(list(d.keys()))
        print(list(d.keys()))
        print(list(d.values()))
        print(list(d.values()))
        print(list(d.items()))
        print(list(d.items()))

    d = SortedDict(x=24,e=5,j=4,b=2,z=26,d=4)
    display(d)

    print('popitem', d.popitem())
    display(d)

    print('pop j')
    d.pop('j')
    display(d)

    d.setdefault('a', 1)
    d.setdefault('g', 7)
    d.setdefault('_')
    display(d)

    d.update({'b' : 2, 'h' : 8})
    display(d)

    del d['x']
    display(d)
    d['y'] = 26
    display(d)

    print(repr(d))

    print(d.copy())

    for k,v in d.itemrange('d', 'z', inclusive=True):
        print(k, v)
