-- Variablen

Produktion = {}

Produktion.debug = true
Produktion.debugPrefix = "[LS25-Mine] "

Produktion.fillType = "PAYDIRT"
Produktion.amountPerHour = 40000
Produktion.debugProductionInterval = 30000
Produktion.animationAcceleration = 0.25
Produktion.animationSpeedMax = 1.0


-- Registrierung

function Produktion.prerequisitesPresent(specializations)
    return true
end

function Produktion.registerFunctions(placeableType)
    SpecializationUtil.registerFunction(placeableType, "produce", Produktion.produce)
    SpecializationUtil.registerFunction(placeableType, "updateAnimationState", Produktion.updateAnimationState)
end

function Produktion.registerEventListeners(placeableType)
    SpecializationUtil.registerEventListener(placeableType, "onLoad", Produktion)
    SpecializationUtil.registerEventListener(placeableType, "onUpdate", Produktion)
    SpecializationUtil.registerEventListener(placeableType, "onFinalizePlacement", Produktion)
end

function Produktion.registerXMLPaths(schema, basePath)
    schema:setXMLSpecializationType("Produktion")
    schema:register(XMLValueType.STRING, basePath .. ".produktion#fillType", "Fill type produced by this mine", Produktion.fillType)
    schema:register(XMLValueType.FLOAT, basePath .. ".produktion#amountPerHour", "Amount produced per game hour", Produktion.amountPerHour)
    schema:setXMLSpecializationType()
end


-- Initialisierung

function Produktion:onLoad(savegame)
    local xmlFillType = self.xmlFile:getValue("placeable.produktion#fillType", Produktion.fillType)
    local xmlAmountPerHour = self.xmlFile:getValue("placeable.produktion#amountPerHour", Produktion.amountPerHour)
self.produktionFillType = xmlFillType
    if self.produktionFillType == nil or self.produktionFillType == "" then
        self.produktionFillType = Produktion.fillType
    end

    self.produktionAmountPerHour = tonumber(xmlAmountPerHour)
    if self.produktionAmountPerHour == nil then
        self.produktionAmountPerHour = Produktion.amountPerHour
    end
    self.produktionAnimationSpeed = 0
    self.produktionAnimationTargetSpeed = 0
    self.produktionWasFull = false
    self.produktionBuffer = 0
    self.produktionDebugTimer = 0
    self.produktionDebugAmount = 0

    if self.raiseActive ~= nil then
        self:raiseActive()
    end

    if Produktion.debug then
        print(Produktion.debugPrefix .. "Konfiguration: " .. tostring(self.produktionFillType) .. " / " .. tostring(self.produktionAmountPerHour) .. " L/h")
    end
end

function Produktion:onFinalizePlacement()
    if self.raiseActive ~= nil then
        self:raiseActive()
    end

    if Produktion.debug then
        print(Produktion.debugPrefix .. "Placeable aktiv: " .. tostring(self.produktionFillType))
    end
end


-- Update

function Produktion:onUpdate(dt)
local timeScale = 1

    if g_currentMission ~= nil and g_currentMission.missionInfo ~= nil and g_currentMission.missionInfo.timeScale ~= nil then
        timeScale = g_currentMission.missionInfo.timeScale
    end

    local gameTimeHours = (dt * timeScale) / 3600000
    local amountToProduce = self.produktionAmountPerHour * gameTimeHours

    if Produktion.debug then
        self.produktionDebugTimer = self.produktionDebugTimer + dt
    end

    self.produktionBuffer = self.produktionBuffer + amountToProduce

    local producedAmount = 0

    if self.produktionBuffer >= 1 then
        producedAmount = self:produce(self.produktionBuffer)
        self.produktionBuffer = self.produktionBuffer - producedAmount

        if self.produktionBuffer > 1000 then
            self.produktionBuffer = 1000
        end
    end

    if producedAmount > 0 then
        self:updateAnimationState(true, dt)
    else
        self:updateAnimationState(false, dt)
    end

    if self.raiseActive ~= nil then
        self:raiseActive()
    end
end


-- Produktion

function Produktion:produce(amount)
    if self.isServer == false then
        return 0
    end

    local spec = self.spec_silo

    if spec == nil or spec.storages == nil then
        if Produktion.debug then
            print(Produktion.debugPrefix .. "Kein Silo-Speicher gefunden")
        end

        return 0
    end

    local fillTypeIndex = g_fillTypeManager:getFillTypeIndexByName(self.produktionFillType)

    if fillTypeIndex == nil then
        if Produktion.debug then
            print(Produktion.debugPrefix .. "FillType nicht gefunden: " .. self.produktionFillType)
        end

        return 0
    end

    local remainingAmount = amount
    local producedAmount = 0
    local hasFreeCapacity = false

    for _, storage in ipairs(spec.storages) do
        local freeCapacity = storage:getFreeCapacity(fillTypeIndex)

        if freeCapacity > 0 then
            hasFreeCapacity = true

            local movedAmount = math.min(remainingAmount, freeCapacity)
            local oldFillLevel = storage:getFillLevel(fillTypeIndex) or 0

            storage:setFillLevel(oldFillLevel + movedAmount, fillTypeIndex)

            remainingAmount = remainingAmount - movedAmount
            producedAmount = producedAmount + movedAmount
        end

        if remainingAmount <= 0.001 then
            break
        end
    end

    if Produktion.debug then
        if producedAmount > 0 then
            self.produktionWasFull = false

            if producedAmount >= 1 then
                self.produktionDebugAmount = self.produktionDebugAmount + producedAmount

                if self.produktionDebugTimer >= Produktion.debugProductionInterval then
                    print(Produktion.debugPrefix .. "Produziert: " .. tostring(math.floor(self.produktionDebugAmount)) .. " L " .. self.produktionFillType .. " in den letzten " .. tostring(Produktion.debugProductionInterval / 1000) .. "s")
                    self.produktionDebugTimer = 0
                    self.produktionDebugAmount = 0
                end
            end
        elseif hasFreeCapacity == false and self.produktionWasFull ~= true then
            self.produktionWasFull = true
            print(Produktion.debugPrefix .. "Speicher voll, Produktion gestoppt")
        end
    end

    return producedAmount
end


-- Animation vorbereitet

function Produktion:updateAnimationState(isProducing, dt)
    if isProducing then
        self.produktionAnimationTargetSpeed = Produktion.animationSpeedMax
    else
        self.produktionAnimationTargetSpeed = 0
    end

    local step = Produktion.animationAcceleration * (dt / 1000)

    if self.produktionAnimationSpeed < self.produktionAnimationTargetSpeed then
        self.produktionAnimationSpeed = math.min(self.produktionAnimationSpeed + step, self.produktionAnimationTargetSpeed)
    elseif self.produktionAnimationSpeed > self.produktionAnimationTargetSpeed then
        self.produktionAnimationSpeed = math.max(self.produktionAnimationSpeed - step, self.produktionAnimationTargetSpeed)
    end

    -- Hier kommt später die echte Animation rein.
    -- Beispiel später:
    -- self:setAnimationTime("mineWorkAnimation", self.produktionAnimationSpeed, true)
    -- oder:
    -- setRotation(self.animationNode, 0, self.produktionAnimationSpeed, 0)
end
