----------------------------------------------------------------------------------------------------
-- SeasonsRotationFrame
----------------------------------------------------------------------------------------------------
-- Purpose:  The frame for crop rotation info
-- Authors:  Rahkiin
--
-- Copyright (c) Realismus Modding, 2019
----------------------------------------------------------------------------------------------------

SeasonsRotationFrame = {}
local SeasonsRotationFrame_mt = Class(SeasonsRotationFrame, TabbedMenuFrameElement)

SeasonsRotationFrame.SHORT_SLOT = 3

SeasonsRotationFrame.CONTROLS = {
    CONTAINER = "container",
    ROTATION_1 = "rotationOne",
    ROTATION_2 = "rotationTwo",
    ROTATION_3 = "rotationThree",
    ROTATION_4 = "rotationFour",
}

function SeasonsRotationFrame:new(i18n, localStorage)
    local self = TabbedMenuFrameElement:new(nil, SeasonsRotationFrame_mt)

    self.i18n = i18n
    self.messageCenter = g_messageCenter
    self.environment = g_seasons.environment
    self.gameEnvironment = g_currentMission.environment
    self.weather = g_seasons.weather
    self.localStorage = localStorage

    self.cropRotation = g_seasons.growth.cropRotation

    self:registerControls(SeasonsRotationFrame.CONTROLS)

    return self
end

function SeasonsRotationFrame:copyAttributes(src)
    SeasonsRotationFrame:superClass().copyAttributes(self, src)

    self.i18n = src.i18n
    self.localStorage = src.localStorage
end

function SeasonsRotationFrame:initialize()
    self.elementToRotationIndex = {}
    self.elementToRotationPosition = {}
    self.stateToFruitType = {}
    self.fruitTypeToState = {}
    self.rotations = {
        self.rotationOne,
        self.rotationTwo,
        self.rotationThree,
        self.rotationFour,
    }

    local titles = {}
    table.insert(titles, self.i18n:getText("character_option_none"))
    table.insert(titles, self.i18n:getText("seasons_rotationCategory_0"))

    for _, fruitType in ipairs(g_fruitTypeManager:getFruitTypes()) do
        if fruitType.allowsSeeding then
            table.insert(titles, fruitType.fillType.title)
            self.stateToFruitType[#titles] = fruitType
            self.fruitTypeToState[fruitType] = #titles
        end
    end

    for rotIndex, rotation in pairs(self.rotations) do
        for i, element in ipairs(rotation) do
            element:setTexts(titles)
            self.elementToRotationIndex[element] = rotIndex
            self.elementToRotationPosition[element] = i
        end
    end

    self:setSettings(self.localStorage:getCropRotations())

    self:updateRotations()
end

function SeasonsRotationFrame:delete()
    self.elementToRotationIndex = {}
    self.elementToRotationPosition = {}

    SeasonsRotationFrame:superClass().delete(self)
end

function SeasonsRotationFrame:onFrameOpen()
    SeasonsRotationFrame:superClass().onFrameOpen(self)
end

function SeasonsRotationFrame:onFrameClose()
    SeasonsRotationFrame:superClass().onFrameClose(self)

    self.localStorage:saveIfDirty()
end

---Get the frame's main content element's screen size.
function SeasonsRotationFrame:getMainElementSize()
    return self.container.size
end

---Get the frame's main content element's screen position.
function SeasonsRotationFrame:getMainElementPosition()
    return self.container.absPosition
end

function SeasonsRotationFrame:updateRotations(updateStorage)
    for rotIndex, _ in pairs(self.rotations) do
        self:updateRotation(rotIndex)
    end

    if updateStorage ~= false then
        self.localStorage:setCropRotations(self:getSettings())
    end
end

---Update the rotation at given index
function SeasonsRotationFrame:updateRotation(rotIndex)

    for yearIndex, element in ipairs(self.rotations[rotIndex]) do
        local category = self:getYearCategory(rotIndex, yearIndex)
        local resultText = element.elements[#element.elements]

        local categoryText = element:getDescendantByName("categoryName")

        -- If this item is empty, do not calculate anything
        if category == nil then
            resultText:setText("-")
            categoryText:setText("-")
        elseif category == SeasonsCropRotation.CATEGORIES.FALLOW then
            resultText:setText("-")
            categoryText:setText(self.i18n:getText("character_option_none"))
        else
            local previousYear = self:getPreviousYear(rotIndex, yearIndex)
            local secondPreviousYear = self:getPreviousYear(rotIndex, previousYear)

            local n1 = self:getYearCategory(rotIndex, previousYear)
            local n2 = self:getYearCategory(rotIndex, secondPreviousYear)

            local multiplier = self.cropRotation:getRotationCategoryMultiplier(n2, n1, category)

            resultText:setText(string.format("%0.2f", multiplier))
            categoryText:setText(self.cropRotation:getCategoryName(category))
        end
    end
end

---Get the year index of the input before given one. Used so we support rotations smaller than 5 items
function SeasonsRotationFrame:getPreviousYear(rotIndex, yearIndex)
    local previous = yearIndex

    repeat
        previous = previous - 1
        if previous == 0 then
            previous = #self.rotations[rotIndex]
        end

        -- Do not keep wrapping around. Assume given item does have a category as well
        if previous == yearIndex then
            return yearIndex
        end
    until self:getYearCategory(rotIndex, previous) ~= nil

    return previous
end

---Get the category for given input
function SeasonsRotationFrame:getYearCategory(rotIndex, yearIndex)
    local state = self.rotations[rotIndex][yearIndex]:getState()

    if state == 1 then
        return nil -- "none"
    elseif state == 2 then
        return SeasonsCropRotation.CATEGORIES.FALLOW
    else
        local fruitType = self.stateToFruitType[state]
        return fruitType.rotation.category
    end
end

----------------------
-- Saving and loading
----------------------

---Set the settings for all rotations (fruit types)
function SeasonsRotationFrame:setSettings(settings)
    for rotIndex, rotation in pairs(settings) do
        for yearIndex, fruitName in pairs(rotation) do
            local state = 1
            if fruitName == "FALLOW" then
                state = 2
            else
                local fruitType = g_fruitTypeManager:getFruitTypeByName(fruitName)
                if fruitType ~= nil then
                    state = self.fruitTypeToState[fruitType]
                end
            end

            self.rotations[rotIndex][yearIndex]:setState(state)
        end
    end

    self:updateRotations(false)
end

---Get a list of rotations, for each a fruit type, fallow, or none
function SeasonsRotationFrame:getSettings()
    local settings = {}

    for rotIndex, rotation in pairs(self.rotations) do
        local rot = {}

        for yearIndex, element in ipairs(rotation) do
            local state = element:getState()
            if state == 1 then
                rot[yearIndex] = nil
            elseif state == 2 then
                rot[yearIndex] = "FALLOW"
            else
                rot[yearIndex] = self.stateToFruitType[state].fillType.name:upper()
            end
        end

        settings[rotIndex] = rot
    end

    return settings
end

----------------------
-- Events
----------------------

function SeasonsRotationFrame:onValueChanged(value, element)
    local rotIndex = self.elementToRotationIndex[element]

    self:updateRotation(rotIndex)

    self.localStorage:setCropRotations(self:getSettings())
end

SeasonsRotationFrame.L10N_SYMBOL = {
}
