from django.urls import include, path


class URLPatterns:
    def __init__(self):
        self.namespace_patterns = None
        self._namespaces = []
        self._patterns = []
        self._urlpatterns = None

    def namespace(self, url_path, namespace, parent=None):
        self._namespaces.append(
            {"path": url_path, "parent": parent, "namespace": namespace}
        )

    def patterns(self, namespace, *new_patterns):
        self._patterns.append({"namespace": namespace, "urlpatterns": new_patterns})

    def single_pattern(self, url_path, namespace, parent, view):
        self.namespace(url_path, namespace, parent)
        self.patterns(":".join((parent, namespace)), path("", view, name="index"))

    def get_child_patterns(self, parent):
        prefix = "%s:" % parent if parent else ""

        namespace_urlpatterns = self.namespace_patterns.get(parent, [])
        for namespace in self._namespaces:
            if namespace["parent"] == parent:
                prefixed_namespace = prefix + namespace["namespace"]
                child_patterns = self.get_child_patterns(prefixed_namespace)
                included_patterns = include(
                    (child_patterns, namespace["namespace"]),
                    namespace=namespace["namespace"],
                )
                namespace_urlpatterns.append(path(namespace["path"], included_patterns))
        return namespace_urlpatterns

    def sum_registered_patters(self):
        all_patterns = {}
        for urls in self._patterns:
            namespace = urls["namespace"]
            added_patterns = urls["urlpatterns"]
            all_patterns.setdefault(namespace, []).extend(added_patterns)

        self.namespace_patterns = all_patterns

    def build_root_urlpatterns(self):
        root_urlpatterns = []
        for namespace in self._namespaces:
            if not namespace["parent"]:
                child_patterns = self.get_child_patterns(namespace["namespace"])
                included_patterns = include(
                    (child_patterns, namespace["namespace"]),
                    namespace=namespace["namespace"],
                )
                root_urlpatterns.append(path(namespace["path"], included_patterns))

        return root_urlpatterns

    def build_urlpatterns(self):
        self.sum_registered_patters()
        return self.build_root_urlpatterns()

    def __call__(self):
        if self._urlpatterns:
            return self._urlpatterns

        self._urlpatterns = self.build_urlpatterns()
        self._namespaces = []
        self._patterns = []
        return self._urlpatterns


urlpatterns = URLPatterns()
