--[[
Interface: 1.5.1.0 b6732

Copyright (C) GtX (Andy), 2019

Author: GtX | Andy
Date: 24.03.2019
Version: 1.0.0.0

Contact:
https://forum.giants-software.com
https://github.com/GtX-Andy

History:
V 1.0.0.0 @ 24.03.2019 - Release Version

Notes:
Based on original idea by GIANTS Software GmbH.
Fixes error when bales are in the trigger and adds support for log weights.
Adds support for placeable 'WeighStation' and multiple displays.
Adds support for 'Imperial' displays.

Important:
No changes are to be made to this script without permission from GtX | Andy
An diesem Skript dürfen ohne Genehmigung von GtX | Andy keine Änderungen vorgenommen werden
]]


EnhancedWeighStation = {}
local EnhancedWeighStation_mt = Class(EnhancedWeighStation)

function EnhancedWeighStation.init(modDirectory, modName)
    local placeablePath = modDirectory .. "scripts/WeighStationPlaceable.lua"
    if fileExists(placeablePath) then
        local name = modName .. ".weighStationPlaceable"
        if g_placeableTypeManager.placeableTypes[name] == nil then
            g_placeableTypeManager:addPlaceableType("weighStationPlaceable", "WeighStationPlaceable", placeablePath)
        end
    end

    if g_modManager:isModMap(modName) then
        print("  Register modOnCreate: EnhancedWeighStation")
        g_onCreateUtil.addOnCreateFunction("EnhancedWeighStation", EnhancedWeighStation.onCreate)
    end
end

function EnhancedWeighStation.onCreate(id)
    g_currentMission:addNonUpdateable(EnhancedWeighStation:new(id))
end

function EnhancedWeighStation:new(triggerId)
    local instance = {}
    setmetatable(instance, EnhancedWeighStation_mt)

    if triggerId ~= nil then
        instance:load(triggerId, false)
    end

    return instance
end

function EnhancedWeighStation:load(triggerId, isPlaceable, displays, lights)
    self.isEnabled = true
    self.isPlaceable = isPlaceable

    self.numTriggerItems = 0
    self.triggerItems = {}

    self.triggerId = triggerId

    if self.isPlaceable then
        self.displays = displays
        self.lights = lights
    else
        addTrigger(triggerId, "triggerCallback", self)

        self.displays = {}

        local weightDisplays = getUserAttribute(triggerId, "weightDisplays")
        if weightDisplays ~= nil then
            local numDisplays = getNumOfChildren(weightDisplays)
            if numDisplays > 0 then
                for id = 0, numDisplays - 1 do
                    local node = getChildAt(weightDisplays, id)
                    local useImperial = Utils.getNoNil(getUserAttribute(node, "useImperial"), false)
                    local showZero = Utils.getNoNil(getUserAttribute(triggerId, "showZero"), true)

                    table.insert(self.displays, {node = node, useImperial = useImperial, showZero = showZero})
                end
            end
        end

        local weightLights = getUserAttribute(triggerId, "weightLights")
        if weightLights ~= nil then
            local numLights = getNumOfChildren(weightLights)
            if numLights > 0 then
                self.lights = {}

                for id = 0, numLights - 1 do
                    local node = getChildAt(weightDisplays, id)
                    local isStopLight = Utils.getNoNil(getUserAttribute(node, "isStopLight"), true)

                    local intensity = getUserAttribute(node, "intensity")
                    if intensity ~= nil and getHasShaderParameter(node, "lightControl") then
                        local _, y, z, w = getShaderParameter(node, "lightControl")

                        if isStopLight then
                            setShaderParameter(node, "lightControl", 0, y, z, w, false)
                        else
                            setShaderParameter(node, "lightControl", intensity, y, z, w, false)
                        end
                    else
                        setVisibility(node, not isStopLight)
                    end

                    table.insert(self.lights, {node = node, isStopLight = isStopLight, intensity = intensity})
                end
            end
        end
    end

    if #self.displays > 0 then
        self:updateDisplayNumbers(0)
    end

    return true
end

function EnhancedWeighStation:delete()
    if self.triggerId ~= nil then
        removeTrigger(self.triggerId)
        self.triggerId = nil
    end
end

function EnhancedWeighStation:updateDisplayNumbers(totalWeight)
    for i = 1, #self.displays do
        local display = self.displays[i]

        if totalWeight > 0.0 and display.useImperial then
            I3DUtil.setNumberShaderByValue(display.node, totalWeight * 2.205, 0, display.showZero)
        else
            I3DUtil.setNumberShaderByValue(display.node, totalWeight, 0, display.showZero)
        end
    end
end

function EnhancedWeighStation:updateLights()
    if self.lights ~= nil then
        for i = 1, #self.lights do
            local light = self.lights[i]

            if self.numTriggerItems > 0 then
                if light.intensity == nil then
                    setVisibility(light.node, light.isStopLight)
                else
                    local _, y, z, w = getShaderParameter(light.node, "lightControl")
                    if light.isStopLight then
                        setShaderParameter(light.node, "lightControl", light.intensity, y, z, w, false)
                    else
                        setShaderParameter(light.node, "lightControl", 0, y, z, w, false)
                    end
                end
            else
                if light.intensity == nil then
                    setVisibility(light.node, not light.isStopLight)
                else
                    local _, y, z, w = getShaderParameter(light.node, "lightControl")
                    if light.isStopLight then
                        setShaderParameter(light.node, "lightControl", 0, y, z, w, false)
                    else
                        setShaderParameter(light.node, "lightControl", light.intensity, y, z, w, false)
                    end
                end
            end
        end
    end
end

function EnhancedWeighStation:updateWeight()
    local mass = 0

    for item, data in pairs (self.triggerItems) do
        if data.isVehicle and item.components ~= nil then
            for _, component in pairs(item.components) do
                mass = mass + component.mass
            end

            if item.spec_wheels ~= nil then
                for _, wheel in pairs(item.spec_wheels.wheels) do
                    mass = mass + wheel.mass
                end
            end
        else
            mass = mass + getMass(item)
        end
    end

    self:updateDisplayNumbers(tonumber(string.format("%.0f", mass * 1000)))
end

function EnhancedWeighStation:triggerCallback(triggerId, otherId, onEnter, onLeave, onStay)
    if self.isEnabled and (onEnter or onLeave) then

        if self.numTriggerItems > 0 then
            for item, data in pairs (self.triggerItems) do
                if not entityExists(data.otherId) then
                    self.triggerItems[item] = nil
                    self.numTriggerItems = math.max(self.numTriggerItems - 1, 0)
                end
            end
        end

        local item, isVehicle = nil, false
        local nodeToObject = g_currentMission.nodeToObject[otherId]

        if nodeToObject ~= nil then
            if nodeToObject.components ~= nil then
                isVehicle = true
                item = nodeToObject
            else
                if nodeToObject.isa ~= nil and nodeToObject:isa(Bale) then
                    item = otherId
                end
            end
        else
            if getHasClassId(otherId, ClassIds.MESH_SPLIT_SHAPE) then
                item = otherId
            end
        end

        if item ~= nil then
            if onEnter then
                if self.triggerItems[item] == nil then
                    self.triggerItems[item] = {otherId = otherId, isVehicle = isVehicle}
                    self.numTriggerItems = self.numTriggerItems + 1
                end
            else
                self.triggerItems[item] = nil
                self.numTriggerItems = math.max(self.numTriggerItems - 1, 0)
            end
        end

        self:updateWeight()
        self:updateLights()
    end
end

EnhancedWeighStation.init(g_currentModDirectory, g_currentModName)
