AnimalAutoCare = {}
AnimalAutoCare.MOD_NAME = g_currentModName
AnimalAutoCare.MOD_DIR = g_currentModDirectory .. "scripts/" 

local AnimalAutoCare_mt = Class(AnimalAutoCare)

function AnimalAutoCare:new()
    local self = setmetatable({}, AnimalAutoCare_mt)
    self.isEnabled = true
    self.autoFeedEnabled = true
    self.autoWaterEnabled = true
    self.autoStrawEnabled = true
    self.dailyWorkerCost = 50
    self.workerName = "Alex"
    self.lastFeedDay = -1
    self.hasRunToday = false
    self.menuVisible = false
    self.selectedOption = 1
    self.menuOptions = 3
    self.editingCost = false
    self.editingName = false
    self.costInputBuffer = ""
    self.nameInputBuffer = ""
    self.savedPlayerPosition = nil
    self.lastClickTime = 0
    self.lastClickOption = 0
    self.doubleClickThreshold = 0.3
    return self
end

function AnimalAutoCare:loadMap(name)
    self.isClient = g_client ~= nil
    self.isServer = g_server ~= nil
    if g_currentMission and g_currentMission.environment then
        self.lastFeedDay = g_currentMission.environment.currentDay or 0
    end
    self:loadSettings()
end

function AnimalAutoCare:deleteMap()
    self:saveSettings()
end

function AnimalAutoCare:getSavegameDirectory()
    if g_currentMission and g_currentMission.missionInfo and g_currentMission.missionInfo.savegameDirectory then
        return g_currentMission.missionInfo.savegameDirectory
    end
    return nil
end

function AnimalAutoCare:saveSettings()
    local savegameDir = self:getSavegameDirectory()
    if not savegameDir then return end
    
    local filePath = savegameDir .. "/animalAutoCare.xml"
    local xmlFile = createXMLFile("animalAutoCareXML", filePath, "animalAutoCare")
    
    if xmlFile and xmlFile ~= 0 then
        setXMLBool(xmlFile, "animalAutoCare.isEnabled", self.isEnabled)
        setXMLBool(xmlFile, "animalAutoCare.autoFeedEnabled", self.autoFeedEnabled)
        setXMLBool(xmlFile, "animalAutoCare.autoWaterEnabled", self.autoWaterEnabled)
        setXMLBool(xmlFile, "animalAutoCare.autoStrawEnabled", self.autoStrawEnabled)
        setXMLInt(xmlFile, "animalAutoCare.dailyWorkerCost", self.dailyWorkerCost)
        setXMLString(xmlFile, "animalAutoCare.workerName", self.workerName)
        setXMLInt(xmlFile, "animalAutoCare.lastFeedDay", self.lastFeedDay)
        
        saveXMLFile(xmlFile)
        delete(xmlFile)
    end
end

function AnimalAutoCare:loadSettings()
    local savegameDir = self:getSavegameDirectory()
    if not savegameDir then return end
    
    local filePath = savegameDir .. "/animalAutoCare.xml"
    if not fileExists(filePath) then return end
    
    local xmlFile = loadXMLFile("animalAutoCareXML", filePath)
    
    if xmlFile and xmlFile ~= 0 then
        self.isEnabled = Utils.getNoNil(getXMLBool(xmlFile, "animalAutoCare.isEnabled"), true)
        self.autoFeedEnabled = Utils.getNoNil(getXMLBool(xmlFile, "animalAutoCare.autoFeedEnabled"), true)
        self.autoWaterEnabled = Utils.getNoNil(getXMLBool(xmlFile, "animalAutoCare.autoWaterEnabled"), true)
        self.autoStrawEnabled = Utils.getNoNil(getXMLBool(xmlFile, "animalAutoCare.autoStrawEnabled"), true)
        self.dailyWorkerCost = Utils.getNoNil(getXMLInt(xmlFile, "animalAutoCare.dailyWorkerCost"), 50)
        self.workerName = Utils.getNoNil(getXMLString(xmlFile, "animalAutoCare.workerName"), "Alex")
        self.lastFeedDay = Utils.getNoNil(getXMLInt(xmlFile, "animalAutoCare.lastFeedDay"), -1)
        
        delete(xmlFile)
    end
end

function AnimalAutoCare:closeMenu()
    self.menuVisible = false
    self.savedPlayerPosition = nil
    g_inputBinding:setShowMouseCursor(false)
end

function AnimalAutoCare:onOpenMenu()
    if self.menuVisible then
        self:closeMenu()
    else
        self.menuVisible = true
        g_inputBinding:setShowMouseCursor(true)
        self.selectedOption = 1
        
        -- Save player position when menu opens
        if g_currentMission.player and g_currentMission.player.rootNode then
            self.savedPlayerPosition = {getWorldTranslation(g_currentMission.player.rootNode)}
        end
    end
end

function AnimalAutoCare:onToggleAutoCare()
    self.isEnabled = not self.isEnabled
    self:saveSettings()
    g_currentMission:addExtraPrintText(self.isEnabled and "Animal Auto Care ENABLED" or "Animal Auto Care DISABLED")
end

function AnimalAutoCare:keyEvent(unicode, sym, modifier, isDown)
    if not self.menuVisible then return false end
    if not isDown then return true end
    
    if self.editingCost then
        if sym == Input.KEY_escape then
            self.editingCost = false
            self.costInputBuffer = ""
            return true
        elseif sym == Input.KEY_return or sym == Input.KEY_KP_enter then
            local value = tonumber(self.costInputBuffer)
            if value and value >= 0 then
                self.dailyWorkerCost = value
                self:saveSettings()
                g_currentMission:addExtraPrintText(string.format("Hired Worker Cost updated to $%d", value))
            end
            self.editingCost = false
            self.costInputBuffer = ""
            return true
        elseif sym == Input.KEY_backspace then
            if #self.costInputBuffer > 0 then
                self.costInputBuffer = string.sub(self.costInputBuffer, 1, -2)
            end
            return true
        elseif unicode and unicode >= 48 and unicode <= 57 then
            if #self.costInputBuffer < 6 then
                self.costInputBuffer = self.costInputBuffer .. string.char(unicode)
            end
            return true
        end
        return true
    end
    
    if self.editingName then
        if sym == Input.KEY_escape then
            self.editingName = false
            self.nameInputBuffer = ""
            return true
        elseif sym == Input.KEY_return or sym == Input.KEY_KP_enter then
            if #self.nameInputBuffer > 0 then
                self.workerName = self.nameInputBuffer
                self:saveSettings()
                g_currentMission:addExtraPrintText(string.format("Hired Worker Name updated to %s", self.nameInputBuffer))
            end
            self.editingName = false
            self.nameInputBuffer = ""
            return true
        elseif sym == Input.KEY_backspace then
            if #self.nameInputBuffer > 0 then
                self.nameInputBuffer = string.sub(self.nameInputBuffer, 1, -2)
            end
            return true
        elseif unicode and ((unicode >= 65 and unicode <= 90) or (unicode >= 97 and unicode <= 122) or unicode == 32) then
            if #self.nameInputBuffer < 20 then
                self.nameInputBuffer = self.nameInputBuffer .. string.char(unicode)
            end
            return true
        end
        return true
    end
    
    if sym == Input.KEY_a and modifier == Input.MOD_LCTRL then
        self:closeMenu()
        return true
    end
    
    if sym == Input.KEY_return or sym == Input.KEY_KP_enter then
        self:activateSelectedOption()
        return true
    end
    
    if sym == Input.KEY_1 then
        self.selectedOption = 1
        self:activateSelectedOption()
        return true
    end
    
    if sym == Input.KEY_2 then
        self.selectedOption = 2
        self:activateSelectedOption()
        return true
    end
    
    if sym == Input.KEY_3 then
        self.selectedOption = 3
        self:activateSelectedOption()
        return true
    end
    
    if sym == Input.KEY_up then
        self.selectedOption = self.selectedOption - 1
        if self.selectedOption < 1 then
            self.selectedOption = self.menuOptions
        end
        return true
    end
    
    if sym == Input.KEY_down then
        self.selectedOption = self.selectedOption + 1
        if self.selectedOption > self.menuOptions then
            self.selectedOption = 1
        end
        return true
    end
    
    return true
end

function AnimalAutoCare:activateSelectedOption()
    if self.selectedOption == 1 then
        self.editingCost = true
        self.costInputBuffer = tostring(self.dailyWorkerCost)
        g_currentMission:addExtraPrintText("Enter Hired Worker Cost (ENTER to confirm, ESC to cancel)")
    elseif self.selectedOption == 2 then
        self.editingName = true
        self.nameInputBuffer = self.workerName
        g_currentMission:addExtraPrintText("Enter Hired Worker Name (ENTER to confirm, ESC to cancel)")
    elseif self.selectedOption == 3 then
        -- Status toggle - handled by double-click in mouseEvent
    end
end

function AnimalAutoCare:mouseEvent(posX, posY, isDown, isUp, button)
    if not self.menuVisible then return false end
    if self.editingCost or self.editingName then return true end
    if not (isDown and button == Input.MOUSE_BUTTON_LEFT) then return true end
    
    local bgX = 0.35
    local bgY = 0.3
    local bgWidth = 0.3
    local bgHeight = 0.40
    local startY = bgY + bgHeight - 0.165
    local lineHeight = 0.03
    
    -- Option 1 - Worker Cost
    local option1Y = startY
    if posX >= bgX + 0.01 and posX <= bgX + bgWidth - 0.01 and posY >= option1Y - 0.005 and posY <= option1Y + 0.04 then
        self.selectedOption = 1
        self:activateSelectedOption()
        return true
    end
    
    -- Option 2 - Worker Name
    local option2Y = startY - lineHeight
    if posX >= bgX + 0.01 and posX <= bgX + bgWidth - 0.01 and posY >= option2Y - 0.005 and posY <= option2Y + 0.04 then
        self.selectedOption = 2
        self:activateSelectedOption()
        return true
    end
    
    -- Option 3 - Status (double-click to toggle)
    local option3Y = startY - lineHeight * 2
    if posX >= bgX + 0.01 and posX <= bgX + bgWidth - 0.01 and posY >= option3Y - 0.005 and posY <= option3Y + 0.04 then
        local currentTime = getTimeSec()
        if self.lastClickOption == 3 and (currentTime - self.lastClickTime) < self.doubleClickThreshold then
            -- Double-click detected, toggle enabled state
            self.isEnabled = not self.isEnabled
            self:saveSettings()
            g_currentMission:addExtraPrintText(self.isEnabled and "Animal Auto Care ENABLED" or "Animal Auto Care DISABLED")
            self.lastClickTime = 0
            self.lastClickOption = 0
        else
            -- First click
            self.selectedOption = 3
            self.lastClickTime = currentTime
            self.lastClickOption = 3
        end
        return true
    end
    
    -- Click outside to close
    if posX < bgX or posX > bgX + bgWidth or posY < bgY or posY > bgY + bgHeight then
        self:closeMenu()
        return true
    end
    
    return true
end

function AnimalAutoCare:draw()
    if not self.menuVisible then return end
    
    local bgX = 0.35
    local bgY = 0.3
    local bgWidth = 0.3
    local bgHeight = 0.40
    
    setTextAlignment(RenderText.ALIGN_LEFT)
    setTextVerticalAlignment(RenderText.VERTICAL_ALIGN_TOP)
    
    -- Background
    drawFilledRect(bgX, bgY, bgWidth, bgHeight, 0.0091, 0.0091, 0.0091, 0.95)
    drawFilledRect(bgX, bgY + bgHeight - 0.002, bgWidth, 0.002, 0.9906, 0.4405, 0.0028, 1)
    drawFilledRect(bgX, bgY, bgWidth, 0.002, 0.9906, 0.4405, 0.0028, 1)
    drawFilledRect(bgX, bgY, 0.002, bgHeight, 0.9906, 0.4405, 0.0028, 1)
    drawFilledRect(bgX + bgWidth - 0.002, bgY, 0.002, bgHeight, 0.9906, 0.4405, 0.0028, 1)
    
    -- Title
    setTextBold(true)
    setTextColor(0.9906, 0.4405, 0.0028, 1)
    renderText(bgX + 0.015, bgY + bgHeight - 0.035, 0.022, "ANIMAL AUTO CARE")
    setTextBold(false)
    
    -- Info
    setTextColor(0.9, 0.9, 0.9, 1)
    renderText(bgX + 0.015, bgY + bgHeight - 0.065, 0.015, "Worker: " .. self.workerName)
    renderText(bgX + 0.015, bgY + bgHeight - 0.085, 0.015, string.format("Daily Cost: $%d per pen", self.dailyWorkerCost))
    
    -- Separator
    drawFilledRect(bgX + 0.01, bgY + bgHeight - 0.11, bgWidth - 0.02, 0.001, 0.9906, 0.4405, 0.0028, 0.3)
    
    local startY = bgY + bgHeight - 0.145
    local lineHeight = 0.03
    
    -- Option 1 - Worker Cost
    local option1Y = startY
    if self.editingCost then
        setTextColor(0.9906, 0.4405, 0.0028, 1)
        renderText(bgX + 0.015, option1Y + 0.008, 0.016, "1) Hired Worker Cost: $" .. self.costInputBuffer .. "_")
    else
        local color1 = (self.selectedOption == 1) and {0.9906, 0.4405, 0.0028, 1} or {0.9, 0.9, 0.9, 1}
        setTextColor(color1[1], color1[2], color1[3], color1[4])
        renderText(bgX + 0.015, option1Y + 0.008, 0.016, "1) Hired Worker Cost: $" .. self.dailyWorkerCost)
    end
    
    -- Option 2 - Worker Name
    local option2Y = startY - lineHeight
    if self.editingName then
        setTextColor(0.9906, 0.4405, 0.0028, 1)
        renderText(bgX + 0.015, option2Y + 0.008, 0.016, "2) Hired Worker Name: " .. self.nameInputBuffer .. "_")
    else
        local color2 = (self.selectedOption == 2) and {0.9906, 0.4405, 0.0028, 1} or {0.9, 0.9, 0.9, 1}
        setTextColor(color2[1], color2[2], color2[3], color2[4])
        renderText(bgX + 0.015, option2Y + 0.008, 0.016, "2) Hired Worker Name: " .. self.workerName)
    end
    
    -- Option 3 - Status (double-click to toggle)
    local option3Y = startY - lineHeight * 2
    local color3 = (self.selectedOption == 3) and {0.9906, 0.4405, 0.0028, 1} or {0.9, 0.9, 0.9, 1}
    setTextColor(color3[1], color3[2], color3[3], color3[4])
    local statusText = self.isEnabled and "ENABLED" or "DISABLED"
    local statusColor = self.isEnabled and " (Green)" or " (Red)"
    renderText(bgX + 0.015, option3Y + 0.008, 0.016, "3) Status: " .. statusText)
    
    setTextColor(0.5, 0.5, 0.5, 1)
    renderText(bgX + 0.015, option3Y - 0.008, 0.012, "   (Double-click to toggle)")
    
    -- Instructions
    setTextColor(0.5, 0.5, 0.5, 1)
    if self.editingCost then
        renderText(bgX + 0.015, bgY + 0.015, 0.013, "Type amount, ENTER to save, ESC to cancel")
    elseif self.editingName then
        renderText(bgX + 0.015, bgY + 0.015, 0.013, "Type name, ENTER to save, ESC to cancel")
    else
        renderText(bgX + 0.015, bgY + 0.015, 0.013, "Click or press number + ENTER | CTRL+A to close | Click outside HUD")
    end
end

function AnimalAutoCare:update(dt)
    -- Handle menu position locking (client-side only)
    if self.isClient then
        if self.menuVisible then
            if g_currentMission.player and g_currentMission.player.rootNode then
                if not self.savedPlayerPosition then
                    self.savedPlayerPosition = {getWorldTranslation(g_currentMission.player.rootNode)}
                end
                g_currentMission.player:setWorldPosition(unpack(self.savedPlayerPosition))
            end
        else
            self.savedPlayerPosition = nil
        end
    end
    
    -- Handle daily care logic (server-side only)
    if self.isServer then
        self:performServerUpdate(dt)
    end
end

function AnimalAutoCare:performServerUpdate(dt)
    if g_currentMission and g_currentMission.environment then
        local currentDay = g_currentMission.environment.currentDay or 0
        local currentHour = g_currentMission.environment.currentHour or 0
        
        if currentDay ~= self.lastFeedDay then
            self.hasRunToday = false
            self.lastFeedDay = currentDay
            self:saveSettings()
        end
        
        if currentHour >= 9 and not self.hasRunToday then
            self:performDailyCare()
            self.hasRunToday = true
        end
    end
end

function AnimalAutoCare:getHusbandries()
    local husbandries = {}
    local myFarmId = g_currentMission:getFarmId()
    
    if g_currentMission and g_currentMission.placeableSystem then
        local placeables = g_currentMission.placeableSystem.placeables
        if placeables then
            for _, placeable in pairs(placeables) do
                if placeable and placeable.spec_husbandry and placeable:getOwnerFarmId() == myFarmId then
                    table.insert(husbandries, placeable)
                end
            end
        end
    end
    
    return husbandries
end

function AnimalAutoCare:performDailyCare()
    if not self.isEnabled then return end
    
    local husbandries = self:getHusbandries()
    if #husbandries == 0 then return end
    
    local totalCost = 0
    local pensServiced = 0
    local farmId = g_currentMission:getFarmId()
    
    for _, husbandry in ipairs(husbandries) do
        local servicedThisPen = false
        
        if self.autoFeedEnabled and self:feedHusbandry(husbandry) then
            servicedThisPen = true
        end
        
        if self.autoWaterEnabled and self:waterHusbandry(husbandry) then
            servicedThisPen = true
        end
        
        if self.autoStrawEnabled and self:addStrawToHusbandry(husbandry) then
            servicedThisPen = true
        end
        
        if servicedThisPen then
            pensServiced = pensServiced + 1
            totalCost = totalCost + self.dailyWorkerCost
        end
    end
    
    if pensServiced > 0 then
        if totalCost > 0 then
            g_currentMission:addMoney(-totalCost, farmId, MoneyType.ANIMAL_UPKEEP, true)
        end
        
        g_currentMission:addGameNotification(self.workerName .. " (Hired Worker)", 
            string.format("Cared for all animals in %d pen(s) - Cost: $%d", pensServiced, totalCost), "", nil, 5000)
    end
end

function AnimalAutoCare:feedHusbandry(husbandry)
    if not husbandry.spec_husbandryFood then return false end
    
    local foodSpec = husbandry.spec_husbandryFood
    if not foodSpec.fillLevels or not foodSpec.capacity or foodSpec.capacity <= 0 then return false end
    
    local totalBefore = 0
    for _, amount in pairs(foodSpec.fillLevels) do
        totalBefore = totalBefore + amount
    end
    
    local numFoodTypes = 0
    for _ in pairs(foodSpec.fillLevels) do
        numFoodTypes = numFoodTypes + 1
    end
    
    if numFoodTypes > 0 then
        local amountPerType = foodSpec.capacity / numFoodTypes
        for fillTypeIndex, _ in pairs(foodSpec.fillLevels) do
            foodSpec.fillLevels[fillTypeIndex] = amountPerType
        end
        return true
    end
    
    return false
end

function AnimalAutoCare:waterHusbandry(husbandry)
    local spec = husbandry.spec_husbandry
    if not spec or not spec.storage then return false end
    
    local waterLevel = spec.storage.fillLevels[FillType.WATER] or 0
    local waterCapacity = spec.storage.capacities[FillType.WATER] or 0
    
    if waterCapacity > 0 and waterLevel < waterCapacity then
        spec.storage.fillLevels[FillType.WATER] = waterCapacity
        if spec.dirtyFlag then
            husbandry:raiseDirtyFlags(spec.dirtyFlag)
        end
        return true
    end
    
    return false
end

function AnimalAutoCare:addStrawToHusbandry(husbandry)
    local spec = husbandry.spec_husbandry
    if not spec or not spec.storage then return false end
    
    local strawLevel = spec.storage.fillLevels[FillType.STRAW] or 0
    local strawCapacity = spec.storage.capacities[FillType.STRAW] or 0
    
    if strawCapacity > 0 and strawLevel < strawCapacity then
        spec.storage.fillLevels[FillType.STRAW] = strawCapacity
        if spec.dirtyFlag then
            husbandry:raiseDirtyFlags(spec.dirtyFlag)
        end
        return true
    end
    
    return false
end

g_animalAutoCare = AnimalAutoCare:new()

PlayerInputComponent.registerGlobalPlayerActionEvents = Utils.appendedFunction(
    PlayerInputComponent.registerGlobalPlayerActionEvents, 
    function()
        g_inputBinding:registerActionEvent("ANIMAL_AUTOCARE_MENU", g_animalAutoCare, AnimalAutoCare.onOpenMenu, 
            false, true, false, true, Input.KEY_a, Input.KEY_lcontrol)
        g_inputBinding:registerActionEvent("ANIMAL_AUTOCARE_TOGGLE", g_animalAutoCare, AnimalAutoCare.onToggleAutoCare, 
            false, true, false, true)
    end
)

addModEventListener(g_animalAutoCare)