----------------------------------------------------------------------------------------------------
-- SeasonsAnimalsUI
----------------------------------------------------------------------------------------------------
-- Purpose:  Animal UI changes
--
-- Copyright (c) Realismus Modding, 2019
----------------------------------------------------------------------------------------------------

SeasonsAnimalsUI = {}

local SeasonsAnimalsUI_mt = Class(SeasonsAnimalsUI)

function SeasonsAnimalsUI:new(mission, i18n)
    local self = setmetatable({}, SeasonsAnimalsUI_mt)

    self.i18n = i18n
    self.mission = mission
    self.isServer = mission:getIsServer()

    SeasonsModUtil.appendedFunction(AnimalScreen,                   "applyDataToItemRow",               self.inj_animalScreen_applyDataToItemRow)
    SeasonsModUtil.appendedFunction(AnimalScreen,                   "updateInfoBox",                    self.inj_animalScreen_updateInfoBox)
    SeasonsModUtil.appendedFunction(InGameMenuAnimalsFrame,         "displayLivestock",                 self.inj_inGameMenuAnimalsFrame_displayLivestock)
    SeasonsModUtil.overwrittenFunction(InGameMenuAnimalsFrame,      "displayHorse",                     self.inj_inGameMenuAnimalsFrame_displayHorse)
    SeasonsModUtil.overwrittenFunction(InGameMenuAnimalsFrame,      "updateAnimalData",                 self.inj_inGameMenuAnimalsFrame_updateAnimalData)

    -- UI
    SeasonsModUtil.overwrittenConstant(InGameMenuAnimalsFrame.L10N_SYMBOL, "LIVESTOCK_PRODUCTIVITY", "seasons_statistic_health")
    SeasonsModUtil.overwrittenConstant(self.mission.inGameMenu.pageAnimals.animalReproductionRateText.parent.elements[1], "text", self.i18n:getText("seasons_statistic_age"))
    SeasonsModUtil.overwrittenConstant(self.mission.inGameMenu.pageAnimals.livestockAttributesLayout.elements[1], "text", self.i18n:getText("seasons_statistic_health"))
    SeasonsModUtil.overwrittenConstant(self.mission.inGameMenu.pageAnimals.livestockAttributesLayout.elements[1], "text", self.i18n:getText("seasons_statistic_health"))

    return self
end

function SeasonsAnimalsUI:delete()
end

function SeasonsAnimalsUI:load()
end

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

----------------------
-- Injections
----------------------

local function formatSex(isFemale)
    return isFemale and g_i18n:getText("seasons_animal_sex_female_short") or g_i18n:getText("seasons_animal_sex_male_short")
end

local function formatAge(age)
    return string.format("%.1f %s", age, g_i18n:getText("seasons_animal_age"))
end

---Update text in the animal screen lists
function SeasonsAnimalsUI.inj_animalScreen_applyDataToItemRow(animalScreen, listRow, animalItem)
    local stateLabel = listRow:getDescendantByName(AnimalScreen.ITEM_STATE)

    local age, weight, isFemale, isHorse = -1, -1, false, false

    if animalItem.animalId ~= nil then -- real animal
        local animal = NetworkUtil.getObject(animalItem.animalId)
        age = animal.seasons_age
        weight = animal:getWeightWithUnborn()
        isFemale = animal.seasons_isFemale
        isHorse = animal:isa(Horse)
    else -- new animal
        local subType = animalItem.subType
        age = subType.storeInfo.buyAge
        weight = subType.storeInfo.buyWeight
        isFemale = subType.storeInfo.buyIsFemale
        isHorse = subType.rideableFileName ~= ""
    end

    if isHorse then
        return
    end

    local stateText = animalScreen.l10n:getText("animal_new")
    if animalItem.state == AnimalItem.STATE_STOCK then
        stateText = animalScreen.l10n:getText("animal_stock")
    end

    local formattedWeight = SeasonsModUtil.formatSmallWeight(weight, 0, false)
    stateLabel:setText(string.format("%s, %0.1f %s, %s", stateText, age, animalScreen.l10n:getText("seasons_animal_age"), formattedWeight))

    local nameLabel = listRow:getDescendantByName(AnimalScreen.ITEM_NAME)
    nameLabel:setText(string.format("%s (%s)", nameLabel.text, formatSex(isFemale)))
end

---Add custom info to the animal on the animal screen
function SeasonsAnimalsUI.inj_animalScreen_updateInfoBox(animalScreen, isSourceSelected)
    local animal = nil
    if isSourceSelected then
        local dataIndex = animalScreen.listSource:getSelectedDataIndex()
        animal = animalScreen.sourceDataSource:getItem(dataIndex)
    else
        local dataIndex = animalScreen.listTarget:getSelectedDataIndex()
        animal = animalScreen.targetDataSource:getItem(dataIndex)
    end

    if animal ~= nil then

        local isFemale = animal.subType.storeInfo.buyIsFemale
        if animal.animalId ~= nil then
            local animal = NetworkUtil.getObject(animal.animalId)
            isFemale = animal.seasons_isFemale
        end

        animalScreen.animalTitle:setText(string.format("%s (%s)", animalScreen.animalTitle.text, formatSex(isFemale)))

        local elements = animalScreen.infoBox.elements
        local infoTextBox = elements[#elements]

        infoTextBox:setText(animalScreen.l10n:getText("seasons_animalInfo_" ..  animal.subType.fillTypeDesc.name))
    end
end

---Update livestock display function with new weight and properties
function SeasonsAnimalsUI.inj_inGameMenuAnimalsFrame_displayLivestock(frame, animals, livestockHusbandry)
    -- Initial loading... the ListElement is a terrible and inefficient thing.
    if g_gui.currentGuiName ~= "InGameMenu" then
        return
    end

    local animal = animals[1]
    local subType = animal:getSubType()

    frame.animalDetailTypeNameText:setText(string.format("%s (%s)", subType.storeInfo.shopItemName, formatSex(animal.seasons_isFemale)))
    frame.animalDetailTypeCountText:setText(SeasonsModUtil.formatSmallWeight(animal:getWeightWithUnborn(), 0, false))
    frame.animalReproductionRateText:setText(formatAge(animal.seasons_age))

    if animal.seasons_isFemale then
        local text = frame.animalTimeTillNextAnimalText
        if animal.seasons_age < animal.subType.breeding.fertileAge then
            text:setText(frame.l10n:getText("seasons_ui_notFertile"))
        elseif animal.seasons_timeUntilBirth <= 0 then
            text:setText("-") -- TODO loca
        else
            text:setText(formatAge(animal.seasons_timeUntilBirth))
        end
    else
        frame.animalTimeTillNextAnimalText:setText("-")
    end

    -- Put the list of food types on a single line
    local original = frame.detailDescriptionText.text
    local oneLine = string.gsub(original, "%)\n%-", ");")
    oneLine = string.gsub(oneLine, ":\n%-", ":")

    local totalFeed = g_seasons.animals:calculateAnnualFeedAmount(livestockHusbandry)
    oneLine = oneLine .. "\n" .. string.format(frame.l10n:getText("seasons_ui_animalsFoodInfo"), totalFeed)

    frame.detailDescriptionText:setText(oneLine)
end

---When showing a horse, the monetary value is what you would get at the end of the day
function SeasonsAnimalsUI.inj_inGameMenuAnimalsFrame_displayHorse(frame, superFunc, animal, horseHusbandry)
    local old = animal.getValue
    animal.getValue = function()
        return animal:getDayReward()
    end

    superFunc(frame, animal, horseHusbandry)

    animal.getValue = old
end

local function makeAnimalData(animal, husbandry)
    local subType = animal:getSubType()

    return {
        isHeader = false,
        isHorse = false,
        count = SeasonsModUtil.formatSmallWeight(animal:getWeightWithUnborn(), 0, false),
        statusValue = husbandry:getGlobalProductionFactor(),
        iconFilename = subType.fillTypeDesc.hudOverlayFilename,
        nameText = string.format("%s (%s)", subType.storeInfo.shopItemName, formatSex(animal.seasons_isFemale)),
        husbandry = husbandry,
        animals = {animal}
    }
end

local function makeHorseData(horse, husbandry)
    local subType = horse:getSubType()

    return {
        isHeader = false,
        isHorse = true,
        count = 1,
        statusValue = MathUtil.clamp(horse:getTodaysRidingTime() / Horse.DAILY_TARGET_RIDING_TIME, 0, 1),
        iconFilename = subType.fillTypeDesc.hudOverlayFilenameSmall,
        nameText = horse:getName(),
        husbandry = husbandry,
        horse = horse
    }
end

---Override generating of the list to show an item per animal instead of groupings
function SeasonsAnimalsUI.inj_inGameMenuAnimalsFrame_updateAnimalData(frame, superFunc)
    local data = {}

    local husbandries = frame:getSortedFarmHusbandries()
    for _, husbandry in ipairs(husbandries) do
        if husbandry:getNumOfAnimals() > 0 then
            local headerData = {isHeader = true, nameText = husbandry:getName()}
            table.insert(data, headerData)
        end

        if husbandry:getAnimalType() == InGameMenuAnimalsFrame.HORSE_TYPE then
            local horses = husbandry:getAnimals()
            for _, horse in ipairs(horses) do
                table.insert(data, makeHorseData(horse, husbandry))
            end
        else
            local animals = husbandry:getAnimals()
            for _, animal in ipairs(animals) do
                table.insert(data, makeAnimalData(animal, husbandry))
            end
        end
    end

    frame.animalsDataSource:setData(data)
end
