--
-- AIExtension
--
-- @author Stefan Maurus
-- @date 13/08/2020
--
-- Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved.


AIExtension = {}

AIExtension.MOD_NAME = g_currentModName

local AIExtension_mt = Class(AIExtension)

function AIExtension.new(customMt)
    local self = setmetatable({}, customMt or AIExtension_mt)

    self.rtkStations = {}
    self.preciseModeActive = false

    return self
end

function AIExtension:loadFromXML(xmlFile, key, baseDirectory, configFileName, mapFilename)
    return true
end

function AIExtension:delete()
    self:setPreciseModeActive(false)
end


function AIExtension:overwriteGameFunctions(pfModule)
    --
    --  Force the AI vehicle to drive not in a straight line
    --  'randomly' add offset to the drive target point
    --  max. 15cm, so in worst case we leave a 4cm gab, but with the 25cm resolution we dont have blank spaces
    --
    pfModule:overwriteGameFunction(AIDriveStrategyStraight, "getDriveStraightData", function(superFunc, self, dt, vX, vY, vZ, distanceToTurn, distanceToEndOfField)
        local tX, tZ, allowedToDrive, maxSpeed, distanceToTurn = superFunc(self, dt, vX, vY, vZ, distanceToTurn, distanceToEndOfField)

        if not pfModule.aiExtension.preciseModeActive then
            self.randomLineOffset = self.randomLineOffset or 0
            if self.randomLineOffset ~= nil then
                self.randomLineOffset = self.randomLineOffset + dt

                local t = self.randomLineOffset / 2500
                local offsetPct = math.sin(t) * math.sin((t+2) * 0.3) * 0.8 + math.cos(t*5) * 0.2
                local offsetDistance = offsetPct * 0.15

                local dirX, dirZ = self.vehicle.aiDriveDirection[1], self.vehicle.aiDriveDirection[2]
                local sideDirX, sideDirY = -dirZ, dirX
                tX, tZ = tX + sideDirX * offsetDistance, tZ + sideDirY * offsetDistance
            end
        end

        return tX, tZ, allowedToDrive, maxSpeed, distanceToTurn
    end)

    --
    --  Force the ai to ignore the current spray level on the field
    --  Just use the visual ground type as reference
    --
    pfModule:overwriteGameFunction(Sprayer, "setSprayerAITerrainDetailProhibitedRange", function(superFunc, vehicle, fillType)
        if vehicle:getUseSprayerAIRequirements() then
            if vehicle.addAITerrainDetailProhibitedRange ~= nil then
                vehicle:clearAITerrainDetailProhibitedRange()
                vehicle:clearAIFruitRequirements()
                vehicle:clearAIFruitProhibitions()

                local sprayTypeDesc = g_sprayTypeManager:getSprayTypeByFillTypeIndex(fillType)
                if sprayTypeDesc ~= nil then
                    if sprayTypeDesc.isHerbicide then
                        local fruitType = g_fruitTypeManager:getFruitTypeByName("weed")
                        if fruitType ~= nil then
                            vehicle:setAIFruitRequirements(fruitType.index, 1, 2)
                        end
                    else
                        vehicle:addAITerrainDetailProhibitedRange(sprayTypeDesc.groundType, sprayTypeDesc.groundType, g_currentMission.sprayFirstChannel, g_currentMission.sprayNumChannels)
                    end

                    -- block ai from working on fully growth fields
                    if sprayTypeDesc.isHerbicide or sprayTypeDesc.isFertilizer then
                        for index, entry in pairs(g_currentMission.fruits) do
                            local fruitType = g_fruitTypeManager:getFruitTypeByIndex(index)
                            if fruitType.name:lower() ~= "grass" then
                                if fruitType.minHarvestingGrowthState ~= nil and fruitType.maxHarvestingGrowthState ~= nil and fruitType.weed == nil then
                                    vehicle:addAIFruitProhibitions(fruitType.index, fruitType.minHarvestingGrowthState, fruitType.maxHarvestingGrowthState)
                                end
                            end
                        end
                    end
                end
            end
        end
    end)

end

function AIExtension:setPreciseModeActive(state)
    self.preciseModeActive = state
    if state then
        AIVehicleUtil.AREA_OVERLAP = -0.175
    else
        AIVehicleUtil.AREA_OVERLAP = 0.26
    end
end

function AIExtension:registerRTKStation(station)
    self.rtkStations[station] = station
    self:setPreciseModeActive(true)
end

function AIExtension:unregisterRTKStation(station)
    self.rtkStations[station] = nil
    self:setPreciseModeActive(next(self.rtkStations) ~= nil)
end
