require "ISUI/ISPanel"
require "ISUI/ISTextEntryBox"
require "ISUI/ISLabel"
require "MS/SettingPanel/MS_SquareButton"
require "MS/SettingPanel/MS_LongButton"
require "MS/MS_IndicatorTooltipManager"

MS_IndicatorTooltipOpacityDialog = ISPanel:derive("MS_IndicatorTooltipOpacityDialog")

local FONT_HGT_SMALL = getTextManager():getFontHeight(UIFont.Small)
local OPACITY_MIN_VALUE = 0
local OPACITY_MAX_VALUE = 100
local OPACITY_STEP = 5

MS_IndicatorTooltipOpacityDialog.CurrentPanel = nil

function MS_IndicatorTooltipOpacityDialog.calculateRequiredSize()
    local rowHeight = math.floor(FONT_HGT_SMALL * 1.5)
    local titleBarHeight = math.floor(FONT_HGT_SMALL * 1.2)
    local buttonHeight = math.floor(FONT_HGT_SMALL * 1.2)
    local padding = math.floor(FONT_HGT_SMALL * 0.2)
    local width = 360
    local height = titleBarHeight + padding * 4 + rowHeight + buttonHeight
    return { width = width, height = height }
end

local function sanitizeOpacityValue(rawValue, fallback)
    return MS_IndicatorTooltipManager.sanitizeOpacity(rawValue, fallback or 100)
end

local function stepOpacityValue(currentValue, delta)
    return sanitizeOpacityValue((tonumber(currentValue) or 100) + delta, currentValue)
end

function MS_IndicatorTooltipOpacityDialog.openForPlayer(playerIndex, anchorX, anchorY)
    if MS_IndicatorTooltipOpacityDialog.CurrentPanel then
        MS_IndicatorTooltipOpacityDialog.CurrentPanel:close()
    end

    local screenWidth = getCore():getScreenWidth()
    local screenHeight = getCore():getScreenHeight()
    local size = MS_IndicatorTooltipOpacityDialog.calculateRequiredSize()

    local x = anchorX or math.floor((screenWidth - size.width) / 2)
    local y = anchorY or math.floor((screenHeight - size.height) / 2)

    local panel = MS_IndicatorTooltipOpacityDialog:new(x, y, nil, nil, playerIndex)
    panel:initialise()
    panel:addToUIManager()
    panel:setVisible(true)

    panel:setX(math.max(10, math.min(screenWidth - panel:getWidth() - 10, panel:getX())))
    panel:setY(math.max(10, math.min(screenHeight - panel:getHeight() - 10, panel:getY())))

    MS_IndicatorTooltipOpacityDialog.CurrentPanel = panel
    return panel
end

function MS_IndicatorTooltipOpacityDialog:initialise()
    ISPanel.initialise(self)
end

function MS_IndicatorTooltipOpacityDialog:new(x, y, width, height, playerIndex)
    local size = MS_IndicatorTooltipOpacityDialog.calculateRequiredSize()
    width = width or size.width
    height = height or size.height

    local o = ISPanel:new(x, y, width, height)
    setmetatable(o, self)
    self.__index = self

    o.playerIndex = playerIndex
    o.padding = math.floor(FONT_HGT_SMALL * 0.2)
    o.titleBarHeight = math.floor(FONT_HGT_SMALL * 1.2)
    o.rowHeight = math.floor(FONT_HGT_SMALL * 1.5)
    o.buttonHeight = math.floor(FONT_HGT_SMALL * 1.2)
    o.buttonSize = math.floor(FONT_HGT_SMALL * 1.2)
    o.moving = false
    o.moveWithMouse = false
    o:noBackground(true)

    o.minusIcon = getTexture("media/ui/ModernStatus/SettingPanel/Icon_Minus.png")
    o.plusIcon = getTexture("media/ui/ModernStatus/SettingPanel/Icon_Plus.png")
    o.title = getText("IGUI_ModernStatus_EnterTooltipOpacity")

    o.titlebarbkg = NinePatchTexture and NinePatchTexture.getSharedTexture and NinePatchTexture.getSharedTexture("media/ui/ModernStatus/SettingPanel/TitleBarBG.png") or nil
    o.contentbkg = NinePatchTexture and NinePatchTexture.getSharedTexture and NinePatchTexture.getSharedTexture("media/ui/ModernStatus/SettingPanel/ContentBackground.png") or nil

    return o
end

function MS_IndicatorTooltipOpacityDialog:close()
    if MS_IndicatorTooltipOpacityDialog.CurrentPanel == self then
        MS_IndicatorTooltipOpacityDialog.CurrentPanel = nil
    end
    self:setVisible(false)
    self:removeFromUIManager()
end

function MS_IndicatorTooltipOpacityDialog:createChildren()
    self:createTitleBar()
    self:createContent()
    self:createBottomButtons()
end

function MS_IndicatorTooltipOpacityDialog:createTitleBar()
    local titleX = math.floor((self.width - getTextManager():MeasureStringX(UIFont.Small, self.title)) / 2)
    self.titleLabel = ISLabel:new(titleX, (self.titleBarHeight - FONT_HGT_SMALL) / 2, self.titleBarHeight, self.title, 1, 1, 1, 1, UIFont.Small, true)
    self.titleLabel:initialise()
    self:addChild(self.titleLabel)
end

function MS_IndicatorTooltipOpacityDialog:createLabel(text, y)
    local label = ISLabel:new(self.padding, y + ((self.rowHeight - FONT_HGT_SMALL) / 2), 0, text, 1, 1, 1, 1, UIFont.Small, true)
    label:initialise()
    self:addChild(label)
    return label
end

function MS_IndicatorTooltipOpacityDialog:createOpacityControl(x, y, labelText, currentValue, onValueChanged)
    self:createLabel(labelText, y)

    local textBoxWidth = getTextManager():MeasureStringX(UIFont.Small, "100") + self.padding * 6
    local textBox

    local function updateTextBox()
        textBox:setText(tostring(sanitizeOpacityValue(currentValue(), 100)))
    end

    local function commitValue(rawValue)
        local value = sanitizeOpacityValue(rawValue, currentValue())
        onValueChanged(value)
        updateTextBox()
        return value
    end

    textBox = ISTextEntryBox:new(tostring(sanitizeOpacityValue(currentValue(), 100)), x + self.buttonSize + self.padding, y + ((self.rowHeight - self.buttonSize) / 2), textBoxWidth, self.buttonSize)
    textBox:initialise()
    textBox:instantiate()
    textBox:setOnlyNumbers(true)
    textBox.borderColor = {r = 0.4, g = 0.4, b = 0.4, a = 0.0}
    textBox.backgroundColor = {r = 0.1, g = 0.1, b = 0.1, a = 0.0}
    textBox.onCommandEntered = function() commitValue(textBox:getText()) end
    textBox.onOtherKey = function(key)
        if key == 28 then
            commitValue(textBox:getText())
        end
    end
    textBox.onMouseDownOutside = function()
        commitValue(textBox:getText())
    end
    textBox.prerender = function(control)
        ISTextEntryBox.prerender(control)
        if not control:isFocused() then
            updateTextBox()
        end
    end
    self:addChild(textBox)

    local decBtn = MS_SquareButton:new(x, y + ((self.rowHeight - self.buttonSize) / 2), self.buttonSize, self.minusIcon, self, function()
        commitValue(stepOpacityValue(currentValue(), -OPACITY_STEP))
    end)
    decBtn:initialise()
    self:addChild(decBtn)

    local incBtn = MS_SquareButton:new(x + self.buttonSize + self.padding + textBoxWidth + self.padding, y + ((self.rowHeight - self.buttonSize) / 2), self.buttonSize, self.plusIcon, self, function()
        commitValue(stepOpacityValue(currentValue(), OPACITY_STEP))
    end)
    incBtn:initialise()
    self:addChild(incBtn)

    return { decBtn = decBtn, textBox = textBox, incBtn = incBtn, commitValue = commitValue }
end

function MS_IndicatorTooltipOpacityDialog:createContent()
    self.pendingOpacity = sanitizeOpacityValue(MS_IndicatorTooltipManager.getOpacity(self.playerIndex), 100)

    local middleX = math.floor(self.width / 2)
    local controlX = middleX + self.padding
    local y = self.titleBarHeight + self.padding * 2

    self.opacityControls = self:createOpacityControl(controlX, y, getText("IGUI_ModernStatus_OpacityLabel"),
        function() return self.pendingOpacity end,
        function(value) self.pendingOpacity = sanitizeOpacityValue(value, self.pendingOpacity) end)
end

function MS_IndicatorTooltipOpacityDialog:createBottomButtons()
    local buttonWidth = math.floor((self:getWidth() - self.padding * 4) / 3)
    local buttonY = self:getHeight() - self.buttonHeight - self.padding

    self.backButton = MS_LongButton:new(self.padding, buttonY, buttonWidth, self.buttonHeight, getText("IGUI_ModernStatus_Back"), self, MS_IndicatorTooltipOpacityDialog.onBackClick)
    self.backButton:initialise()
    self.backButton:setActive(true)
    self.backButton:setActiveColor(0.8, 0.2, 0.2)
    self:addChild(self.backButton)

    self.applyButton = MS_LongButton:new(self.backButton:getRight() + self.padding, buttonY, buttonWidth, self.buttonHeight, getText("IGUI_ModernStatus_Apply"), self, MS_IndicatorTooltipOpacityDialog.onApplyClick)
    self.applyButton:initialise()
    self.applyButton:setActive(true)
    self.applyButton:setActiveColor(0.2, 0.65, 0.2)
    self:addChild(self.applyButton)

    self.acceptButton = MS_LongButton:new(self.applyButton:getRight() + self.padding, buttonY, buttonWidth, self.buttonHeight, getText("IGUI_ModernStatus_Accept"), self, MS_IndicatorTooltipOpacityDialog.onAcceptClick)
    self.acceptButton:initialise()
    self.acceptButton:setActive(true)
    self.acceptButton:setActiveColor(0.2, 0.75, 0.2)
    self:addChild(self.acceptButton)
end

function MS_IndicatorTooltipOpacityDialog:applyValues(closeAfter)
    if self.opacityControls and self.opacityControls.commitValue then
        self.opacityControls.commitValue(self.opacityControls.textBox:getText())
    end

    MS_IndicatorTooltipManager.updateSetting(self.playerIndex, "opacity", self.pendingOpacity)

    if closeAfter then
        self:close()
    end
end

function MS_IndicatorTooltipOpacityDialog:onBackClick()
    self:close()
end

function MS_IndicatorTooltipOpacityDialog:onApplyClick()
    self:applyValues(false)
end

function MS_IndicatorTooltipOpacityDialog:onAcceptClick()
    self:applyValues(true)
end

function MS_IndicatorTooltipOpacityDialog:onMouseDown(x, y)
    if y <= self.titleBarHeight then
        self.moving = true
        self:setCapture(true)
        return true
    end
    return ISPanel.onMouseDown(self, x, y)
end

function MS_IndicatorTooltipOpacityDialog:onMouseUp(x, y)
    if self.moving then
        self.moving = false
        self:setCapture(false)
    end
    return ISPanel.onMouseUp(self, x, y)
end

function MS_IndicatorTooltipOpacityDialog:onMouseMove(dx, dy)
    if self.moving then
        self:setX(self.x + dx)
        self:setY(self.y + dy)
        return true
    end
    return ISPanel.onMouseMove(self, dx, dy)
end

function MS_IndicatorTooltipOpacityDialog:onMouseMoveOutside(dx, dy)
    if self.moving then
        self:setX(self.x + dx)
        self:setY(self.y + dy)
        return true
    end
    return ISPanel.onMouseMoveOutside(self, dx, dy)
end

function MS_IndicatorTooltipOpacityDialog:onMouseUpOutside(x, y)
    if self.moving then
        self.moving = false
        self:setCapture(false)
    end
    return ISPanel.onMouseUpOutside(self, x, y)
end

function MS_IndicatorTooltipOpacityDialog:prerender()
    local titlebarbkg = self.titlebarbkg
    if not titlebarbkg and NinePatchTexture and NinePatchTexture.getSharedTexture then
        titlebarbkg = NinePatchTexture.getSharedTexture("media/ui/ModernStatus/SettingPanel/TitleBarBG.png")
        self.titlebarbkg = titlebarbkg
    end

    if titlebarbkg and titlebarbkg.render then
        titlebarbkg:render(self:getAbsoluteX(), self:getAbsoluteY(), self:getWidth(), self.titleBarHeight, 0.5, 0.5, 0.5, 0.95)
    else
        self:drawRect(0, 0, self:getWidth(), self.titleBarHeight, 0.95, 0.5, 0.5, 0.5)
    end

    local contentbkg = self.contentbkg
    if not contentbkg and NinePatchTexture and NinePatchTexture.getSharedTexture then
        contentbkg = NinePatchTexture.getSharedTexture("media/ui/ModernStatus/SettingPanel/ContentBackground.png")
        self.contentbkg = contentbkg
    end

    if contentbkg and contentbkg.render then
        contentbkg:render(self:getAbsoluteX(), self:getAbsoluteY() + self.titleBarHeight, self:getWidth(), self:getHeight() - self.titleBarHeight, 0.12, 0.12, 0.12, 0.98)
    else
        self:drawRect(0, self.titleBarHeight, self:getWidth(), self:getHeight() - self.titleBarHeight, 0.98, 0.12, 0.12, 0.12)
    end
end

return MS_IndicatorTooltipOpacityDialog
