require "TimedActions/ISBaseTimedAction"
require "W900_HydrantWater"
require "W900_CisternParts"

ISFillW900CisternFromHydrant = ISBaseTimedAction:derive("ISFillW900CisternFromHydrant")

local function isHydrantFillTarget(part)
	return W900CisternParts.isHydrantFillTarget(part)
end

function ISFillW900CisternFromHydrant:isValid()
	return isHydrantFillTarget(self.part)
		and self.vehicle:isInArea(self.part:getArea(), self.character)
		and self.character:getInventory():containsTypeRecurse(self.hoseType)
		and self.hydrant
		and self.hydrant:getSquare()
		and self.hydrant:getSprite()
		and self.hydrant:getSprite():getName() == self.hydrantSpriteName
		and W900HydrantWater.canUseHydrant(self.hydrant)
end

function ISFillW900CisternFromHydrant:getTransferredAmount()
	local currentAmount = self.part:getContainerContentAmount()
	return math.max(0, math.floor(currentAmount - self.tankStart))
end

function ISFillW900CisternFromHydrant:applyHydrantDrain(amount)
	if self.hydrantDrainApplied then
		return
	end
	if amount and amount > 0 then
		W900HydrantWater.consumeStoredWater(self.hydrant, amount)
	end
	self.hydrantDrainApplied = true
end

function ISFillW900CisternFromHydrant:waitToStart()
	self.character:faceThisObject(self.vehicle)
	return self.character:shouldBeTurning()
end

function ISFillW900CisternFromHydrant:update()
	if not W900HydrantWater.canUseHydrant(self.hydrant) then
		self:forceStop()
		return
	end

	local litres = self.tankStart + (self.tankTarget - self.tankStart) * self:getJobDelta()
	litres = math.floor(litres)
	if litres ~= self.amountSent then
		self.part:setContainerContentAmount(litres)
		self.vehicle:transmitPartModData(self.part)
		self.amountSent = litres
	end

	self.character:setMetabolicTarget(Metabolics.HeavyDomestic)
end

function ISFillW900CisternFromHydrant:start()
	self:setActionAnim("fill_container_tap")
	self:setOverrideHandModels(nil, nil)
	self.character:reportEvent("EventTakeWater")
	self.sound = self.character:playSound("GetWaterFromTap")
end

function ISFillW900CisternFromHydrant:stop()
	self.character:stopOrTriggerSound(self.sound)
	self:applyHydrantDrain(self:getTransferredAmount())
	ISBaseTimedAction.stop(self)
end

function ISFillW900CisternFromHydrant:serverStop()
	local litres = self.tankStart + (self.tankTarget - self.tankStart) * self.netAction:getProgress()
	local currentAmount = math.floor(litres)
	self.part:setContainerContentAmount(currentAmount)
	self.vehicle:transmitPartModData(self.part)
	self:applyHydrantDrain(currentAmount - self.tankStart)
end

function ISFillW900CisternFromHydrant:perform()
	self.character:stopOrTriggerSound(self.sound)
	ISBaseTimedAction.perform(self)
end

function ISFillW900CisternFromHydrant:complete()
	self.part:setContainerContentAmount(self.tankTarget)
	self.vehicle:transmitPartModData(self.part)
	self:applyHydrantDrain(self.transferAmount)
	return true
end

function ISFillW900CisternFromHydrant:getDuration()
	if not isHydrantFillTarget(self.part) then
		self.tankStart = 0
		self.tankTarget = 0
		self.amountSent = 0
		self.transferAmount = 0
		return 0
	end

	self.tankStart = self.part:getContainerContentAmount()
	local tankLitresFree = self.part:getContainerCapacity() - self.tankStart
	self.transferAmount = W900HydrantWater.getTransferAmount(self.hydrant, tankLitresFree)
	self.tankTarget = self.tankStart + self.transferAmount
	self.amountSent = self.tankStart
	return self.transferAmount * 50
end

function ISFillW900CisternFromHydrant:new(character, part, hydrant, hydrantSpriteName, hoseType)
	local o = ISBaseTimedAction.new(self, character)
	o.vehicle = part:getVehicle()
	o.part = part
	o.hydrant = hydrant
	o.hydrantSpriteName = hydrantSpriteName
	o.hoseType = hoseType or "RubberHose"
	o.stopOnWalk = true
	o.stopOnRun = true
	o.transferAmount = 0
	o.hydrantDrainApplied = false
	o.maxTime = o:getDuration()
	return o
end