import QtQml
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import "../Helpers/ColorList.js" as ColorList
import qs.Commons
import qs.Services.UI
import qs.Widgets

Popup {
  id: root

  property color selectedColor: Color.black

  enum EditMode {
    R,
    G,
    B,
    H,
    S,
    V
  }
  property int editMode: NColorPickerDialog.EditMode.R

  // Code to deal with Hue when color is achromatic
  property real stableHue: 0
  onSelectedColorChanged: {
    if (selectedColor.hsvHue >= 0) {
      stableHue = selectedColor.hsvHue;
    }
  }
  readonly property real displayHue: selectedColor.hsvHue < 0 ? stableHue : selectedColor.hsvHue

  signal colorSelected(color color)

  width: 580
  height: {
    const h = scrollView.implicitHeight + padding * 2;
    Math.min(h, screen?.height - Style.barHeight - Style.marginL * 2);
  }
  padding: Style.marginXL

  // Center popup in parent
  x: (parent.width - width) * 0.5
  y: (parent.height - height) * 0.5

  modal: true

  background: Rectangle {
    color: Color.mSurface
    radius: Style.iRadiusS
    border.color: Color.mPrimary
    border.width: Style.borderM
  }

  contentItem: NScrollView {
    id: scrollView
    width: parent.width

    verticalPolicy: ScrollBar.AlwaysOff
    horizontalPolicy: ScrollBar.AlwaysOff

    ColumnLayout {
      width: scrollView.availableWidth
      spacing: Style.marginL

      // Header
      RowLayout {
        Layout.fillWidth: true

        RowLayout {
          spacing: Style.marginS

          NIcon {
            icon: "color-picker"
            pointSize: Style.fontSizeXXL
            color: Color.mPrimary
          }

          NText {
            text: I18n.tr("widgets.color-picker.title")
            pointSize: Style.fontSizeXL
            font.weight: Style.fontWeightBold
            color: Color.mPrimary
          }
        }

        Item {
          Layout.fillWidth: true
        }

        NIconButton {
          icon: "close"
          onClicked: root.close()
        }
      }

      // Color preview section
      Rectangle {
        Layout.fillWidth: true
        Layout.preferredHeight: 80
        radius: Style.iRadiusS
        color: root.selectedColor
        border.color: Color.mOutline
        border.width: Style.borderS

        ColumnLayout {
          spacing: 0
          anchors.fill: parent

          Item {
            Layout.fillHeight: true
          }

          NText {
            text: root.selectedColor.toString().toUpperCase()
            family: Settings.data.ui.fontFixed
            pointSize: Style.fontSizeL
            font.weight: Font.Bold
            color: root.selectedColor.r + root.selectedColor.g + root.selectedColor.b > 1.5 ? Color.black : Color.white
            Layout.alignment: Qt.AlignHCenter
          }

          NText {
            text: "RGB(" + Math.round(root.selectedColor.r * 255) + ", " + Math.round(root.selectedColor.g * 255) + ", " + Math.round(root.selectedColor.b * 255) + ")"
            family: Settings.data.ui.fontFixed
            pointSize: Style.fontSizeM
            color: root.selectedColor.r + root.selectedColor.g + root.selectedColor.b > 1.5 ? Color.black : Color.white
            Layout.alignment: Qt.AlignHCenter
          }

          Item {
            Layout.fillHeight: true
          }
        }
      }

      // Main Box
      NBox {
        Layout.fillWidth: true
        Layout.preferredHeight: controlsOutterColumn.implicitHeight + Style.marginL * 2

        ButtonGroup {
          id: colorValues
        }

        ColumnLayout {
          id: controlsOutterColumn
          anchors.fill: parent
          anchors.margins: Style.marginL
          spacing: Style.marginM

          RowLayout {
            spacing: Style.marginL // Ensure nice gap between Left and Right groups

            // SpinBoxes Column
            ColumnLayout {
              Layout.fillWidth: true
              Layout.fillHeight: true
              Layout.alignment: Qt.AlignTop
              Layout.preferredWidth: 3

              // --- RED ---
              RowLayout {
                Layout.fillWidth: true
                spacing: Style.marginM

                NRadioButton {
                  ButtonGroup.group: colorValues
                  text: "R"
                  font.weight: Font.Bold
                  checked: true
                  onClicked: root.editMode = NColorPickerDialog.EditMode.R
                  Layout.fillWidth: false
                }

                NSpinBox {
                  id: redSpinBox
                  from: 0
                  to: 255

                  onValueChanged: {
                    if (!selectedSlider.pressed && !fieldMouse.pressed && !hexInput.activeFocus && value !== Math.round(root.selectedColor.r * 255)) {
                      root.selectedColor = Qt.rgba(value / 255, root.selectedColor.g, root.selectedColor.b, 1);
                    }
                  }
                  Binding {
                    target: redSpinBox
                    property: "value"
                    value: Math.round(root.selectedColor.r * 255)
                  }
                }
              }

              // --- GREEN ---
              RowLayout {
                Layout.fillWidth: true
                spacing: Style.marginM

                NRadioButton {
                  ButtonGroup.group: colorValues
                  text: "G"
                  font.weight: Font.Bold
                  onClicked: root.editMode = NColorPickerDialog.EditMode.G
                  Layout.fillWidth: false
                }

                NSpinBox {
                  id: greenSpinBox
                  from: 0
                  to: 255

                  onValueChanged: {
                    if (!selectedSlider.pressed && !fieldMouse.pressed && !hexInput.activeFocus && value !== Math.round(root.selectedColor.g * 255)) {
                      root.selectedColor = Qt.rgba(root.selectedColor.r, value / 255, root.selectedColor.b, 1);
                    }
                  }
                  Binding {
                    target: greenSpinBox
                    property: "value"
                    value: Math.round(root.selectedColor.g * 255)
                  }
                }
              }

              // --- BLUE ---
              RowLayout {
                Layout.fillWidth: true
                spacing: Style.marginM

                NRadioButton {
                  ButtonGroup.group: colorValues
                  text: "B"
                  font.weight: Font.Bold
                  onClicked: root.editMode = NColorPickerDialog.EditMode.B
                  Layout.fillWidth: false
                }

                NSpinBox {
                  id: blueSpinBox
                  from: 0
                  to: 255

                  onValueChanged: {
                    if (!selectedSlider.pressed && !fieldMouse.pressed && !hexInput.activeFocus && value !== Math.round(root.selectedColor.b * 255)) {
                      root.selectedColor = Qt.rgba(root.selectedColor.r, root.selectedColor.g, value / 255, 1);
                    }
                  }
                  Binding {
                    target: blueSpinBox
                    property: "value"
                    value: Math.round(root.selectedColor.b * 255)
                  }
                }
              }

              // Spacer
              Item {
                Layout.fillHeight: true
                Layout.fillWidth: true
              }

              // --- HUE ---
              RowLayout {
                Layout.fillWidth: true
                spacing: Style.marginM

                NRadioButton {
                  ButtonGroup.group: colorValues
                  text: "H"
                  font.weight: Font.Bold
                  checked: true
                  onClicked: root.editMode = NColorPickerDialog.EditMode.H
                  Layout.fillWidth: false
                }

                NSpinBox {
                  id: hueSpinBox
                  from: 0
                  to: 360

                  onValueChanged: {
                    if (!selectedSlider.pressed && !fieldMouse.pressed && !hexInput.activeFocus && value !== Math.round(root.displayHue * 360)) {
                      var newHue = value / 360;
                      root.selectedColor = Qt.hsva(newHue, root.selectedColor.hsvSaturation, root.selectedColor.hsvValue, 1);
                      root.stableHue = newHue;
                    }
                  }

                  Binding {
                    target: hueSpinBox
                    property: "value"
                    value: Math.round(root.displayHue * 360)
                  }
                }
              }

              // --- SATURATION ---
              RowLayout {
                Layout.fillWidth: true
                spacing: Style.marginM

                NRadioButton {
                  ButtonGroup.group: colorValues
                  text: "S"
                  font.weight: Font.Bold
                  onClicked: root.editMode = NColorPickerDialog.EditMode.S
                  Layout.fillWidth: false
                }

                NSpinBox {
                  id: satSpinBox
                  from: 0
                  to: 100

                  onValueChanged: {
                    if (!selectedSlider.pressed && !fieldMouse.pressed && !hexInput.activeFocus && value !== Math.round(root.selectedColor.hsvSaturation * 100)) {
                      root.selectedColor = Qt.hsva(root.selectedColor.hsvHue, value / 100, root.selectedColor.hsvValue, 1);
                    }
                  }
                  Binding {
                    target: satSpinBox
                    property: "value"
                    value: Math.round(root.selectedColor.hsvSaturation * 100)
                  }
                }
              }

              // --- VALUE ---
              RowLayout {
                spacing: Style.marginM

                NRadioButton {
                  ButtonGroup.group: colorValues
                  text: "V"
                  font.weight: Font.Bold
                  onClicked: root.editMode = NColorPickerDialog.EditMode.V
                  Layout.fillWidth: false
                }

                NSpinBox {
                  id: valSpinBox
                  from: 0
                  to: 100

                  onValueChanged: {
                    if (!selectedSlider.pressed && !fieldMouse.pressed && !hexInput.activeFocus && value !== Math.round(root.selectedColor.hsvValue * 100)) {
                      root.selectedColor = Qt.hsva(root.selectedColor.hsvHue, root.selectedColor.hsvSaturation, value / 100, 1);
                    }
                  }
                  Binding {
                    target: valSpinBox
                    property: "value"
                    value: Math.round(root.selectedColor.hsvValue * 100)
                  }
                }
              }

              // Spacer
              Item {
                Layout.fillHeight: true
                Layout.fillWidth: true
              }

              // Hex input
              RowLayout {
                id: hexInput
                Layout.fillWidth: true
                spacing: Style.marginM

                NLabel {
                  label: "Hex:"
                  Layout.alignment: Qt.AlignVCenter
                }

                NTextInput {
                  text: root.selectedColor.toString().toUpperCase()
                  fontFamily: Settings.data.ui.fontFixed
                  Layout.fillWidth: true
                  Layout.minimumWidth: implicitWidth
                  onEditingFinished: {
                    if (/^#[0-9A-F]{6}$/i.test(text)) {
                      root.selectedColor = text;
                    }
                  }
                }
              }
            }

            RowLayout {
              Layout.fillWidth: true
              Layout.fillHeight: true
              Layout.preferredWidth: 5
              Layout.alignment: Qt.AlignTop
              spacing: Style.marginS

              Layout.topMargin: Math.round(2 * Style.uiScaleRatio) //Shim to try and line up colorField with SpinBoxes

              // --- SLIDER ---
              NColorSlider {
                id: selectedSlider
                Layout.fillHeight: true
                rainbowMode: root.editMode === "h"
                topColor: {
                  if (rainbowMode)
                    return "transparent";
                  switch (root.editMode) {
                  case NColorPickerDialog.EditMode.R:
                    return "#FF0000";
                  case NColorPickerDialog.EditMode.G:
                    return "#00FF00";
                  case NColorPickerDialog.EditMode.B:
                    return "#0000FF";
                  default:
                    return "#FFFFFF";
                  }
                }

                Binding {
                  target: selectedSlider
                  property: "value"
                  when: !selectedSlider.pressed // Only update from model when NOT dragging
                  value: {
                    switch (root.editMode) {
                    case NColorPickerDialog.EditMode.R:
                      return root.selectedColor.r;
                    case NColorPickerDialog.EditMode.G:
                      return root.selectedColor.g;
                    case NColorPickerDialog.EditMode.B:
                      return root.selectedColor.b;
                    case NColorPickerDialog.EditMode.H:
                      return root.displayHue;
                    case NColorPickerDialog.EditMode.S:
                      return root.selectedColor.hsvSaturation;
                    case NColorPickerDialog.EditMode.V:
                      return root.selectedColor.hsvValue;
                    default:
                      return 0;
                    }
                  }
                }

                onMoved: {
                  var v = value;
                  switch (root.editMode) {
                  case NColorPickerDialog.EditMode.R:
                    root.selectedColor = Qt.rgba(v, root.selectedColor.g, root.selectedColor.b, 1);
                    break;
                  case NColorPickerDialog.EditMode.G:
                    root.selectedColor = Qt.rgba(root.selectedColor.r, v, root.selectedColor.b, 1);
                    break;
                  case NColorPickerDialog.EditMode.B:
                    root.selectedColor = Qt.rgba(root.selectedColor.r, root.selectedColor.g, v, 1);
                    break;
                  case NColorPickerDialog.EditMode.H:
                    root.selectedColor = Qt.hsva(v, root.selectedColor.hsvSaturation, root.selectedColor.hsvValue, 1);
                    root.stableHue = v;
                    break;
                  case NColorPickerDialog.EditMode.S:
                    root.selectedColor = Qt.hsva(root.selectedColor.hsvHue, v, root.selectedColor.hsvValue, 1);
                    break;
                  case NColorPickerDialog.EditMode.V:
                    root.selectedColor = Qt.hsva(root.selectedColor.hsvHue, root.selectedColor.hsvSaturation, v, 1);
                    break;
                  }
                }
              }

              // Color Field
              Rectangle {
                id: colorField
                Layout.fillWidth: true

                Layout.preferredHeight: width
                Layout.alignment: Qt.AlignTop

                radius: 0
                border.color: Color.mOutline
                border.width: Style.borderS
                clip: true

                ShaderEffect {
                  anchors.fill: parent
                  anchors.margins: 1 // Avoid drawing over the border

                  fragmentShader: "../Shaders/qsb/color_picker.frag.qsb"

                  // Pass which radio is selected
                  readonly property real fixedVal: {
                    switch (root.editMode) {
                    case NColorPickerDialog.EditMode.R:
                      return root.selectedColor.r;
                    case NColorPickerDialog.EditMode.G:
                      return root.selectedColor.g;
                    case NColorPickerDialog.EditMode.B:
                      return root.selectedColor.b;
                    case NColorPickerDialog.EditMode.H:
                      return root.displayHue;
                    case NColorPickerDialog.EditMode.S:
                      return root.selectedColor.hsvSaturation;
                    case NColorPickerDialog.EditMode.V:
                      return root.selectedColor.hsvValue;
                    default:
                      return 0;
                    }
                  }

                  // Send as one vector because GPUs are so damn picky
                  property vector4d params: Qt.vector4d(1.0, fixedVal, root.editMode, 0)
                }

                MouseArea {
                  id: fieldMouse
                  anchors.fill: parent
                  cursorShape: Qt.CrossCursor

                  // Update color when clicking or dragging
                  function updateColor(mouse) {
                    // Normalize X and Y (0.0 to 1.0)
                    var xVal = Math.max(0, Math.min(1, mouse.x / width));
                    var yVal = Math.max(0, Math.min(1, 1.0 - (mouse.y / height))); // Flip Y (0 at bottom)

                    // Get the current fixed value (from the slider)
                    var fixed = 0.0;

                    switch (root.editMode) {
                    case NColorPickerDialog.EditMode.R:
                      fixed = root.selectedColor.r;
                      root.selectedColor = Qt.rgba(fixed, xVal, yVal, 1);
                      break;
                    case NColorPickerDialog.EditMode.G:
                      fixed = root.selectedColor.g;
                      root.selectedColor = Qt.rgba(xVal, fixed, yVal, 1);
                      break;
                    case NColorPickerDialog.EditMode.B:
                      fixed = root.selectedColor.b;
                      root.selectedColor = Qt.rgba(xVal, yVal, fixed, 1);
                      break;
                    case NColorPickerDialog.EditMode.H:
                      // Use stableHue to prevent flipping to -1
                      fixed = root.displayHue;
                      root.selectedColor = Qt.hsva(fixed, xVal, yVal, 1);
                      root.stableHue = fixed;
                      break;
                    case NColorPickerDialog.EditMode.S:
                      fixed = root.selectedColor.hsvSaturation;
                      root.selectedColor = Qt.hsva(xVal, fixed, yVal, 1);
                      // If we dragged Hue (xVal), update stableHue
                      root.stableHue = yVal;
                      break;
                    case NColorPickerDialog.EditMode.V:
                      fixed = root.selectedColor.hsvValue;
                      root.selectedColor = Qt.hsva(xVal, yVal, fixed, 1);
                      // If we dragged Hue (xVal), update stableHue
                      root.stableHue = xVal;
                      break;
                    }
                  }
                  onPressed: mouse => updateColor(mouse)
                  onPositionChanged: mouse => updateColor(mouse)
                }

                // Color Indicator
                Rectangle {
                  width: 10
                  height: 10
                  radius: Math.min(Style.iRadiusXS, width / 2)
                  color: "transparent"
                  border.color: root.selectedColor.hsvValue < 0.5 ? "white" : "black"
                  border.width: 1

                  // Find position based on the current color
                  readonly property point selectedPos: {
                    switch (root.editMode) {
                    case NColorPickerDialog.EditMode.R:
                      return Qt.point(root.selectedColor.g, root.selectedColor.b);
                    case NColorPickerDialog.EditMode.G:
                      return Qt.point(root.selectedColor.r, root.selectedColor.b);
                    case NColorPickerDialog.EditMode.B:
                      return Qt.point(root.selectedColor.r, root.selectedColor.g);
                    case NColorPickerDialog.EditMode.H:
                      return Qt.point(root.selectedColor.hsvSaturation, root.selectedColor.hsvValue);
                    case NColorPickerDialog.EditMode.S:
                      return Qt.point(root.displayHue, root.selectedColor.hsvValue);
                    case NColorPickerDialog.EditMode.V:
                      return Qt.point(root.displayHue, root.selectedColor.hsvSaturation);
                    default:
                      return Qt.point(0, 0);
                    }
                  }

                  // Convert values to pixel position
                  x: (selectedPos.x * parent.width) - width / 2
                  y: ((1.0 - selectedPos.y) * parent.height) - height / 2
                }

                // Redraw the border in case Color Indicator is near the edge
                Rectangle {
                  anchors.fill: parent
                  color: "transparent"
                  border.color: Color.mOutline
                  border.width: Style.borderS
                  antialiasing: false
                }
              }
            }
          }

          NCollapsible {
            id: paletteCollapsible
            label: I18n.tr("widgets.color-picker.palette.label")
            description: I18n.tr("widgets.color-picker.palette.description")

            Layout.fillWidth: true
            contentSpacing: Style.marginS

            GridLayout {
              Layout.alignment: Qt.AlignHCenter
              columns: 15
              columnSpacing: 6
              rowSpacing: 6

              NLabel {
                Layout.columnSpan: 15
                Layout.fillWidth: true
                description: I18n.tr("widgets.color-picker.palette.theme-colors")
              }

              Repeater {
                model: [
                  {
                    name: "mPrimary",
                    color: Color.mPrimary
                  },
                  {
                    name: "mSecondary",
                    color: Color.mSecondary
                  },
                  {
                    name: "mTertiary",
                    color: Color.mTertiary
                  },
                  {
                    name: "mError",
                    color: Color.mError
                  },
                  {
                    name: "mSurface",
                    color: Color.mSurface
                  },
                  {
                    name: "mSurfaceVariant",
                    color: Color.mSurfaceVariant
                  },
                  {
                    name: "mOutline",
                    color: Color.mOutline
                  }
                ]

                Rectangle {
                  width: 24
                  height: 24
                  radius: Style.iRadiusXXS
                  color: modelData.color
                  border.color: root.selectedColor.toString() === modelData.color.toString() ? Color.mPrimary : Color.mOutline
                  border.width: Math.max(1, root.selectedColor.toString() === modelData.color.toString() ? Style.borderM : Style.borderS)

                  MouseArea {
                    anchors.fill: parent
                    cursorShape: Qt.PointingHandCursor
                    hoverEnabled: true

                    onEntered: {
                      TooltipService.show(parent, modelData.name + "\n" + parent.color.toString().toUpperCase());
                    }
                    onExited: {
                      TooltipService.hide();
                    }
                    onClicked: {
                      root.selectedColor = modelData.color;
                      TooltipService.hide();
                    }
                  }
                }
              }

              NDivider {
                Layout.columnSpan: 15
                Layout.fillWidth: true
                Layout.topMargin: Style.marginXS
                Layout.bottomMargin: 0
              }

              Repeater {
                model: ColorList.colors

                Rectangle {
                  width: 24
                  height: 24
                  radius: Math.min(Style.iRadiusXS, width / 2)
                  color: modelData.color
                  border.color: root.selectedColor.toString() === modelData.color.toString() ? Color.mPrimary : Color.mOutline
                  border.width: root.selectedColor.toString() === modelData.color.toString() ? 2 : 1

                  MouseArea {
                    anchors.fill: parent
                    cursorShape: Qt.PointingHandCursor
                    hoverEnabled: true

                    onEntered: {
                      TooltipService.show(screen, parent, modelData.name + "\n" + parent.color.toString().toUpperCase(), "auto");
                    }
                    onExited: {
                      TooltipService.hide();
                    }
                    onClicked: {
                      root.selectedColor = modelData.color;
                      TooltipService.hide();
                    }
                  }
                }
              }
            }
          }
        }
      }

      RowLayout {
        Layout.fillWidth: true
        Layout.topMargin: 1
        Layout.bottomMargin: 1
        spacing: 10

        Item {
          Layout.fillWidth: true
        }

        NButton {
          id: cancelButton
          text: I18n.tr("widgets.color-picker.cancel")
          outlined: cancelButton.hovered ? false : true
          onClicked: {
            root.close();
          }
        }

        NButton {
          text: I18n.tr("widgets.color-picker.apply")
          icon: "check"
          onClicked: {
            root.colorSelected(root.selectedColor);
            root.close();
          }
        }
      }
    }
  }
}
