-- 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 context = require 'mc.context'
local OBJECT_PROPERTIES_INTERFACE<const> = 'bmc.kepler.Object.Properties'
-- FruCtrl 所在服务
local FRUCTRL_MDB_SERVICE <const> = 'bmc.kepler.fructrl'
-- PowerAction 资源树接口
local POWERACTION_MDB_INTF <const> = 'bmc.kepler.Systems.PowerAction'
local m = {}
local log = require 'mc.logging'
local cjson = require 'cjson'

-- 返回值为数字类型
local function get_sysid(path)
    local sysid = -1
    local err, rsp = bus:pcall(FRUCTRL_MDB_SERVICE, path, OBJECT_PROPERTIES_INTERFACE, 'GetAllWithContext', 'a{ss}s',
        context.get_context() or context.new(), OBJECT_PROPERTIES_INTERFACE)
    if not err then
        local identifier = rsp.ObjectIdentifier and rsp.ObjectIdentifier:value()
        if identifier then
            sysid = identifier[1]
        end
    end
    return sysid
end

local function cleartimeoutFlag_action(ctx, obj, objs, sysid, is_multihost)
    objs[#objs + 1] = {}
    objs[#objs].sysid = sysid
    obj.PowerOnTimeoutFlag = 0
    objs[#objs].flag = obj.PowerOnTimeoutFlag == 0
    if is_multihost then
        log:operation(ctx:get_initiator(), 'fructrl',
            string.format('[System%s] Clear power on lock %s', sysid,
            objs[#objs].flag and 'successfully' or 'failed'))
    else
        log:operation(ctx:get_initiator(), 'fructrl',
            string.format('Clear power on lock %s',
            objs[#objs].flag and 'successfully' or 'failed'))
    end
end

function m.getclear_timeoutFlag(input)
    local ctx = context.get_context()
    local objs = {}
    local poweractionlist
    local poweractionobj
    local sysid
    local is_multihost = mdb.get_object(bus, '/bmc/kepler/Managers/1/Multihost',
        'bmc.kepler.Managers.Multihost').HostType == 'Multihost'
    if #input ~= 0 then
        local sysid = input[1]
        -- input[1]代表 -s 传的参数
        poweractionobj = mdb.get_object(bus, '/bmc/kepler/Systems/'.. sysid ..'/PowerAction', POWERACTION_MDB_INTF)
        sysid = tonumber(sysid)
        cleartimeoutFlag_action(ctx, poweractionobj, objs, sysid, is_multihost)
    else
        poweractionlist = mdb.get_sub_objects(bus, '/bmc/kepler/Systems', POWERACTION_MDB_INTF, 2)
        for _, v in pairs(poweractionlist) do
            sysid = get_sysid(v.path)
            cleartimeoutFlag_action(ctx, v, objs, sysid, is_multihost)
        end
        table.sort(objs, function(a, b)
            return a.sysid < b.sysid
        end)
    end
    return objs
end

function m.get_authorization()
    local status, input = libroutemapper_utils.get_line_without_echo(
        'Input your username and password using the format "username:password":')
    if status ~= 0 or string.match(input, '(.*)%s*:%s*(.*)') == nil then
        return {-1, nil}
    end
    return {0, input}
end

local function adjust_headers(headers, client_ip)
    local request_headers = curl.slist_init()
    for title, content in pairs(headers) do
        request_headers = curl.slist_append(request_headers, title .. ':' .. content)
    end
    local ip = string.match(client_ip, '(.*):.*')
    request_headers = curl.slist_append(request_headers, 'x-real-ip:' .. ip)
    return request_headers
end

function m.call_redfish(input, uri, method, req_body, req_header, client_ip)
    local request_body, request_header, rsp_body
    local curl_uri = 'http://127.0.0.1:30080' .. uri
    if req_body == 'null' then
        request_body = nil
    else
        local ok1, res1 = pcall(cjson.decode, req_body)
        if not ok1 then
            log:error(res1)
            return {-1, nil}
        else
            request_body = req_body
        end
    end
    if req_header == 'null' then
        request_header = {}
    else
        local ok2, res2 = pcall(cjson.decode, req_header)
        if not ok2 then
            log:error(res2)
            return {-2, nil}
        else
            request_header = res2
        end
    end
    local curl_handle = curl.easy_init()
    if curl_handle == nil then
        log:error('get curl handler failed')
        return {-3, nil}
    end
    curl.easy_setopt_customerquest(curl_handle, method)
    curl.easy_setopt_url(curl_handle, curl_uri)
    curl.easy_setopt_userpwd(curl_handle, input[2])
    curl.easy_setopt_httpheader(curl_handle, adjust_headers(request_header, client_ip))
    if request_body then
        curl.easy_setopt_postfields(curl_handle, request_body)
    end
    curl.easy_setopt_writefunction(curl_handle, function (body)
        rsp_body = body
    end)
    local ret_code = curl.easy_perform(curl_handle)
    if ret_code == 0 then
        curl.easy_cleanup(curl_handle)
        return {0, rsp_body}
    else
        local err = curl.easy_strerror(ret_code)
        curl.easy_cleanup(curl_handle)
        return {-4, err}
    end
end

return m
