--
-- Author: E.T.A La Marchoise
-- Date: 07-10-22
-- Version: 1.0.0.0
-- Copyright (C) E.T.A La Marchoise, All Rights Reserved
-- ExtendedFruitPreparer.lua
--

ExtendedFruitPreparer = {};
ExtendedFruitPreparer.MOD_NAME = g_currentModName;


function ExtendedFruitPreparer.initSpecialization()
    local schema = Vehicle.xmlSchema;

    schema:setXMLSpecializationType("ExtendedFruitPreparer");
    schema:register(XMLValueType.STRING, "vehicle.fruitPreparer#fruitTypes", "Fruit types");
    schema:setXMLSpecializationType();
end

function ExtendedFruitPreparer.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(FruitPreparer, specializations) and SpecializationUtil.hasSpecialization(VineDetector, specializations);
end

function ExtendedFruitPreparer.registerFunctions(vehicleType)
    SpecializationUtil.registerFunction(vehicleType, "isFruitTypeIsValid", ExtendedFruitPreparer.isFruitTypeIsValid);
end

function ExtendedFruitPreparer.registerEventListeners(vehicleType)
    SpecializationUtil.registerEventListener(vehicleType, "onPreLoad", ExtendedFruitPreparer);
    SpecializationUtil.registerEventListener(vehicleType, "onLoad", ExtendedFruitPreparer);
end

function ExtendedFruitPreparer.registerOverwrittenFunctions(vehicleType)
    SpecializationUtil.registerOverwrittenFunction(vehicleType, "onTurnedOff", ExtendedFruitPreparer.onTurnedOff);
    SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanStartVineDetection", ExtendedFruitPreparer.getCanStartVineDetection);
    SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsValidVinePlaceable", ExtendedFruitPreparer.getIsValidVinePlaceable);
    SpecializationUtil.registerOverwrittenFunction(vehicleType, "handleVinePlaceable", ExtendedFruitPreparer.handleVinePlaceable);
    SpecializationUtil.registerOverwrittenFunction(vehicleType, "processFruitPreparerArea", ExtendedFruitPreparer.processFruitPreparerArea);
end

function ExtendedFruitPreparer:onPreLoad(savegame)
    self.spec_extendedFruitPreparer = self[("spec_%s.extendedFruitPreparer"):format(ExtendedFruitPreparer.MOD_NAME)];
end

function ExtendedFruitPreparer:onLoad(savegame)
    local spec = self.spec_extendedFruitPreparer;
    local fruitTypes = self.xmlFile:getString("vehicle.fruitPreparer#fruitTypes");

    spec.allowedFruitTypes = {};

    if fruitTypes == nil then
        Logging.xmlError(self.xmlFile, "Missing fruitTypes attribute for fruitPreparer");
    else
        fruitTypes = fruitTypes:split(" ");

        for i, fruitTypeName in pairs(fruitTypes) do
            local fruitType = g_fruitTypeManager:getFruitTypeByName(fruitTypeName);

            if fruitType ~= nil then
                print("Load " .. tostring(fruitTypeName) .. " => " .. tostring(fruitType.index))
                table.insert(spec.allowedFruitTypes, fruitType.index);
            end
        end
    end
end

function ExtendedFruitPreparer:onTurnedOff()
    self:cancelVineDetection();
end

function ExtendedFruitPreparer:getCanStartVineDetection(superFunc)
    if not superFunc(self) then
        return false;
    end

    return self:getIsTurnedOn() and self.movingDirection > 0;
end

function ExtendedFruitPreparer:getIsValidVinePlaceable(superFunc, placeable)
    if not superFunc(self, placeable) then
        return false;
    end

    return self:isFruitTypeIsValid(placeable:getVineFruitType());
end

function ExtendedFruitPreparer:handleVinePlaceable(superFunc, node, placeable, x, y, z, distance)
    if not superFunc(self, node, placeable, x, y, z, distance) then
        return false;
    end

    if placeable ~= nil then
        placeable:updateVineNode(node, true);

        return true;
    end

    return false;
end

function ExtendedFruitPreparer:isFruitTypeIsValid(fruitTypeToCheck)
    local spec = self.spec_extendedFruitPreparer;

    for _, fruitType in pairs(spec.allowedFruitTypes) do
        if fruitType == fruitTypeToCheck then
            return true;
        end
    end

    return false;
end

function ExtendedFruitPreparer:processFruitPreparerArea(superFunc, workArea)
    local spec = self.spec_fruitPreparer
    local workAreaSpec = self.spec_workArea
    local xs, _, zs = getWorldTranslation(workArea.start)
    local xw, _, zw = getWorldTranslation(workArea.width)
    local xh, _, zh = getWorldTranslation(workArea.height)
    local dxs = xs
    local dzs = zs
    local dxw = xw
    local dzw = zw
    local dxh = xh
    local dzh = zh

    if workArea.dropWorkAreaIndex ~= nil then
        local dropArea = workAreaSpec.workAreas[workArea.dropWorkAreaIndex]

        if dropArea ~= nil then
            dxs, _, dzs = getWorldTranslation(dropArea.start)
            dxw, _, dzw = getWorldTranslation(dropArea.width)
            dxh, _, dzh = getWorldTranslation(dropArea.height)
        end
    end

    local extendedFruitPreparerSpec = self.spec_extendedFruitPreparer;
    local area = 0;

    for iFruitType, fruitTypeId in pairs(extendedFruitPreparerSpec.allowedFruitTypes) do
        local fruitType = g_fruitTypeManager:getFruitTypeByIndex(fruitTypeId);

        if fruitType ~= nil and fruitType.terrainDataPlaneIdPreparing ~= nil then
            area = FSDensityMapUtil.updateFruitPreparerArea(fruitTypeId, xs, zs, xw, zw, xh, zh, dxs, dzs, dxw, dzw, dxh, dzh);

            if area > 0 then
                spec.lastWorkTime = g_time;
                break;
            end
        end
    end

    return 0, area;
end

function FruitPreparer:onLoad(savegame)
    local spec = self.spec_fruitPreparer

    XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.turnOnAnimation#name", "vehicle.turnOnVehicle.turnedAnimation#name")
    XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.turnOnAnimation#speed", "vehicle.turnOnVehicle.turnedAnimation#turnOnSpeedScale")
    XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.fruitPreparer#useReelStateToTurnOn")
    XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.fruitPreparer#onlyActiveWhenLowered")
    XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.vehicle.fruitPreparerSound", "vehicle.fruitPreparer.sounds.work")
    XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.turnedOnRotationNodes.turnedOnRotationNode", "vehicle.fruitPreparer.animationNodes.animationNode", "fruitPreparer")

    if self.isClient then
        spec.samples = {
            work = g_soundManager:loadSampleFromXML(self.xmlFile, "vehicle.fruitPreparer.sounds", "work", self.baseDirectory, self.components, 0, AudioGroup.VEHICLE, self.i3dMappings, self)
        }
        spec.animationNodes = g_animationManager:loadAnimations(self.xmlFile, "vehicle.fruitPreparer.animationNodes", self.components, self, self.i3dMappings)
    end

    spec.fruitType = FruitType.UNKNOWN
    local fruitType = self.xmlFile:getValue("vehicle.fruitPreparer#fruitType")

    if fruitType ~= nil then
        local desc = g_fruitTypeManager:getFruitTypeByName(fruitType)

        if desc ~= nil then
            spec.fruitType = desc.index

            if self.setAIFruitRequirements ~= nil then
                self:setAIFruitRequirements(desc.index, desc.minPreparingGrowthState, desc.maxPreparingGrowthState)

                local aiUsePreparedState = self.xmlFile:getValue("vehicle.fruitPreparer#aiUsePreparedState", self.spec_cutter ~= nil)

                if aiUsePreparedState then
                    self:addAIFruitRequirement(desc.index, desc.preparedGrowthState, desc.preparedGrowthState)
                end
            end
        else
            Logging.xmlWarning(self.xmlFile, "Unable to find fruitType '%s' in fruitPreparer", fruitType)
        end
    else
        Logging.xmlWarning(self.xmlFile, "Missing fruitType in fruitPreparer")
    end

    spec.isWorking = false
    spec.lastWorkTime = -math.huge
    spec.dirtyFlag = self:getNextDirtyFlag()
end


function FruitPreparer.onLoad(self, savegame)
    local spec = self.spec_fruitPreparer

    XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.turnOnAnimation#name", "vehicle.turnOnVehicle.turnedAnimation#name")
    XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.turnOnAnimation#speed", "vehicle.turnOnVehicle.turnedAnimation#turnOnSpeedScale")
    XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.fruitPreparer#useReelStateToTurnOn")
    XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.fruitPreparer#onlyActiveWhenLowered")
    XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.vehicle.fruitPreparerSound", "vehicle.fruitPreparer.sounds.work")
    XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.turnedOnRotationNodes.turnedOnRotationNode", "vehicle.fruitPreparer.animationNodes.animationNode", "fruitPreparer")

    if self.isClient then
        spec.samples = {
            work = g_soundManager:loadSampleFromXML(self.xmlFile, "vehicle.fruitPreparer.sounds", "work", self.baseDirectory, self.components, 0, AudioGroup.VEHICLE, self.i3dMappings, self)
        }
        spec.animationNodes = g_animationManager:loadAnimations(self.xmlFile, "vehicle.fruitPreparer.animationNodes", self.components, self, self.i3dMappings)
    end

    spec.isWorking = false
    spec.lastWorkTime = -math.huge
    spec.dirtyFlag = self:getNextDirtyFlag()
end