local M = {}

local function readPropertyContainer(props, key)
    if not props or not key then return nil end

    if type(props) == "table" then
        return props[key]
    end

    if props.get then
        local ok, value = pcall(function() return props:get(key) end)
        if ok and value ~= nil then return value end
    end

    if props.size and props.get then
        local okSize, size = pcall(function() return props:size() end)
        if okSize and size and size > 0 then
            for i = 0, size - 1 do
                local okEntry, entry = pcall(function() return props:get(i) end)
                if okEntry and entry then
                    local entryKey = nil
                    local entryValue = nil
                    if type(entry) == "table" then
                        entryKey = entry.key or entry[1]
                        entryValue = entry.value or entry[2]
                    else
                        local okKey, k = pcall(function() return entry.getKey and entry:getKey() end)
                        local okValue, v = pcall(function() return entry.getValue and entry:getValue() end)
                        if okKey then entryKey = k end
                        if okValue then entryValue = v end
                    end

                    if tostring(entryKey) == tostring(key) then
                        return entryValue
                    end
                end
            end
        end
    end

    if props.entrySet then
        local okEntries, entries = pcall(function() return props:entrySet() end)
        if okEntries and entries and entries.iterator then
            local okIterator, iterator = pcall(function() return entries:iterator() end)
            if okIterator and iterator then
                while true do
                    local okHasNext, hasNext = pcall(function() return iterator:hasNext() end)
                    if not okHasNext or not hasNext then break end

                    local okEntry, entry = pcall(function() return iterator:next() end)
                    if okEntry and entry then
                        local okKey, entryKey = pcall(function() return entry.getKey and entry:getKey() end)
                        if okKey and tostring(entryKey) == tostring(key) then
                            local okValue, entryValue = pcall(function() return entry.getValue and entry:getValue() end)
                            return okValue and entryValue or nil
                        end
                    end
                end
            end
        end
    end

    return nil
end

local function getScriptProperty(item, key)
    if not item or not key or not item.getScriptItem then return nil end

    local script = item:getScriptItem()
    if not script then return nil end

    if script.getProperty then
        local ok, value = pcall(function() return script:getProperty(key) end)
        if ok and value ~= nil and value ~= "" then return value end
    end

    if script.getAllProperties then
        local ok, props = pcall(function() return script:getAllProperties() end)
        if ok then
            local value = readPropertyContainer(props, key)
            if value ~= nil and value ~= "" then return value end
        end
    end

    local modData = item.getModData and item:getModData()
    if modData and modData[key] ~= nil and modData[key] ~= "" then
        return modData[key]
    end

    return nil
end

local function propGetter(key)
    return function(item)
        return getScriptProperty(item, key)
    end
end

M.defs = {
    --==========================================
    -- ELECTRONICS: ADVANCED SUBSTATS
    --==========================================
    {
        id       = "powerConsumption",
        labelKey = "IGUI_Inspect_Electronics_Label_PowerConsumption",
        fallback = "Power consumption",
        getter   = propGetter("powerConsumption"),
    },
    {
        id       = "powerOutput",
        labelKey = "IGUI_Inspect_Electronics_Label_PowerOutput",
        fallback = "Power output",
        getter   = propGetter("powerOutput"),
    },
    {
        id       = "batteryDrainRate",
        labelKey = "IGUI_Inspect_Electronics_Label_BatteryDrainRate",
        fallback = "Battery drain",
        getter   = propGetter("batteryDrainRate"),
    },

    {
        id       = "signalRange",
        labelKey = "IGUI_Inspect_Electronics_Label_SignalRange",
        fallback = "Signal range",
        getter   = propGetter("signalRange"),
    },
    {
        id       = "signalClarity",
        labelKey = "IGUI_Inspect_Electronics_Label_SignalClarity",
        fallback = "Signal clarity",
        getter   = propGetter("signalClarity"),
    },
    {
        id       = "frequencySupport",
        labelKey = "IGUI_Inspect_Electronics_Label_FrequencySupport",
        fallback = "Frequencies",
        getter   = propGetter("frequencySupport"),
    },

    {
        id       = "lumensEquivalent",
        labelKey = "IGUI_Inspect_Electronics_Label_Lumens",
        fallback = "Lumens",
        getter   = propGetter("lumensEquivalent"),
    },
    {
        id       = "beamDistance",
        labelKey = "IGUI_Inspect_Electronics_Label_BeamDistance",
        fallback = "Beam distance",
        getter   = propGetter("beamDistance"),
    },

    {
        id       = "heatOutput",
        labelKey = "IGUI_Inspect_Electronics_Label_HeatOutput",
        fallback = "Heat output",
        getter   = propGetter("heatOutput"),
    },
    {
        id       = "riskRating",
        labelKey = "IGUI_Inspect_Electronics_Label_RiskRating",
        fallback = "Risk",
        getter   = propGetter("riskRating"),
    },

    {
        id       = "memoryCapacity",
        labelKey = "IGUI_Inspect_Electronics_Label_MemoryCapacity",
        fallback = "Memory",
        getter   = propGetter("memoryCapacity"),
    },
    {
        id       = "channelCount",
        labelKey = "IGUI_Inspect_Electronics_Label_ChannelCount",
        fallback = "Channels",
        getter   = propGetter("channelCount"),
    },

    {
        id       = "audioGain",
        labelKey = "IGUI_Inspect_Electronics_Label_AudioGain",
        fallback = "Audio gain",
        getter   = propGetter("audioGain"),
    },
    {
        id       = "noiseFilter",
        labelKey = "IGUI_Inspect_Electronics_Label_NoiseFilter",
        fallback = "Noise filter",
        getter   = propGetter("noiseFilter"),
    },
}

M.order = {
    "powerConsumption",
    "powerOutput",
    "batteryDrainRate",

    "signalRange",
    "signalClarity",
    "frequencySupport",

    "lumensEquivalent",
    "beamDistance",

    "heatOutput",
    "riskRating",

    "memoryCapacity",
    "channelCount",

    "audioGain",
    "noiseFilter",
}

return M
