--author: igor29381
--v6.0
--date: 08.06.20

ShowCargoUnits = {};

function ShowCargoUnits.prerequisitesPresent(specializations)
    return true;
end;

function ShowCargoUnits.registerFunctions(vehicleType)
    SpecializationUtil.registerFunction(vehicleType, "getHasMeasurement", ShowCargoUnits.getHasMeasurement);
    SpecializationUtil.registerFunction(vehicleType, "getTipOnPalletIsPossible", ShowCargoUnits.getTipOnPalletIsPossible);
    SpecializationUtil.registerFunction(vehicleType, "tipOnPallet", ShowCargoUnits.tipOnPallet);
	SpecializationUtil.registerFunction(vehicleType, "updateCargoUnits", ShowCargoUnits.updateCargoUnits);
end;

function ShowCargoUnits.registerEventListeners(vehicleType)
	SpecializationUtil.registerEventListener(vehicleType, "onLoad", ShowCargoUnits);
	SpecializationUtil.registerEventListener(vehicleType, "onPostLoad", ShowCargoUnits);
	SpecializationUtil.registerEventListener(vehicleType, "onUpdate", ShowCargoUnits);
	SpecializationUtil.registerEventListener(vehicleType, "onRegisterActionEvents", ShowCargoUnits);
end;

function ShowCargoUnits.registerOverwrittenFunctions(vehicleType)
	SpecializationUtil.registerOverwrittenFunction(vehicleType, "addFillUnitFillLevel", ShowCargoUnits.addFillUnitFillLevel);
	SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanDischargeToGround", ShowCargoUnits.getCanDischargeToGround);
end;

function ShowCargoUnits:onLoad(savegame)
    if hasXMLProperty(self.xmlFile, "vehicle.cargoUnits") then
        self.cargoUnits = {spec=self[string.format("spec_%s.ShowCargoUnits", self.customEnvironment)], units={}};
		self.cargoUnits.fillUnitIndex = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.cargoUnits#fillUnitIndex"), 1);
		self.cargoUnits.fillUnit = self.spec_fillUnit.fillUnits[self.cargoUnits.fillUnitIndex];
        local i = 0;
        while true do
            local key = string.format("vehicle.cargoUnits.unit(%d)", i);
            local index = getXMLString(self.xmlFile, key.."#index");
            local fillTypes = getXMLString(self.xmlFile, key.."#fillTypes");
            if not index or not fillTypes then
                break;
            end;
			local node = I3DUtil.indexToObject(self.components, index);
			if node and node > 0 then
				local count = getNumOfChildren(node);
				local unit = {node=node, count=count};
				fillTypes = StringUtil.splitString(" ", fillTypes);
				for ii=1, #fillTypes do
					local fillType = g_fillTypeManager.nameToIndex[fillTypes[ii]];
					if fillType then
						self.cargoUnits.units[fillType] = unit;
					end;
				end;
				if Utils.getNoNil(getXMLBool(self.xmlFile, key.."#defaultCargoUnit"), false) then
					self.cargoUnits.defaultCargoUnit = unit;
				end;
			end;
            i = i + 1;
        end;
        if self.cargoUnits.defaultCargoUnit then
            for fillType,_ in pairs(self.cargoUnits.fillUnit.supportedFillTypes) do
                if not self.cargoUnits.units[fillType] then
                    self.cargoUnits.units[fillType] = self.cargoUnits.defaultCargoUnit;
                end;
            end;
        end;
        if self:getHasMeasurement() and hasXMLProperty(self.xmlFile, "vehicle.liquidColors") then
            i = 0;
            self.cargoUnits.liquidColors = {};
            while true do
                local key = string.format("vehicle.liquidColors.color(%d)", i);
                local rgb = getXMLString(self.xmlFile, key.."#rgb");
                local fillTypes = getXMLString(self.xmlFile, key.."#fillTypes");
                if not rgb or not fillTypes then
                    break;
                end;
                fillTypes = StringUtil.splitString(" ", fillTypes);
                for ii=1, #fillTypes do
                    local fillType = g_fillTypeManager.nameToIndex[fillTypes[ii]];
                    if fillType then
                        self.cargoUnits.liquidColors[fillType] = {StringUtil.getVectorFromString(rgb)};
                    end;
                end;
                i = i + 1;
            end;
        end;
        self.cargoUnits.loadPalletMode = false;
        local palletReferencePointIndex = getXMLString(self.xmlFile, "vehicle.cargoUnits#palletReferencePointIndex");
        if palletReferencePointIndex then
            self.cargoUnits.palletReferencePoint = I3DUtil.indexToObject(self.components, palletReferencePointIndex);
        end;
        local tipOnPalletInputString = Utils.getNoNil(getXMLString(self.xmlFile, "vehicle.cargoUnits#tipOnPalletInputAction"), "TOGGLE_TIPSTATE_GROUND");
        self.cargoUnits.tipOnPalletInputAction = InputAction[tipOnPalletInputString];
    end;
end;

function ShowCargoUnits:onPostLoad(savegame)
	self:updateCargoUnits();
end;

function ShowCargoUnits:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
	if self.cargoUnits.actionEventId then
		g_inputBinding:setActionEventActive(self.cargoUnits.actionEventId, self:getTipOnPalletIsPossible() and isActiveForInput);
	end;
end;

function ShowCargoUnits:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection)
    if self.isClient then
		self:clearActionEventsTable(self.cargoUnits.spec.actionEvents);
        if isActiveForInputIgnoreSelection then
            _, self.cargoUnits.actionEventId = self:addActionEvent(self.cargoUnits.spec.actionEvents, self.cargoUnits.tipOnPalletInputAction, self, ShowCargoUnits.tipOnPallet, false, true, false, true);
			g_inputBinding:setActionEventTextPriority(self.cargoUnits.actionEventId, GS_PRIO_NORMAL);
			g_inputBinding:setActionEventText(self.cargoUnits.actionEventId, g_i18n:getText("tipOnPallet"));
        end;
    end;
end;

function ShowCargoUnits:getHasMeasurement()
    if #self.cargoUnits.fillUnit.measurementNodes > 0 then
		return true;
    end;
    return false;
end;

function ShowCargoUnits:getTipOnPalletIsPossible()
    if not self.cargoUnits then
        return false;
    end;
    if not self.cargoUnits.palletReferencePoint then
        return false;
    end;
	local desc = g_fillTypeManager.fillTypes[self.cargoUnits.fillUnit.fillType];
    if not desc.palletFilename then
        return false;
    end;
    if self.cargoUnits.fillUnit.fillLevel <= 0 then
        return false;
    end;
	if SpecializationUtil.hasSpecialization(Dischargeable, self.specializations) then
		if self:getCanDischargeToObject(self.spec_dischargeable.currentDischargeNode) then
			return false;
		end;
	end;
    return true;
end;

function ShowCargoUnits:tipOnPallet()
	if g_server then
		local x,y,z = getWorldTranslation(self.cargoUnits.palletReferencePoint);
		local rx,ry,rz = getWorldRotation(self.cargoUnits.palletReferencePoint);
		PlacementUtil.tempHasCollision = false;
		overlapBox(x,y,z, rx,ry,rz, 0.3, 0.3, 0.3, "PlacementUtil.collisionTestCallback", nil, 25178120);
		if PlacementUtil.tempHasCollision then
			g_currentMission:showBlinkingWarning(g_i18n:getText("otherPallet"));
			return;
		end;
		local fillUnit = self.cargoUnits.fillUnit;
		local palletFilename = g_fillTypeManager.fillTypes[fillUnit.fillType].palletFilename;
		if palletFilename then
			local farmId = self:getActiveFarm();
			local pallet = g_currentMission:loadVehicle(palletFilename, x,y+0.25,z, 0, ry, true, 0, Vehicle.PROPERTY_STATE_OWNED, farmId, nil, nil);
			if pallet then
				local fillLevel = math.min(pallet.spec_fillUnit.fillUnits[1].capacity, fillUnit.fillLevel);
				pallet:addFillUnitFillLevel(farmId, 1, fillLevel, fillUnit.fillType, ToolType.UNDEFINED);
				self:addFillUnitFillLevel(farmId, self.cargoUnits.fillUnitIndex, -fillLevel, fillUnit.fillType, ToolType.UNDEFINED);
				if fillUnit.fillType == FillType.SEEDS then
					if self.seedsExtension and pallet.seedsExtension then
						pallet.seedsExtension.fruitType = self.seedsExtension.fruitType;
						pallet.seedsExtension.seedClass = self.seedsExtension.seedClass;
						--setFruitPicture(pallet);
					end;
				end;
				g_currentMission:addMoney(-50, farmId, MoneyType.AI, true);
				g_currentMission:showMoneyChange(MoneyType.AI);
			end;
		end;
	else
		g_client:getServerConnection():sendEvent(TipOnPalletEvent:new(self));
	end;
end;

function ShowCargoUnits:updateCargoUnits()
	local fillUnit = self.cargoUnits.fillUnit;
	if self.cargoUnits.units then
		if fillUnit.fillType ~= FillType.UNKNOWN then
			local unit = self.cargoUnits.units[fillUnit.fillType];
			if unit and fillUnit.capacity > 0 then
				local count = math.ceil(unit.count*(fillUnit.fillLevel/fillUnit.capacity));
				for i=1, unit.count do
					setVisibility(getChildAt(unit.node, i-1), i <= count);
				end;
			end;
		else
			for _,unit in pairs(self.cargoUnits.units) do
				for i=1, unit.count do
					setVisibility(getChildAt(unit.node, i-1), false);
				end;
			end;
		end;
	end;
	-- if self.liquidColors then
		-- for i=1, #self.fillUnits do
			-- local fillUnit = self.fillUnits[i];
			-- if fillUnit.measurementNodes then
				-- for ii=1, #fillUnit.measurementNodes do
					-- local rgb = self.liquidColors[fillUnit.fillType];
					-- if rgb then
						-- setShaderParameter(fillUnit.measurementNodes[ii], "liquidColor", rgb[1], rgb[2], rgb[3], 0, false);
					-- end;
				-- end;
			-- end;
		-- end;
	-- end;
end;

function ShowCargoUnits:getCanDischargeToGround()
    return false;
end;

function ShowCargoUnits:addFillUnitFillLevel(superFunc, farmId, fillUnitIndex, fillLevelDelta, fillType, toolType, fillPositionData)
	local appliedDelta = superFunc(self, farmId, fillUnitIndex, fillLevelDelta, fillType, toolType, fillPositionData);
	self:updateCargoUnits();
	return appliedDelta;
end;



TipOnPalletEvent = {};
TipOnPalletEvent_mt = Class(TipOnPalletEvent, Event);
InitEventClass(TipOnPalletEvent, "TipOnPalletEvent");

function TipOnPalletEvent:emptyNew()
    local self = Event:new(TipOnPalletEvent_mt);
    return self;
end;

function TipOnPalletEvent:new(object)
    local self = TipOnPalletEvent:emptyNew();
    self.object = object;
    return self;
end;

function TipOnPalletEvent:readStream(streamId, connection)
    local object = NetworkUtil.getObject(streamReadInt32(streamId));
    object:tipOnPallet();
end;

function TipOnPalletEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, NetworkUtil.getObjectId(self.object));
end;
