from datetime import datetime
from collections import defaultdict

from slugify import slugify

from stag.signals import signals
from stag.ecs import Page, Taxonomy, Term, Metadata, Content
from stag.utils import chdir, SortDate

_TAXONOMIES = []
_RAW_TAXO = defaultdict(lambda: defaultdict(set))


def copy_output_type(pages, default="html"):
    for page in pages:
        if page.output and page.output.type:
            return page.output.type
    return default


def update_metadata(page, **kw):
    if not page.metadata:
        page.metadata = Metadata()
    kw.update(page.metadata.data)
    page.metadata.data = kw


def init_taxonomies(site):
    if not site.config.taxonomies:
        return

    global _TAXONOMIES
    _TAXONOMIES = [
        Taxonomy(name=ttab.key, singular=ttab.singular, plural=ttab.plural)
        for ttab in site.config.taxonomies
    ]


def add_pages(site):
    for page in site.pages:
        if not page.metadata:
            continue

        for taxonomy in _TAXONOMIES:
            terms = page.metadata.get(taxonomy.name)

            if not terms:
                continue
            if not isinstance(terms, list):
                terms = [terms]

            for term in terms:
                _RAW_TAXO[taxonomy.name][term].add(page)


def finalize(site):
    # Pages can be created by users for taxonomies and terms. In this situation
    # stag will override some members (page.list), update others with unset
    # values (metadata) and leave the rest untouched (e.g. content).
    #
    # This is to give users possibility to hardcode custom metadata for specific
    # taxonomies.
    now = datetime.now()
    for taxonomy in _TAXONOMIES:
        baseslug = slugify(taxonomy.name)
        taxo_page = site.get_or_make_page(baseslug)
        taxo_page.taxonomy = taxonomy
        update_metadata(taxo_page, title=taxonomy.plural, date=now)

        for term, pages in _RAW_TAXO[taxonomy.name].items():
            termslug = slugify(term)
            term_page = site.get_or_make_page(f"{baseslug}/{termslug}")
            term_page.term = Term(termslug, sorted(pages, key=SortDate))
            term_page.output = Content(type=copy_output_type(pages))
            update_metadata(term_page, title=term, date=now, taxonomy=taxonomy.name)

            taxo_page.taxonomy.terms.append(term_page)

        taxo_page.taxonomy.terms.sort()
        taxo_page.output = Content(type=copy_output_type(taxo_page.taxonomy.terms))

    site.taxonomies = _TAXONOMIES


def register_plugin():
    signals.site_init.connect(init_taxonomies)
    signals.readers_finished.connect(add_pages)
    signals.processors_init.connect(finalize)
