from flask import url_for


class BaseMenu(object):
    """
        Base menu item
    """
    def __init__(self, name, class_name=None, icon_type=None, icon_value=None, target=None):
        self.name = name
        self.class_name = class_name
        self.icon_type = icon_type
        self.icon_value = icon_value
        self.target = target

        self.parent = None
        self._children = []

    def add_child(self, menu):
        # TODO: Check if menu item is already assigned to some parent
        menu.parent = self
        self._children.append(menu)

    def get_url(self):
        raise NotImplementedError()

    def is_category(self):
        return False

    def is_active(self, view):
        for c in self._children:
            if c.is_active(view):
                return True

        return False

    def get_class_name(self):
        return self.class_name

    def get_icon_type(self):
        return self.icon_type

    def get_icon_value(self):
        return self.icon_value

    def is_visible(self):
        return True

    def is_accessible(self):
        return True

    def get_children(self):
        return [c for c in self._children if c.is_accessible() and c.is_visible()]


class MenuCategory(BaseMenu):
    """
        Menu category item.
    """
    def get_url(self):
        return None

    def is_category(self):
        return True

    def is_visible(self):
        for c in self._children:
            if c.is_visible():
                return True

        return False

    def is_accessible(self):
        for c in self._children:
            if c.is_accessible():
                return True

        return False


class MenuView(BaseMenu):
    """
        Admin view menu item
    """
    def __init__(self, name, view=None, cache=True):
        super(MenuView, self).__init__(name,
                                       class_name=view.menu_class_name,
                                       icon_type=view.menu_icon_type,
                                       icon_value=view.menu_icon_value)

        self._view = view
        self._cache = cache
        self._cached_url = None

        view.menu = self

    def get_url(self):
        if self._view is None:
            return None

        if self._cached_url:
            return self._cached_url

        url = self._view.get_url('%s.%s' % (self._view.endpoint, self._view._default_view))

        if self._cache:
            self._cached_url = url

        return url

    def is_active(self, view):
        if view == self._view:
            return True

        return super(MenuView, self).is_active(view)

    def is_visible(self):
        if self._view is None:
            return False

        return self._view.is_visible()

    def is_accessible(self):
        if self._view is None:
            return False

        return self._view.is_accessible()


class MenuLink(BaseMenu):
    """
        Link item
    """
    def __init__(self, name, url=None, endpoint=None, category=None, class_name=None,
                 icon_type=None, icon_value=None, target=None):
        super(MenuLink, self).__init__(name, class_name, icon_type, icon_value, target)

        self.category = category

        self.url = url
        self.endpoint = endpoint

    def get_url(self):
        return self.url or url_for(self.endpoint)
