-- Copyright (c) 2025 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You can use this software according to the terms and conditions of the Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at: http://license.coscl.org.cn/MulanPSL2
--
-- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
-- EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
-- MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-- See the Mulan PSL v2 for more details.

local json = require 'cjson'
local context = require 'mc.context'

local m = {}

function m.is_valid_power_supplies_id(slot_number)
    if not slot_number:match("^%d+$") then
        return false
    end
    local id = tonumber(slot_number)
    local onepower_path = bus:call('bmc.kepler.maca', '/bmc/kepler/MdbService', 'bmc.kepler.Mdb', 'GetPath',
    'a{ss}ssb', context.new(), "bmc.kepler.Systems.PowerMgmt.OnePower",
    json.encode({SlotNumber = id}), false)
    if onepower_path == '' then
        return false
    end
    return true
end

local function get_sensor(id, identifier, sensor_list)
    local oid
    for _, obj in pairs(sensor_list) do
        if obj.SensorIdentifier == identifier then
            oid = '/redfish/v1/Chassis/' .. id .. '/Sensors/' ..
                string.format(string.gsub(obj.SensorName, " ", "") .. '.' .. obj.SensorNumber)
            return {oid, obj.SensorReading ~= 'na' and tonumber(obj.SensorReading) or json.null}
        end
    end
    return nil
end

function m.get_input_current_amps(id, slot_number, sensor_list)
    return get_sensor(id, "PS" .. slot_number .. " IIn", sensor_list)
end

function m.get_input_power_watts(id, slot_number, sensor_list)
    return get_sensor(id, "Power" .. slot_number, sensor_list)
end

function m.get_input_voltage(id, slot_number, sensor_list)
    return get_sensor(id, "PS" .. slot_number .. " VIN", sensor_list)
end

function m.get_output_power_watts(id, slot_number, sensor_list)
    return get_sensor(id, "PS" .. slot_number .. " POut", sensor_list)
end

function m.get_rail_power_watts(id, slot_number, sensor_list)
    local identifier, sensor_pwr_2, sensor_pwr_3
    local rail_power_watts = cjson.json_object_new_array()

    identifier = "BCU1 12V0_2 Pwr"
    sensor_pwr_2 = get_sensor(id, identifier, sensor_list)
    identifier = "BCU1 12V0_3 Pwr"
    sensor_pwr_3 = get_sensor(id, identifier, sensor_list)

    local new_sensor_list = {sensor_pwr_2, sensor_pwr_3}
    local rail_num = 1
    for _, sensor in pairs(new_sensor_list) do
        if sensor then
            rail_power_watts[rail_num] = cjson.json_object_new_object()
            rail_power_watts[rail_num]["DataSourceUri"] = sensor[1]
            rail_power_watts[rail_num]["Reading"] = sensor[2]
            rail_num = rail_num + 1
        end
    end

    return rail_power_watts
end

function m.get_rail_voltage(id, slot_number, sensor_list)
    local identifier, sensor_vol_2, sensor_vol_3
    local rail_voltage = cjson.json_object_new_array()

    identifier = "BCU1 VCC_12V0_2"
    sensor_vol_2 = get_sensor(id, identifier, sensor_list)
    identifier = "BCU1 VCC_12V0_3"
    sensor_vol_3 = get_sensor(id, identifier, sensor_list)

    local new_sensor_list = {sensor_vol_2, sensor_vol_3}
    local rail_num = 1
    for _, sensor in pairs(new_sensor_list) do
        if sensor then
            rail_voltage[rail_num] = cjson.json_object_new_object()
            rail_voltage[rail_num]["DataSourceUri"] = sensor[1]
            rail_voltage[rail_num]["Reading"] = sensor[2]
            rail_num = rail_num + 1
        end
    end

    return rail_voltage
end

--这里用电源环境温度
function m.get_temperature_celsius(id, slot_number, sensor_list)
    return get_sensor(id, "PS" .. slot_number .. " Inlet Temp", sensor_list)
end

local function contains_values(sersor_identifier, sensor_identifier_list)
    for _, identifier in pairs(sensor_identifier_list) do
        if string.find(sersor_identifier, identifier) then
            return false
        end
    end
    return false
end

local state_to_value = {
    ['Enabled'] = 0,
    ['Disabled'] = 1,
    ['Intest'] = 2,
    ['Starting'] = 3
}

local value_to_state = {
    [0] = 'Enabled',
    [1] = 'Disabled',
    [2] = 'Intest',
    [3] = 'Starting'
}

local health_to_value = {
    ['OK'] = 0,
    ['Minor'] = 1,
    ['Major'] = 2,
    ['Critical'] = 3
}

local value_to_health = {
    [0] = 'OK',
    [1] = 'Minor',
    [2] = 'Major',
    [3] = 'Critical'
}

function m.get_status(id, slot_number, sensor_list)
    local sensor_identifier_list = {
        "PS" .. slot_number .. " IIn",
        "Power" .. slot_number,
        "PS" .. slot_number .. " VIN",
        "PS" .. slot_number .. " POut",
        "PS" .. slot_number .. " Inlet Temp"
    }
    local state = 0
    local health = 0
    for _, obj in pairs(sensor_list) do
        if contains_values(obj.SensorIdentifier, sensor_identifier_list) then
            if state_to_value[obj.Status] > state then
                state = state_to_value[obj.Status]
            end
            if health_to_value[obj.Health] > health then
                health = health_to_value[obj.Health]
            end
        end
    end
    return {value_to_state[state], value_to_health[health]}
end

return m