"""
Subify Settings & Preferences Window
"""

import os
import json
import objc
import AppKit
from AppKit import (
    NSWindow, NSView, NSTextField, NSSlider, NSButton, NSPopUpButton,
    NSButtonTypeSwitch, NSControlStateValueOn, NSControlStateValueOff,
    NSWindowStyleMaskTitled, NSWindowStyleMaskClosable,
    NSFont, NSColor, NSFontWeightBold, NSFontWeightMedium,
    NSMakeRect, NSMakeSize, NSApp
)
from Foundation import NSObject

CONFIG_PATH = os.path.expanduser('~/.subify_settings.json')


class Settings:
    """Manages application preferences stored in ~/.subify_settings.json."""

    def __init__(self):
        self.font_size = 22.0
        self.show_next_line = True
        self.glass_opacity = 0.85
        self.bottom_margin = 45.0
        self.theme_name = 'dark'
        self.sync_offset = 0.0  # Timing offset in seconds (+delay, -advance)
        self.custom_center_x = None
        self.custom_center_y = None
        self.load()

    def load(self):
        if os.path.exists(CONFIG_PATH):
            try:
                with open(CONFIG_PATH, 'r') as f:
                    data = json.load(f)
                    self.font_size = float(data.get('font_size', 22.0))
                    self.show_next_line = bool(data.get('show_next_line', True))
                    self.glass_opacity = float(data.get('glass_opacity', 0.85))
                    self.bottom_margin = float(data.get('bottom_margin', 45.0))
                    self.theme_name = str(data.get('theme_name', 'dark'))
                    self.sync_offset = float(data.get('sync_offset', 0.0))

                    cx = data.get('custom_center_x')
                    cy = data.get('custom_center_y')
                    self.custom_center_x = float(cx) if cx is not None else None
                    self.custom_center_y = float(cy) if cy is not None else None
            except Exception:
                pass

    def save(self):
        try:
            with open(CONFIG_PATH, 'w') as f:
                json.dump({
                    'font_size': self.font_size,
                    'show_next_line': self.show_next_line,
                    'glass_opacity': self.glass_opacity,
                    'bottom_margin': self.bottom_margin,
                    'theme_name': self.theme_name,
                    'sync_offset': self.sync_offset,
                    'custom_center_x': self.custom_center_x,
                    'custom_center_y': self.custom_center_y
                }, f, indent=2)
        except Exception:
            pass


def create_label(text, frame, bold=False):
    """Helper function to create styled NSTextField labels."""
    lbl = NSTextField.alloc().initWithFrame_(frame)
    lbl.setEditable_(False)
    lbl.setBezeled_(False)
    lbl.setDrawsBackground_(False)
    lbl.setSelectable_(False)
    font_weight = NSFontWeightBold if bold else NSFontWeightMedium
    lbl.setFont_(NSFont.systemFontOfSize_weight_(13, font_weight))
    lbl.setStringValue_(text)
    return lbl


class SettingsWindowController(NSObject):
    """Controller for the Preferences window."""

    def initWithApp_settings_(self, app, settings):
        self = objc.super(SettingsWindowController, self).init()
        if self is None:
            return None
        self._app = app
        self._settings = settings
        self._window = None

        self._theme_popup = None
        self._font_size_slider = None
        self._font_size_val_label = None
        self._next_line_checkbox = None
        self._opacity_slider = None
        self._opacity_val_label = None
        self._margin_slider = None
        self._margin_val_label = None
        self._sync_slider = None
        self._sync_val_label = None

        return self

    def showWindow(self):
        if self._window is None:
            self._create_window()

        self._window.deminiaturize_(None)
        self._window.makeKeyAndOrderFront_(None)
        NSApp.activateIgnoringOtherApps_(True)

    def _create_window(self):
        w = 460
        h = 365

        window = NSWindow.alloc().initWithContentRect_styleMask_backing_defer_(
            NSMakeRect(200, 200, w, h),
            NSWindowStyleMaskTitled | NSWindowStyleMaskClosable,
            2,
            False
        )
        window.setTitle_('Subify Preferences')
        window.setReleasedWhenClosed_(False)
        window.setHidesOnDeactivate_(False)

        content = NSView.alloc().initWithFrame_(NSMakeRect(0, 0, w, h))
        window.setContentView_(content)

        # ── 1. Glass Theme ──
        lbl0 = create_label('Glass Theme:', NSMakeRect(30, 300, 130, 20), bold=True)
        content.addSubview_(lbl0)

        popup = NSPopUpButton.alloc().initWithFrame_pullsDown_(NSMakeRect(170, 300, 200, 25), False)
        popup.addItemsWithTitles_(['Dark Glass', 'Light Frost', 'Cyberpunk Neon', 'Golden Hour', 'Minimal Carbon'])

        theme_map = {'dark': 0, 'light': 1, 'cyberpunk': 2, 'gold': 3, 'carbon': 4}
        popup.selectItemAtIndex_(theme_map.get(self._settings.theme_name, 0))
        popup.setTarget_(self)
        popup.setAction_('themeChanged:')
        content.addSubview_(popup)
        self._theme_popup = popup

        # ── 2. Font Size ──
        lbl1 = create_label('Font Size:', NSMakeRect(30, 255, 130, 20), bold=True)
        content.addSubview_(lbl1)

        slider1 = NSSlider.sliderWithValue_minValue_maxValue_target_action_(
            self._settings.font_size, 16.0, 36.0, self, 'fontSizeChanged:'
        )
        slider1.setFrame_(NSMakeRect(170, 255, 180, 20))
        content.addSubview_(slider1)
        self._font_size_slider = slider1

        val1 = create_label(f'{int(self._settings.font_size)}pt', NSMakeRect(360, 255, 50, 20))
        content.addSubview_(val1)
        self._font_size_val_label = val1

        # ── 3. Glass Opacity ──
        lbl2 = create_label('Glass Opacity:', NSMakeRect(30, 210, 130, 20), bold=True)
        content.addSubview_(lbl2)

        slider2 = NSSlider.sliderWithValue_minValue_maxValue_target_action_(
            self._settings.glass_opacity, 0.3, 1.0, self, 'opacityChanged:'
        )
        slider2.setFrame_(NSMakeRect(170, 210, 180, 20))
        content.addSubview_(slider2)
        self._opacity_slider = slider2

        val2 = create_label(f'{int(self._settings.glass_opacity * 100)}%', NSMakeRect(360, 210, 50, 20))
        content.addSubview_(val2)
        self._opacity_val_label = val2

        # ── 4. Bottom Screen Margin ──
        lbl3 = create_label('Bottom Margin:', NSMakeRect(30, 165, 130, 20), bold=True)
        content.addSubview_(lbl3)

        slider3 = NSSlider.sliderWithValue_minValue_maxValue_target_action_(
            self._settings.bottom_margin, 20.0, 200.0, self, 'marginChanged:'
        )
        slider3.setFrame_(NSMakeRect(170, 165, 180, 20))
        content.addSubview_(slider3)
        self._margin_slider = slider3

        val3 = create_label(f'{int(self._settings.bottom_margin)}px', NSMakeRect(360, 165, 50, 20))
        content.addSubview_(val3)
        self._margin_val_label = val3

        # ── 5. Lyrics Sync Offset ──
        lbl4 = create_label('Sync Offset:', NSMakeRect(30, 120, 130, 20), bold=True)
        content.addSubview_(lbl4)

        slider4 = NSSlider.sliderWithValue_minValue_maxValue_target_action_(
            self._settings.sync_offset, -5.0, 5.0, self, 'syncOffsetChanged:'
        )
        slider4.setFrame_(NSMakeRect(170, 120, 180, 20))
        content.addSubview_(slider4)
        self._sync_slider = slider4

        sync_str = f'{self._settings.sync_offset:+.1f}s' if self._settings.sync_offset != 0 else '0.0s'
        val4 = create_label(sync_str, NSMakeRect(360, 120, 60, 20))
        content.addSubview_(val4)
        self._sync_val_label = val4

        # ── 6. Show Next Line Preview ──
        chk = NSButton.checkboxWithTitle_target_action_(
            'Show upcoming line preview', self, 'nextCheckChanged:'
        )
        chk.setFrame_(NSMakeRect(170, 75, 220, 25))
        chk.setState_(NSControlStateValueOn if self._settings.show_next_line else NSControlStateValueOff)
        content.addSubview_(chk)
        self._next_line_checkbox = chk

        # ── 7. Reset Position Button ──
        btn_reset = NSButton.alloc().initWithFrame_(NSMakeRect(170, 25, 180, 30))
        btn_reset.setTitle_('Reset Position to Center')
        btn_reset.setTarget_(self)
        btn_reset.setAction_('resetPosition:')
        content.addSubview_(btn_reset)

        self._window = window

    @objc.IBAction
    def syncOffsetChanged_(self, sender):
        val = round(sender.doubleValue(), 1)
        self._settings.sync_offset = val
        sync_str = f'{val:+.1f}s' if val != 0 else '0.0s'
        self._sync_val_label.setStringValue_(sync_str)
        self._settings.save()
        if self._app:
            self._app.applySettings()

    @objc.IBAction
    def resetPosition_(self, sender):
        self._settings.custom_center_x = None
        self._settings.custom_center_y = None
        self._settings.save()
        if self._app:
            self._app.applySettings()

    @objc.IBAction
    def themeChanged_(self, sender):
        idx = sender.indexOfSelectedItem()
        names = ['dark', 'light', 'cyberpunk', 'gold', 'carbon']
        if 0 <= idx < len(names):
            self._settings.theme_name = names[idx]
            self._settings.save()
            if self._app:
                self._app.applySettings()

    @objc.IBAction
    def fontSizeChanged_(self, sender):
        val = sender.doubleValue()
        self._settings.font_size = val
        self._font_size_val_label.setStringValue_(f'{int(val)}pt')
        self._settings.save()
        if self._app:
            self._app.applySettings()

    @objc.IBAction
    def opacityChanged_(self, sender):
        val = sender.doubleValue()
        self._settings.glass_opacity = val
        self._opacity_val_label.setStringValue_(f'{int(val * 100)}%')
        self._settings.save()
        if self._app:
            self._app.applySettings()

    @objc.IBAction
    def marginChanged_(self, sender):
        val = sender.doubleValue()
        self._settings.bottom_margin = val
        self._settings.custom_center_x = None
        self._settings.custom_center_y = None
        self._settings.save()
        if self._app:
            self._app.applySettings()

    @objc.IBAction
    def nextCheckChanged_(self, sender):
        is_on = (sender.state() == NSControlStateValueOn)
        self._settings.show_next_line = is_on
        self._settings.save()
        if self._app:
            self._app.applySettings()
