#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributors.

from fenrirscreenreader.core.i18n import _
from fenrirscreenreader.utils import line_utils
from fenrirscreenreader.utils import mark_utils


class bookmark_command:
    """Base class for bookmark operations - read, set, clear"""

    def __init__(self, bookmark_id, action="read"):
        self.ID = str(bookmark_id)
        self.action = action

    def initialize(self, environment):
        self.env = environment
        # Always initialize bookmark structure - all commands need this
        if self.ID not in self.env["commandBuffer"]["bookMarks"]:
            self.env["commandBuffer"]["bookMarks"][self.ID] = {}

    def shutdown(self):
        pass

    def get_description(self):
        if self.action == "read":
            return _("read Bookmark {0}").format(self.ID)
        elif self.action == "set":
            return _("set Bookmark {0}").format(self.ID)
        elif self.action == "clear":
            return _("remove Bookmark {0}").format(self.ID)
        return f"{self.action} Bookmark {self.ID}"

    def run(self):
        if self.action == "read":
            self._read_bookmark()
        elif self.action == "set":
            self._set_bookmark()
        elif self.action == "clear":
            self._clear_bookmark()

    def _read_bookmark(self):
        curr_app = self.env["runtime"][
            "ApplicationManager"
        ].get_current_application()

        if not self.env["commandBuffer"]["bookMarks"][self.ID]:
            self.env["runtime"]["OutputManager"].present_text(
                "Bookmark {0} not set".format(self.ID), interrupt=True
            )
            return

        if curr_app not in self.env["commandBuffer"]["bookMarks"][self.ID]:
            self.env["runtime"]["OutputManager"].present_text(
                "Bookmark for application {0} not set".format(curr_app),
                interrupt=True,
            )
            return

        if not self.env["commandBuffer"]["bookMarks"][self.ID][curr_app].get(
            "1"
        ):
            self.env["runtime"]["OutputManager"].present_text(
                "Bookmark for application {0} not set".format(curr_app),
                interrupt=True,
            )
            return

        # Get bookmarked text
        marked = ""
        start_mark = self.env["commandBuffer"]["bookMarks"][self.ID][curr_app][
            "1"
        ].copy()

        if self.env["commandBuffer"]["bookMarks"][self.ID][curr_app]["2"]:
            end_mark = self.env["commandBuffer"]["bookMarks"][self.ID][
                curr_app
            ]["2"].copy()
            marked = mark_utils.get_text_between_marks(
                start_mark, end_mark, self.env["screen"]["new_content_text"]
            )
        else:
            x, y, marked = line_utils.get_current_line(
                start_mark["x"],
                start_mark["y"],
                self.env["screen"]["new_content_text"],
            )

        if marked.isspace():
            self.env["runtime"]["OutputManager"].present_text(
                _("blank"), sound_icon="EmptyLine", interrupt=True
            )
        else:
            self.env["runtime"]["OutputManager"].present_text(
                marked, interrupt=True
            )

    def _set_bookmark(self):
        if not self.env["commandBuffer"]["Marks"]["1"]:
            self.env["runtime"]["OutputManager"].present_text(
                _("No mark found"), interrupt=True
            )
            return

        curr_app = self.env["runtime"][
            "ApplicationManager"
        ].get_current_application()
        self.env["commandBuffer"]["bookMarks"][self.ID][curr_app] = {}

        bookmarks = self.env["commandBuffer"]["bookMarks"][self.ID][curr_app]
        bookmarks["1"] = self.env["commandBuffer"]["Marks"]["1"].copy()

        if self.env["commandBuffer"]["Marks"]["2"]:
            bookmarks["2"] = self.env["commandBuffer"]["Marks"]["2"].copy()
        else:
            bookmarks["2"] = None

        self.env["runtime"]["OutputManager"].present_text(
            _("Bookmark {0} set for application {1}").format(
                self.ID, curr_app
            ),
            interrupt=True,
        )

        # Clear marks after setting bookmark
        self.env["commandBuffer"]["Marks"]["1"] = None
        self.env["commandBuffer"]["Marks"]["2"] = None

    def _clear_bookmark(self):
        curr_app = self.env["runtime"][
            "ApplicationManager"
        ].get_current_application()

        bookmarks = self.env["commandBuffer"]["bookMarks"]
        if self.ID in bookmarks and curr_app in bookmarks[self.ID]:
            del self.env["commandBuffer"]["bookMarks"][self.ID][curr_app]
            self.env["runtime"]["OutputManager"].present_text(
                _("Bookmark {0} removed for application {1}").format(
                    self.ID, curr_app
                ),
                interrupt=True,
            )
        else:
            self.env["runtime"]["OutputManager"].present_text(
                _("Bookmark {0} not set for application {1}").format(
                    self.ID, curr_app
                ),
                interrupt=True,
            )

    def set_callback(self, callback):
        pass


# Factory function to create bookmark command instances


def create_bookmark_commands():
    """Create all bookmark command instances"""
    commands = {}

    # Create read bookmark commands (bookmark_1 through bookmark_10)
    for i in range(1, 11):
        commands[f"bookmark_{i}"] = lambda i=i: bookmark_command(i, "read")

    # Create set bookmark commands (set_bookmark_1 through set_bookmark_10)
    for i in range(1, 11):
        commands[f"set_bookmark_{i}"] = lambda i=i: bookmark_command(i, "set")

    # Create clear bookmark commands (clear_bookmark_1 through
    # clear_bookmark_10)
    for i in range(1, 11):
        commands[f"clear_bookmark_{i}"] = lambda i=i: bookmark_command(
            i, "clear"
        )

    return commands


# For backwards compatibility, provide individual command classes
# This allows the existing command loading system to work unchanged


def _make_command_class(bookmark_id, action):
    """Create a command class for a specific bookmark and action"""

    class command(bookmark_command):
        def __init__(self):
            super().__init__(bookmark_id, action)

    return command


# Generate individual command classes for each bookmark operation
# These will be used by the existing command loading system


# Read bookmarks (bookmark_1.py style)
for i in range(1, 11):
    globals()[f"bookmark_{i}_command"] = _make_command_class(i, "read")

# Set bookmarks (set_bookmark_1.py style)
for i in range(1, 11):
    globals()[f"set_bookmark_{i}_command"] = _make_command_class(i, "set")

# Clear bookmarks (clear_bookmark_1.py style)
for i in range(1, 11):
    globals()[f"clear_bookmark_{i}_command"] = _make_command_class(i, "clear")
