--[[
Interface: 1.5.1.0 b6732

Copyright (C) GtX (Andy), 2019

Author: GtX | Andy
Date: 25.08.2019
Version: 1.0.0.0

Contact:
https://forum.giants-software.com
https://github.com/GtX-Andy

History:
V 1.0.0.0 @ 25.08.2019 - Release Version
V 1.1.0.0 @ 07.10.2019 - Fix bug where warning text did not reset on other placeables.

Important:
Free for use in other mods - no permission needed.
No changes are to be made to this script without permission from GtX | Andy

Frei verwendbar - keine erlaubnis nötig
An diesem Skript dürfen ohne Genehmigung von GtX | Andy keine Änderungen vorgenommen werden
]]


ObjectStorageGui = {}
ObjectStorageGui.BUILD_ID = 3

local ObjectStorageGui_mt = Class(ObjectStorageGui, YesNoDialog)

ObjectStorageGui.CONTROLS = {
    STANDARD_SCREEN = "standardScreen",
    FERMENTING_SCREEN = "fermentingScreen",
    FERMENTING_BUTTON = "fermentingButton",
    SET_STORAGE_AREA = "setStorageArea",
    SET_NUMBER_TO_SPAWN = "setNumberToSpawn",
    STORAGE_AREA_IMAGE = "storageAreaImage",
    HELP_WINDOW_TEXT = "helpWindowText",
    FILL_LEVEL_TEXT = "fillLevelText",
    CAPACITY_TEXT = "capacityText",
    NEXT_OBJECT_FILL_LEVEL_TEXT = "nextObjectFillLevelText",
    LOSE_FILL_LEVEL_TEXT = "loseFillLevelText",
    NUMBER_FERMENTING_TEXT = "numberFermentingText",
    AVAILABLE_HEADER = "availableHeader",
    CAPACITY_HEADER = "capacityHeader",
    NEXT_LEVEL_HEADER = "nextLevelHeader",
    TOTAL_LEVEL_HEADER = "totalLevelHeader",
    FERMENTING_HEADER = "fermentingHeader",
    NUM_TO_SPAWN_HEADER = "numToSpawnHeader",
    STORAGE_AREA_HEADER = "storageAreaHeader",
    FERMENTING_LIST = "fermentingList",
    LIST_ITEM_TEMPLATE = "listItemTemplate"
}

function ObjectStorageGui:new(target, custom_mt)
    local self = YesNoDialog:new(target, custom_mt or ObjectStorageGui_mt)

    self:registerControls(ObjectStorageGui.CONTROLS)

    self.storageAreas = {}
    self.selectionToIndex = {}

    self.currentStorageArea = nil

    self.numberToSpawn = 0
    self.updateTimer = 400

    self.forceSpawnUpdate = false
    self.fermentingScreenVisible = false
    self.fermentingScreenAvailable = false

    self.customTexts = nil
    self.fermetingBales = nil

    self.isServer = g_server ~= nil

    return self
end

function ObjectStorageGui:setCustomTexts(customTexts)
    self.customTexts = customTexts

    self.availableHeader:setText(customTexts.availableHeader)
    self.capacityHeader:setText(customTexts.capacityHeader)
    self.nextLevelHeader:setText(customTexts.nextLevelHeader)
    self.totalLevelHeader:setText(customTexts.totalLevelHeader)
    self.fermentingHeader:setText(customTexts.fermentingHeader)
    self.numToSpawnHeader:setText(customTexts.numToSpawnHeader)
    self.storageAreaHeader:setText(customTexts.storageAreaHeader)
end

function ObjectStorageGui:loadCallback(callback, target)
    self.target = target
    self.callback = callback
end

function ObjectStorageGui:loadStorageAreas(storageAreas)
    self.isMultiplayer = g_currentMission.missionDynamicInfo.isMultiplayer
    self.storageAreas = storageAreas

    self.helpWindowText:setText("")
    self.selectionToIndex = {}

    local storageNames = {}
    for fillTypeIndex, storageArea in pairs(storageAreas) do
        table.insert(storageNames, storageArea.title)
        table.insert(self.selectionToIndex, fillTypeIndex)
    end

    self.setStorageArea:setTexts(storageNames)
    self.setStorageArea:setState(1, true)
    self.setStorageArea:setDisabled(#storageNames < 2)
end

function ObjectStorageGui:onClickNumberToSpawn(index)
    self.numberToSpawn = (index - 1)
    self.yesButton:setDisabled(self.numberToSpawn == 0)
end

function ObjectStorageGui:onClickStorageAreaSelection(index)
    self.updateTimer = 400

    local storageArea, fillTypeIndex = self:getStorageArea(index)
    if storageArea ~= nil then
        self.currentFillTypeIndex = fillTypeIndex
        self.currentStorageArea = storageArea

        self.forceSpawnUpdate = true
        self:updateProtectionScreen()

        self:updateVisibleScreen(true)
        self.fermentingScreenAvailable = (self.isServer and storageArea.supportsFermenting)
        self.fermentingButton:setVisible(self.fermentingScreenAvailable)
    end
end

function ObjectStorageGui:updateProtectionScreen()
    local storageArea = self.currentStorageArea
    if storageArea ~= nil then
        self.spawnerVehicle = self.target:determineProtectionState(storageArea)

        if self.spawnerVehicle ~= nil then
            if self.spawnerVehicle ~= self.lastSetSpawnerVehicle then
                self.lastSetSpawnerVehicle = self.spawnerVehicle

                local vehicle = self.spawnerVehicle
                local farm = g_farmManager:getFarmById(vehicle:getActiveFarm())
                local storeItem = g_storeManager:getItemByXMLFilename(vehicle.configFileName:lower())

                local name = storeItem.name

                local brand = g_brandManager:getBrandByIndex(storeItem.brandIndex)
                if brand ~= nil then
                    name = brand.title .. " " .. name
                end

                local farmName = Utils.getNoNil(farm.name, "N/A")
                local warning = g_i18n:getText("warning_noFreeSpaceHere")
                local text = string.format("%s\n\n%s:  %s\n%s:  %s", warning, g_i18n:getText("ui_vehicle"), name, g_i18n:getText("ui_farmName"), farmName)

                self.storageAreaImage:setImageFilename(storeItem.imageFilename)
                self:updateHelpWindow(0, nil, text)

                self:updateSpawnSelector(storageArea, false, 0)
            end

            self:updateStorageScreen()
        else
            self.lastSetSpawnerVehicle = nil

            local storedObjects = #storageArea.storedObjects
            local freeSpawnPlaces = self.target:getNumFreeSpawnPlaces(storageArea, storedObjects)
            if freeSpawnPlaces ~= self.freeSpawnPlaces or self.forceSpawnUpdate then
                self:updateSpawnSelector(storageArea, not self.forceSpawnUpdate, freeSpawnPlaces)
                self.forceSpawnUpdate = false
            end

            self:updateHelpWindow(freeSpawnPlaces, storedObjects, nil)
            self:updateStorageScreen()
        end
    end
end

function ObjectStorageGui:updateStorageScreen()
    local storageArea = self.currentStorageArea
    if storageArea ~= nil then
        if self.spawnerVehicle == nil then
            self.storageAreaImage:setImageFilename(storageArea.image)
        end

        local objectCount = #storageArea.storedObjects

        local fillLevel = string.format("%d %s", objectCount, storageArea.unitType)
        self.fillLevelText:setText(fillLevel)

        local capacity = string.format("%d %s", storageArea.capacity, storageArea.unitType)
        self.capacityText:setText(capacity)

        local nextObjectFillLevel = 0.0
        if objectCount > 0 then
            nextObject = storageArea.storedObjects[objectCount]
            nextObjectFillLevel = nextObject.fillLevel
        end
        self.nextObjectFillLevelText:setText(g_i18n:formatNumber(nextObjectFillLevel, 0) .. " " .. storageArea.objectUnitType)

        local storedLitres = 0
        for _, objectData in pairs(storageArea.storedObjects) do
            storedLitres = storedLitres + objectData.fillLevel
        end
        self.loseFillLevelText:setText(g_i18n:formatNumber(storedLitres, 0) .. " " .. storageArea.objectUnitType)

        if storageArea.supportsFermenting then
            if self.isMultiplayer then
                self.numberFermentingText:setText(math.max(self.target.numberFermenting, 0) .. " " .. storageArea.unitType)
            else
                local numberFermenting = 0
                for i = 1, #storageArea.storedObjects do
                    local objectData = storageArea.storedObjects[i]

                    if objectData.isFermenting and objectData.fermentingProcess ~= nil then
                        if objectData.fermentingProcess < 1 then
                            numberFermenting = numberFermenting + 1
                        end
                    end
                end

                self.numberFermentingText:setText(numberFermenting .. " " .. storageArea.unitType)
            end
        else
            self.numberFermentingText:setText("N / A")
        end
    end
end

function ObjectStorageGui:updateSpawnSelector(storageArea, keepState, freeSpawnPlaces)
    local oldState = 1

    if freeSpawnPlaces == nil then
        freeSpawnPlaces = self.target:getNumFreeSpawnPlaces(storageArea, #storageArea.storedObjects)
    end

    self.freeSpawnPlaces = freeSpawnPlaces

    if keepState then
        oldState = self.setNumberToSpawn.state
    end

    local spawnSelector = {}
    local spawnSelectorCount = 0
    for i = 1, freeSpawnPlaces + 1 do
        spawnSelector[i] = string.format("%d  /  %d", i - 1, freeSpawnPlaces)
        spawnSelectorCount = spawnSelectorCount + 1
    end

    self.setNumberToSpawn:setTexts(spawnSelector)
    self.setNumberToSpawn:setState(math.min(oldState, spawnSelectorCount), true)
    self.setNumberToSpawn:setDisabled(spawnSelectorCount < 2)
end

function ObjectStorageGui:createFermentingScreen()
    self.fermentingList:deleteListItems()

    local storageArea = self.currentStorageArea
    if storageArea ~= nil then
        local colourCount = 0

        self.currentObjectIndex = 0
        self.currentObjectData = {}

        self.fermetingBales = {}

        for i = #storageArea.storedObjects, 1, -1 do
            local objectData = storageArea.storedObjects[i]

            if objectData.isFermenting and objectData.fermentingProcess ~= nil then
                if objectData.fermentingProcess < 1 then
                    self.currentObjectIndex = i
                    self.currentObjectData = objectData
                    self.fermetingBales[objectData] = {}

                    local newRow = self.listItemTemplate:clone(self.fermentingList)
                    newRow:updateAbsolutePosition()

                    if colourCount % 2 ~= 0 then
                        newRow:setImageColor(nil, 0.118, 0.116, 0.115, 0.20)
                    else
                        newRow:setImageColor(nil, 0.718, 0.716, 0.715, 0.0625)
                    end

                    colourCount = colourCount + 1

                    self.currentObjectData = nil
                end
            end
        end

        self.currentObjectIndex = nil
    else
        self.fermetingBales = nil
    end
end

function ObjectStorageGui:onCreateBale(element)
    if self.currentObjectData ~= nil then
        element:setText(self.currentObjectIndex)
    end
end

function ObjectStorageGui:onCreatePercent(element)
    if self.currentObjectData ~= nil then
        local percent = string.format("%.2f", self.currentObjectData.fermentingProcess * 100)
        element:setText(percent)

        self.fermetingBales[self.currentObjectData].percentElement = element

        local r, g, b = self:getFermentingColour(self.currentObjectData.fermentingProcess)
        element:setTextColor(r, g, b, 1)
    end
end

function ObjectStorageGui:onCreateTime(element)
    if self.currentObjectData ~= nil then
        local value = math.max(0, 1.0 - self.currentObjectData.fermentingProcess)
        local remainingTime = value * (g_seasons.environment.daysPerSeason / 3 * 24) * 60
        local hours = math.floor(remainingTime / 60)
        local minutes = remainingTime - (hours * 60)
        local hoursMinutes = string.format("%02d:%02d h", hours, minutes)
        element:setText(hoursMinutes)

        self.fermetingBales[self.currentObjectData].timeElement = element

        local r, g, b = self:getFermentingColour(self.currentObjectData.fermentingProcess)
        element:setTextColor(r, g, b, 1)
    end
end

function ObjectStorageGui:onCreateFillType(element)
    if self.currentObjectData ~= nil then
        local fillType = g_fillTypeManager:getFillTypeByIndex(self.currentObjectData.oldFillTypeIndex)
        element:setText(fillType.title)
    end
end

function ObjectStorageGui:updateFermentingScreen()
    if self.fermetingBales ~= nil then
        for objectData, elementData in pairs (self.fermetingBales) do
            local fermentingProcess = 1
            if objectData.fermentingProcess ~= nil then
                fermentingProcess = objectData.fermentingProcess
            end

            local percent = string.format("%.2f", fermentingProcess * 100)
            local r, g, b = self:getFermentingColour(fermentingProcess)

            elementData.percentElement:setText(percent)
            elementData.percentElement:setTextColor(r, g, b, 1)

            local value = math.max(0, 1.0 - fermentingProcess)
            local remainingTime = value * (g_seasons.environment.daysPerSeason / 3 * 24) * 60
            local hours = math.floor(remainingTime / 60)
            local minutes = remainingTime - (hours * 60)
            local hoursMinutes = string.format("%02d:%02d h", hours, minutes)

            elementData.timeElement:setText(hoursMinutes)
            elementData.timeElement:setTextColor(r, g, b, 1)
        end
    end
end

function ObjectStorageGui:update(dt)
    ObjectStorageGui:superClass().update(self, dt)

    self.updateTimer = self.updateTimer - 1

    local isStandardScreen = not self.fermentingScreenVisible

    if self.updateTimer < 0 then
        self.updateTimer = 400

        if isStandardScreen then
            self:updateProtectionScreen()
        else
            self:updateFermentingScreen()
        end
    end

    if isStandardScreen then
        if Input.isMouseButtonPressed(Input.MOUSE_BUTTON_WHEEL_UP) then
            self.setNumberToSpawn:setState(self.setNumberToSpawn.state + 1, true)
        elseif Input.isMouseButtonPressed(Input.MOUSE_BUTTON_WHEEL_DOWN) then
            self.setNumberToSpawn:setState(self.setNumberToSpawn.state - 1, true)
        end
    end
end

function ObjectStorageGui:getStorageArea(selection, fillTypeIndex)
    if selection ~= nil then
        fillTypeIndex = self.selectionToIndex[selection]
    end

    return self.storageAreas[fillTypeIndex], fillTypeIndex
end

function ObjectStorageGui:updateHelpWindow(freeSpawnPlaces, storedObjects, text)
    if freeSpawnPlaces == 0 then
        if text ~= nil then
            self.helpWindowText:setText(text)
        else
            if storedObjects > 0 then
                self.helpWindowText:setText(g_i18n:getText("warning_noFreeSpaceHere"))
            else
                self.helpWindowText:setText("")
            end
        end
    else
        self.helpWindowText:setText("")
    end
end

function ObjectStorageGui:getFermentingColour(percent)
    local numberPercent = tonumber(percent)
    local r, g, b = 0.2122, 0.5271, 0.0307

    if numberPercent <= 0.40 then
        r, g, b = 0.8069, 0.0097, 0.0097
    elseif numberPercent <= 0.70 then
        r, g, b = 0.9301, 0.2874, 0.0130
    end

    return r, g, b
end

function ObjectStorageGui:updateVisibleScreen(isStandard)
    self.standardScreen:setVisible(isStandard)
    self.fermentingScreenVisible = not isStandard
    self.fermentingScreen:setVisible(self.fermentingScreenVisible)
end

function ObjectStorageGui:onClickOk()
    if self.numberToSpawn < 1 or self.callback == nil then
        return true
    end

    if self.target ~= nil then
        self.callback(self.target, self.currentFillTypeIndex, self.numberToSpawn)
    else
        print("  Error: [ObjectStorageGui]  Target is missing.")
    end

    self:close()
end

function ObjectStorageGui:onClickBack(forceBack, usedMenuButton)
    self:close()
end

function ObjectStorageGui:onClickActivate()
    if not self.fermentingScreenAvailable then
        return true
    end

    local setStandardScreen = self.fermentingScreenVisible
    self:updateVisibleScreen(setStandardScreen)

    if setStandardScreen then
        self:updateStorageScreen()
    else
        self:createFermentingScreen()
    end
end
