-- 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 m = {}

local log = require "mc.logging"
local LDAP_REMOTEGROUP_PATH_HAED = '/bmc/kepler/AccountService/RemoteGroups/LDAP'
local LDAP_REMOTEGROUP_INTERFACE = 'bmc.kepler.AccountService.RemoteGroup'

-- @function  查询Ldap域控制器集合信息UserDomain由Folder和UserDomain字段拼接显示于snmp
-- @function  来自redfish 插件下 orchestrator/manager.lua文件的get_user_domain函数
-- @param     folder      请求体中传入的Folder, 值为CN=xxx
-- @param     user_domain 请求体中传入的UserDomain, 值为xxx.xxx.xxx
function m.get_user_domain(folder, user_domain)
    local rsp = folder .. ',DC='
    local delimiter = '.'
    local gmatch_res = {}
    -- 使用 Lua 的 string.gmatch 函数进行字符串的拆分
    for match in string.gmatch('.' .. user_domain, "([^" .. delimiter .. "]+)") do
        gmatch_res[#gmatch_res + 1] = match
    end
    rsp = rsp .. table.concat(gmatch_res, ',DC=')
    return rsp
end

-- @function 分割user_domain为域和folder 来自redfish 插件下 orchestrator/manager.lua文件的split_user_domain函数
-- @param user_domain  输入格式为CN=test,OU=testusers,DC=company,DC=com
-- @return 返回为CN=test,OU=testuser和company.com
function m.split_user_domain(user_domain)
    if string.len(user_domain) == 0 then
        return {nil, nil}
    end
    local delimiter = ','
    -- 使用 Lua 的 string.gmatch 函数进行字符串的拆分
    local gmatch_res = {}
    for match in string.gmatch(user_domain, "([^" .. delimiter .. "]+)") do
        gmatch_res[#gmatch_res + 1] = match
    end
    local rsp = {}
    rsp[1] = {}
    rsp[2] = {}
    for _, match in ipairs(gmatch_res) do
        if string.sub(match, 1, 3) ~= 'DC=' then
            table.insert(rsp[1], match)
        else
            table.insert(rsp[2], string.sub(match, 4)) -- 只需要下标4开始的字段，如上例拼成company.com
        end
    end
    if #rsp[1] == 0 then
        rsp[1] = ''
    else
        rsp[1] = table.concat(rsp[1], ',')
    end
    if #rsp[2] == 0 then
        rsp[2] = ''
    else
        rsp[2] = table.concat(rsp[2], '.')
    end
    return rsp
end

-- @function 过滤输入不满足特定条件的元素
-- @param Input  类型为数组，为需要过滤的输入
-- @param condition  过滤条件
-- @return 返回为CN=test,OU=testuser和company.com
function m.filter_table(Input, condition)
    for i=#Input,1,-1 do
        if not (string.match(Input[i], condition)) then
            table.remove(Input, i)
        end
    end
    return Input
end

-- @function 判断是否有group_domain，并传递正确的group_name和group_folder
-- @param    GroupName    请求体中传入的GroupName
-- @param    GroupFolder  请求体中传入的GroupFolder
-- @param    GroupDomain  请求体中传入的GroupDomain
-- @param    IsExist      资源是否存在
-- @return   flag         GroupName、GroupFolder、GroupDomain校验结果
-- @return   group_name   拆解比对成功后实际的group_name
-- @return   group_folder 拆解比对成功后实际的group_folder
function m.get_group_name_folder_domain(GroupName, GroupFolder, GroupDomain, IsExist)
    local group_name
    local group_folder
    if not GroupDomain then
        group_name = GroupName
        group_folder = GroupFolder
    else
        -- 有domain，domain格式 CN=***,OU=***,DC=***...
        local cn_pos = string.find(GroupDomain, 'CN=', 1)
        local pos = string.find(GroupDomain, ',', 1)
        local name_str
        local remain_str
        if cn_pos == nil then
            name_str = GroupName or ''
            remain_str = GroupDomain
        else
            if pos == nil then
                pos = string.len(GroupDomain)
                remain_str = ''
            else
                -- 此处截取+1是为了跳过","
                remain_str = string.sub(GroupDomain, pos + 1, string.len(GroupDomain))
                pos = pos - 1
            end
            -- 此处截取+3是为了跳过"CN="字符串
            name_str = string.sub(GroupDomain, cn_pos + 3, pos)
        end
        -- 此时remain_str期望为GroupDomain去掉"CN=***,"的部分
        local dc_pos = string.find(remain_str, 'DC=', 1)
        local folder_str
        -- remain_str为"***"的格式
        if not dc_pos then
            folder_str = remain_str
        -- remain_str为"DC=***"或",DC=***"的格式
        elseif dc_pos == 4 or dc_pos == 5 then
            folder_str = ''
        -- remain_str为"***,DC=***"的格式
        else
            -- 此处截取-2是为了跳过"DC"和前面的","
            folder_str = string.sub(remain_str, 1, dc_pos - 2)
        end

        -- 若有group_name则进行匹配校验
        if not GroupName then
            group_name = name_str
        else
            group_name = GroupName
        end
        local ou_pos = string.find(folder_str, 'OU=', 1)
        if ou_pos == nil then
            group_folder = GroupFolder
        else
            group_folder = string.sub(folder_str, ou_pos + 3, string.len(folder_str))
        end
    end
    if (not group_name or group_name == '') and (not IsExist) then
        log:error("Set property ****** failed, please check user exist or set GroupDomain or GroupFolder first")
        error(base_messages.InternalError())
    end
    return {group_name, group_folder or "", group_name and true or false}
end

function m.get_group_floder(controller_id, group_id)
    local path = LDAP_REMOTEGROUP_PATH_HAED .. controller_id .. "_" .. group_id
    local ok, object = pcall(mdb.get_object, bus, path, LDAP_REMOTEGROUP_INTERFACE)
    if not ok then
        return nil
    end
    return object.Folder
end

-- @function 将登陆接口（数字）转换为table数组
-- @param 登陆接口
-- @return   登陆接口数组
function m.get_group_interface_table(Input)
    if not Input then
        return nil
    end
    local res = {}
    if (Input & 8)~=0 then
        res[#res + 1] = 'SSH'
    end
    if (Input & 128)~=0 then
        res[#res + 1] = 'Redfish'
    end
    if (Input & 1)~=0 then
        res[#res + 1] = 'Web'
    end
    return res
end

-- @function 将登陆接口（数组）转换为数字，get_group_interface_table的逆反操作
-- @param 登陆接口数组
-- @return   登陆接口数字
function get_interface_number(interface)
    local interface_number = 0
    for _, v in pairs(interface) do
        if v == 'SSH' then
            interface_number = interface_number + 8
        elseif v == 'Web' then
            interface_number = interface_number + 1
        elseif v == 'Redfish' then
            interface_number = interface_number + 128
        end
    end
    return interface_number
end

return m
