import dataclasses
import datetime
import enum
from typing import Optional

from folkugat_web.services import ngrams

NGrams = dict[int, list[str]]


class LinkType(enum.Enum):
    SCORE = "score"
    AUDIO = "audio"
    OTHER = "other"


class LinkSubtype(enum.Enum):
    # Score
    PDF = "pdf"
    IMAGE = "image"
    # Audio
    SPOTIFY = "spotify"
    YOUTUBE = "youtube"


@dataclasses.dataclass
class Link:
    type: LinkType
    subtype: Optional[LinkSubtype]
    url: str
    title: str = ""

    def to_dict(self):
        return dict(
            type=self.type.value,
            subtype=self.subtype.value if self.subtype else None,
            url=self.url,
            title=self.title,
        )

    @classmethod
    def from_dict(cls, d):
        return cls(
            type=LinkType(d["type"]),
            subtype=LinkSubtype(d["subtype"]) if d["subtype"] else None,
            url=d["url"],
            title=d["title"],
        )


class PropertyField(enum.Enum):
    AUTOR = "autor"
    TIPUS = "tipus"
    COMPAS = "compàs"
    ORIGEN = "orígen"


@dataclasses.dataclass
class Property:
    field: PropertyField
    value: str

    def to_dict(self):
        return dict(
            field=self.field.value,
            value=self.value,
        )

    @classmethod
    def from_dict(cls, d):
        return cls(
            field=PropertyField(d["field"]),
            value=d["value"],
        )


@dataclasses.dataclass
class Lyrics:
    title: str
    content: str

    def to_dict(self):
        return dict(
            title=self.title,
            content=self.content,
        )

    @classmethod
    def from_dict(cls, d):
        return cls(
            title=d["title"],
            content=d["content"],
        )


@dataclasses.dataclass
class Tema:
    id: Optional[int] = None
    # Info
    title: str = ""
    properties: list[Property] = dataclasses.field(default_factory=list)
    links: list[Link] = dataclasses.field(default_factory=list)
    lyrics: list[Lyrics] = dataclasses.field(default_factory=list)
    # Search related
    alternatives: list[str] = dataclasses.field(default_factory=list)
    ngrams: NGrams = dataclasses.field(default_factory=dict)
    hidden: bool = True
    # Other info
    modification_date: datetime.datetime = dataclasses.field(default_factory=datetime.datetime.now)
    creation_date: datetime.datetime = dataclasses.field(default_factory=datetime.datetime.now)

    def compute_ngrams(self):
        self.ngrams = ngrams.get_text_ngrams(self.title, *self.alternatives)

    def with_ngrams(self):
        self.compute_ngrams()
        return self

    def scores(self):
        return [link for link in self.links if link.type is LinkType.SCORE]

    def audios(self):
        return [link for link in self.links if link.type is LinkType.AUDIO]
