-- Copyright (c) 2024 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 log = require 'mc.logging'
local custom_msg = require 'messages.custom'
local mdb_service = require 'mc.mdb.mdb_service'

local m = {}

local function size_of(arr)
    if type(arr) ~= 'userdata' then
        return nil
    end
    local ret = 0
    for _, _ in pairs(arr) do
        ret = ret + 1
    end
    return ret
end

local function get_recommended_policy(recommended_policy_names, recommended_policies, influences)
    local recommended_policy_names_size = size_of(recommended_policy_names)
    local recommended_policies_size = size_of(recommended_policies)
    if not recommended_policy_names_size or not recommended_policies_size or not size_of(influences) then
        log:error('Recommended policy data type error.')
        return {}
    end
    if recommended_policy_names_size ~= recommended_policies_size then
        log:error('Recommended policy policies mismatch.')
        return {}
    end
    local ret, obj = {}
    for i = 1, recommended_policy_names_size, 1 do
        obj = {}
        obj.PolicyName = recommended_policy_names[i]
        obj.PolicyValue = recommended_policies[i]
        if influences[i] then
            obj.Effect = influences[i]
        end
        table.insert(ret, obj)
    end
    return ret
end

local function get_current_policy(current_policy_names, current_policies)
    local current_policy_names_size = size_of(current_policy_names)
    local current_policies_size = size_of(current_policies)
    if not current_policy_names_size or not current_policies_size then
        log:error('Current policy data type error.')
        return {}
    end
    if current_policy_names_size ~= current_policies_size then
        log:error('Current policy policies mismatch.')
        return {}
    end
    local ret, obj = {}
    for i = 1, current_policy_names_size, 1 do
        obj = {}
        obj.PolicyName = current_policy_names[i]
        obj.PolicyValue = current_policies[i]
        table.insert(ret, obj)
    end
    return ret
end

function m.get_policy_guidances(input)
    local ret, object = {}
    for _, item in pairs(input) do
        object = {}
        object.ComponentType = item.Component
        object.EnergySavingScore = item.HealthPercent and item.HealthPercent or 0
        object.Current = get_current_policy(item.CurrentPolicyName, item.CurrentPolicies)
        object.Recommended = get_recommended_policy(item.RecommendedPolicyName, item.RecommendedPolicies,
                                    item.Influence)
        table.insert(ret, object)
    end
    return ret
end

function m.check_min_work_psu_count_valid(input)
    if type(input) == 'number' and input > 0 and input < 255 then
        return true
    end
    if input == null then
        return true
    end
    local err = custom_msg.PropertyValueOutOfRange(string.format("%.0f", input), "MinWorkPSUCount", "1",
                tostring(input))
    err.RelatedProperties = {'#/MinWorkPSUCount'}
    error(err)
end

function m.is_supported_energy_saving_measurement()
    local ok, rsp = pcall(mdb_service.is_valid_path, bus, '/bmc/kepler/Chassis/1/EnergySavingMeasurement')
    if not ok or not rsp.Result then
        return false
    end
    return true
end

function m.get_measurement_id(manager_id)
    if m.is_supported_energy_saving_measurement() then
        return {
            ["@odata.id"] = "/redfish/v1/Managers/" .. manager_id .. "/EnergySavingService/Measurement"
        }
    end
    return lua_nil
end

return m
