from collections import OrderedDict as dict
import pandas as pd
import numpy as np

__all__ = ['CatalogueGroup', 
           'Catalogue']

class CatalogueGroup(object):
    """ CatalogueGroup class.
    
    This is basically a dictionary used by Catalogue class. The idea is 
    to be able to store different types of data inside the main catalogue 
    instance. 

    Since it's a Sorted Dictionary all the data remain in order as they
    are inserted, and the performances are better than standard lists.

    CatalogueGroup class store similar items or relationship. This collections of items
    could be seen as a group. The group could be defined by the type
    of the class, name, tag or anything. It's will depend on the needs
    and this will be managed for the main catalog class.

    This class will also manage the callbacks so the catalogue will be able
    to know whether an element has been added, removed or modified.

    Each CatalogueGroup has a (name) and a function (callback) when action is 
    performed inside the dictionary.

    The function callback need to be implemented as follows:
        def callback_name(id, key, option):
 
    Where:
        name: name of the current GRoup or dictionary
        key: the item that has been, added, removed or modifed
        option: action performed added, removed or modifed
    """
    ADDED = 0
    REMOVED = 1
    MODIFIED = 2

    @property
    def items(self):
        return self._items

    @property
    def name(self):
        return self._name

    def __init__(self, name, callback=None):
        """ Initialize all the variables
        """
        self._name = name
        self._items = dict()
        self._callback = callback

    def _notify(self, key, option):
        """Notify when a new element has been added.  
        """
        if self._callback is not None:
            self._callback(self._name, key, option)

    def __setitem__(self, key, value):
        """Add a new items into the items list.
        """
        if key in self._items:
            option = CatalogueGroup.MODIFIED
        else:
            option = CatalogueGroup.ADDED
        #Set the current item (added or modified)
        self._items[key] = value
        # Finally callback to the function
        self._notify(key, option)

    def __delitem__(self, key):
         """ Delete current item for the list
         """
         del self._items[key] 