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

        self.parent = None
        self._children = []
        self.admin = None

    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):
        super().__init__(name, class_name=view.menu_class_name,
                         icon_type=view.menu_icon_type,
                         icon_value=view.menu_icon_value)

        self._view = view
        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
        # TODO: rethink variable name
        _d = self._view._default_view
        _u = '%s.%s' % (self._view.endpoint, _d)
        self._cached_url = self._view.get_url(_u)
        return self._cached_url

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

        return super().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):
        super().__init__(name, class_name, icon_type, icon_value)

        self.category = category

        self.url = url
        self.endpoint = endpoint

    def get_url(self):
        # TODO: fix url_for function
        router = self.admin.app.router
        return self.url or router[self.endpoint].url()

add menu objects