# Copyright (C) 2024 Araten & Marigold
#
# This file is part of Edgeware++.
#
# Edgeware++ is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Edgeware++ is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Edgeware++.  If not, see <https://www.gnu.org/licenses/>.

import multiprocessing
from collections.abc import Callable
from dataclasses import dataclass, field
from tkinter import Toplevel
from typing import Any

import pyglet
import pystray


class Popup(Toplevel):  # Circular
    pass


@dataclass
class Subject:
    value: Any
    observers: list[Callable[[], None]] = field(default_factory=list)

    def notify(self) -> None:
        for observer in self.observers:
            observer()

    def attach(self, observer: Callable[[], None]) -> None:
        self.observers.append(observer)


@dataclass
class State:
    fill_number = 0
    _popup_number = Subject(0)
    prompt_active = False
    video_number = 0

    audio_players: list[pyglet.media.Player] = field(default_factory=list)
    popups: list[Popup] = field(default_factory=list)

    panic_lockout_active = False

    _hibernate_active = Subject(False)
    hibernate_id = None
    pump_scare = False

    corruption_level = 1
    corruption_time_start = 0  # Milliseconds
    corruption_popup_number = 0
    corruption_launches_number = 1

    tray: pystray.Icon | None = None

    keyboard_process: multiprocessing.Process | None = None
    alt_held = False

    @property
    def popup_number(self) -> int:
        return self._popup_number.value

    @popup_number.setter
    def popup_number(self, value: int) -> None:
        self._popup_number.value = value
        self._popup_number.notify()

    @property
    def hibernate_active(self) -> bool:
        return self._hibernate_active.value

    @hibernate_active.setter
    def hibernate_active(self, value: bool) -> None:
        self._hibernate_active.value = value
        self._hibernate_active.notify()
