# -*- coding: utf-8 -*-
# Copyright (C) 2018-2026 Connet Information Technology Company, Shanghai.

from enum import IntEnum

from qtpy.QtWidgets import QMainWindow, QDialog, QWidget, QFrame, QLabel, QHBoxLayout
from qtpy.QtCore import Qt, QEvent
from qtpy.QtGui import QMouseEvent, QShowEvent, QResizeEvent

from .native import (ns_move_window,
    ns_set_window_button_enabled, ns_set_window_button_visible
)


class WindowButton(IntEnum):
    Close = 0x00000001
    Minimize = 0x00000010
    Maximize = 0x00000100


class QModernTitleBar(QFrame):
    def __init__(self, window: 'QWidget'):
        super().__init__(window)
        self.__window = window
        # fixed height 28 pixels
        self.setFixedHeight(28)
        # label
        self.__label = QLabel(self)
        self.__label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        font = self.__label.font()
        font.setBold(True)
        self.__label.setFont(font)
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.__label)
        self.setLayout(layout)
        window.setContentsMargins(0, 28, 0, 0)
        self.window().installEventFilter(self)

    def setText(self, text: str):
        self.__label.setText(text)

    def text(self) -> str:
        return self.__label.text()

    def mouseMoveEvent(self, event: QMouseEvent):
        ns_move_window(self.window(), event.globalPosition())


class ModernWindowMixin:
    """
    Mixin for QWindow
    """
    WindowButton = WindowButton

    def initialize(self):
        self.__titleBar = QModernTitleBar(self)
        # === perfect on macOS to make title bar's color transparent. ===
        self.setWindowFlag(Qt.WindowType.NoTitleBarBackgroundHint)
        self.setWindowFlag(Qt.WindowType.ExpandedClientAreaHint)
        self.__visibleButtons = self.WindowButton.Close | self.WindowButton.Minimize | self.WindowButton.Maximize
        self.__enabledButtons = self.WindowButton.Close | self.WindowButton.Minimize | self.WindowButton.Maximize

    def titleBar(self) -> QModernTitleBar:
        return self.__titleBar

    def setWindowButtonVisible(self, button: WindowButton, visible: bool):
        if visible:
            self.__visibleButtons |= button
        else:
            self.__visibleButtons &= ~button

    def setWindowButtonEnabled(self, button: WindowButton, enabled: bool):
        if enabled:
            self.__enabledButtons |= button
        else:
            self.__enabledButtons &= ~button

    def visibleWindowButtons(self) -> int:
        return self.__visibleButtons

    def enabledWindowButtons(self) -> int:
        return self.__enabledButtons

    def showEvent(self, event: QShowEvent):
        """Override QWidget's `showEvent`"""
        self.__beforeShowEvent(event)
        super().showEvent(event)

    def resizeEvent(self, event: QResizeEvent):
        """Override QWidget's  `resizeEvent`"""
        super().resizeEvent(event)
        self.__afterResizeEvent(event)

    def changeEvent(self, event: QEvent):
        """Override QWidget's `changeEvent`"""
        self.__beforeChangeEvent(event)
        super().changeEvent(event)

    def setWindowTitle(self, title: str):
        """Override QWidget's `setWindowTitle`"""
        self.__titleBar.setText(title)

    def windowTitle(self) -> str:
        """Override QWidget's `windowTitle`"""
        return self.__titleBar.text()

    def __beforeShowEvent(self, event: QShowEvent):
        self.__titleBar.raise_()
        # must set visibility on window show event.
        ns_set_window_button_enabled(self, 'close', bool(self.enabledWindowButtons() & self.WindowButton.Close))
        ns_set_window_button_enabled(self, 'miniaturize',
                                     bool(self.enabledWindowButtons() & self.WindowButton.Minimize))
        ns_set_window_button_enabled(self, 'zoom', bool(self.enabledWindowButtons() & self.WindowButton.Maximize))
        ns_set_window_button_visible(self, 'close', bool(self.visibleWindowButtons() & self.WindowButton.Close))
        ns_set_window_button_visible(self, 'miniaturize',
                                     bool(self.visibleWindowButtons() & self.WindowButton.Minimize))
        ns_set_window_button_visible(self, 'zoom', bool(self.visibleWindowButtons() & self.WindowButton.Maximize))

    def __afterResizeEvent(self, event: QResizeEvent):
        self.__titleBar.resize(self.width(), self.__titleBar.height())

    def __beforeChangeEvent(self, event: QEvent):
        if event.type() == QEvent.Type.WindowStateChange:
            # reset states on every window state change.
            ns_set_window_button_enabled(self, 'close', bool(self.enabledWindowButtons() & self.WindowButton.Close))
            ns_set_window_button_enabled(self, 'miniaturize', bool(self.enabledWindowButtons() & self.WindowButton.Minimize))
            ns_set_window_button_enabled(self, 'zoom', bool(self.enabledWindowButtons() & self.WindowButton.Maximize))
            ns_set_window_button_visible(self, 'close', bool(self.visibleWindowButtons() & self.WindowButton.Close))
            ns_set_window_button_visible(self, 'miniaturize', bool(self.visibleWindowButtons() & self.WindowButton.Minimize))
            ns_set_window_button_visible(self, 'zoom', bool(self.visibleWindowButtons() & self.WindowButton.Maximize))


class QModernMainWindow(ModernWindowMixin, QMainWindow):

    def __init__(self) -> None:
        super().__init__()
        ModernWindowMixin.initialize(self)


class QModernDialog(ModernWindowMixin, QDialog):

    def __init__(self) -> None:
        super().__init__()
        ModernWindowMixin.initialize(self)


class QModernWindow(ModernWindowMixin, QWidget):

    def __init__(self) -> None:
        super().__init__()
        ModernWindowMixin.initialize(self)

