# Standard library imports.
from pathlib import Path
from urllib.parse import urlencode
from functools import cmp_to_key

# Django imports.
from django.conf import settings

# Project imports.
from .utils import make_thumbnail, is_image_file

###########################################################################################
# Constants.                                                                              #
###########################################################################################

SORT_OPTIONS = [
    ("abc", "Alphabetical A-Z"),
    ("cba", "Alphabetical Z-A"),
    ("old", "Creation date old to new"),
    ("new", "Creation date new to old"),
    ("recent", "Modification date most recent"),
    ("tnecer", "Modification date least recent"),
]

SORT_LABELS = dict(SORT_OPTIONS)


def normalize_sort(sort_value):
    return sort_value if sort_value in SORT_LABELS else "abc"


def normalize_theme(theme_value):
    return theme_value if theme_value in ("dark", "light") else "dark"


def get_creation_timestamp(path_obj):
    try:
        stat_data = path_obj.stat()
        return getattr(stat_data, "st_birthtime", stat_data.st_ctime)
    except OSError:
        return 0


def get_modification_timestamp(path_obj):
    try:
        return path_obj.stat().st_mtime
    except OSError:
        return 0


def build_query(search_text):
    query = {}

    if search_text != "":
        query["search"] = search_text

    return query


def append_query(url, query_dict):
    if len(query_dict) == 0:
        return url

    return url + "?" + urlencode(query_dict)


def gallery_url(path_obj=None, is_dir=False, query_dict=None, special=None):
    if query_dict is None:
        query_dict = {}

    if path_obj is None:
        base_url = f"/gallery/{special}/" if special is not None else "/gallery/"
    else:
        path_text = str(path_obj).replace("\\", "/")
        base_url = (f"/gallery/{special}/" if special is not None else "/gallery/") + path_text

        if is_dir and not base_url.endswith("/"):
            base_url += "/"

    return append_query(base_url, query_dict)


def sort_images(images, sort_key):
    def compare(img_a, img_b):
        name_a = img_a.name.lower()
        name_b = img_b.name.lower()
        rel_a = str(img_a.relative_to(settings.GALLERY_ROOT)).lower()
        rel_b = str(img_b.relative_to(settings.GALLERY_ROOT)).lower()

        if sort_key == "abc":
            if name_a < name_b:
                return -1
            if name_a > name_b:
                return 1

        elif sort_key == "cba":
            if name_a > name_b:
                return -1
            if name_a < name_b:
                return 1

        elif sort_key == "old":
            created_a = get_creation_timestamp(img_a)
            created_b = get_creation_timestamp(img_b)

            if created_a < created_b:
                return -1
            if created_a > created_b:
                return 1

        elif sort_key == "new":
            created_a = get_creation_timestamp(img_a)
            created_b = get_creation_timestamp(img_b)

            if created_a > created_b:
                return -1
            if created_a < created_b:
                return 1

        elif sort_key == "recent":
            modified_a = get_modification_timestamp(img_a)
            modified_b = get_modification_timestamp(img_b)

            if modified_a > modified_b:
                return -1
            if modified_a < modified_b:
                return 1

        elif sort_key == "tnecer":
            modified_a = get_modification_timestamp(img_a)
            modified_b = get_modification_timestamp(img_b)

            if modified_a < modified_b:
                return -1
            if modified_a > modified_b:
                return 1

        if name_a < name_b:
            return -1
        if name_a > name_b:
            return 1
        if rel_a < rel_b:
            return -1
        if rel_a > rel_b:
            return 1
        return 0

    return sorted(images, key=cmp_to_key(compare))


def build_breadcrumbs(path_text, query_dict):
    breadcrumbs = [{"label": "Gallery", "path": gallery_url(None, True, query_dict)}]

    if path_text == "":
        return breadcrumbs

    segments = Path(path_text).parts
    current = Path("")

    for segment in segments:
        current = current.joinpath(segment)
        breadcrumbs.append(
            {"label": segment, "path": gallery_url(current, True, query_dict)}
        )

    return breadcrumbs


def build_sort_options(request, search_text, sort_key, theme):
    options = []

    for option_key, label in SORT_OPTIONS:
        # Build a URL that points to the settings toggle endpoint which will
        # persist the chosen sort (and optionally theme) in the user's
        # UserSettings and then redirect back to the current view. Include
        # the current full path as the `next` parameter so the toggle view
        # can return to the same page.
        query = {"next": request.get_full_path(), "sort": option_key, "theme": theme}

        if search_text != "":
            # Include search top-level so templates/tests can assert its presence
            query["search"] = search_text

        options.append(
            {
                "key": option_key,
                "label": label,
                "url": append_query("/gallery/toggle-settings/", query),
                "is_active": option_key == sort_key,
            }
        )

    return options


def get_first_image_thumbnail_url(subdir):
    try:
        images = sorted(
            [
                entry
                for entry in subdir.iterdir()
                if entry.is_file() and not entry.is_symlink() and is_image_file(entry)
            ],
            key=lambda item: (
                item.name.lower(),
                str(item.relative_to(settings.GALLERY_ROOT)).lower(),
            ),
        )
    except OSError:
        return None

    if len(images) == 0:
        return None

    first_image = images[0]

    try:
        make_thumbnail(first_image)
        rel_path = first_image.relative_to(settings.GALLERY_ROOT)
        thumb_path = settings.THUMBNAILS_ROOT.joinpath(rel_path)

        if thumb_path.exists():
            return "/thumbs/" + str(rel_path).replace("\\", "/")
    except Exception:
        pass

    return None
