-- 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 class = require 'mc.class'
local app_service = require 'manufacture.service'
local ipmi_message = require 'manufacture.ipmi.ipmi'
local factory = require 'factory'
local log = require 'mc.logging'
local manufacture_service = require 'manufacture_service'
local device_chip_service = require 'device_chip.device_chip_service'
local external_interface_handler = require 'external_interface.handler'
local ipmi_get_test_item_count = require 'ipmi_cmd.get_test_item_count'
local ipmi_get_test_item_info = require 'ipmi_cmd.get_test_item_info'
local ipmi_start_dft_test = require 'ipmi_cmd.start_dft_test'
local ipmi_read_version_data = require 'ipmi_cmd.read_version_data'
local ipmi_get_dft_result = require 'ipmi_cmd.get_dft_result'
local ipmi_import_image_to_gpu = require 'ipmi_cmd.import_image_to_gpu'
local reboot_manage = require 'mc.mdb.micro_component.reboot'
local object_manage = require 'mc.mdb.object_manage'
local skynet = require 'skynet'
local manufacture_db = require 'db_singleton'
local mc_admin = require 'mc.mc_admin'
local utils_core = require 'utils.core'
local common = require 'external_interface.common'

local manufacture_app = class(app_service)

function manufacture_app:ctor()
    self.manufacture_service = manufacture_service.new()
    self.device_chip_service = device_chip_service.new()
    self.external_interface_handler = external_interface_handler.new(self.bus)
    self.manufacture_db = manufacture_db.new(self)
    factory.register_to_factory("manufacture_service", self.manufacture_service)
    factory.register_to_factory("device_chip_service", self.device_chip_service)
    factory.register_to_factory("external_interface_handler", self.external_interface_handler)
end

function manufacture_app:check_dependencies()
    local admin = mc_admin.new()
    admin:parse_dependency(utils_core.getcwd() .. '/mds/service.json')
    admin:check_dependency(self.bus)
end

function manufacture_app:init()
    manufacture_app.super.init(self)
    self:check_dependencies()
    self:register_ipmi_commands()
    self:register_object_callback()
    self:main()
end

function manufacture_app:register_ipmi_commands()
    self:register_ipmi_cmd(ipmi_message.GetTestItemCount, ipmi_get_test_item_count.get_test_item_count)
    self:register_ipmi_cmd(ipmi_message.GetTestItemInfo, ipmi_get_test_item_info.get_test_item_info)
    self:register_ipmi_cmd(ipmi_message.StartDftTest, ipmi_start_dft_test.start_dft_test)
    self:register_ipmi_cmd(ipmi_message.GetDftResult, ipmi_get_dft_result.get_test_result)
    self:register_ipmi_cmd(ipmi_message.ReadVersionData, ipmi_read_version_data.read_version_data)
    self:register_ipmi_cmd(ipmi_message.ImportImageToGpu, ipmi_import_image_to_gpu.import_image_to_gpu)
end

function manufacture_app:register_object_callback()
    object_manage.on_add_object(self.bus, function(class_name, object, position)
        self.device_chip_service:on_add_object(class_name, object, position)
    end)
end

function manufacture_app:on_reboot_prepare()
    log:info("[manufacture_app] reboot prepare")
end

function manufacture_app:on_reboot_cancel()
    log:info("[manufacture_app] reboot cancel")
end
 
function manufacture_app:on_reboot_action()
    log:info("[manufacture_app] reboot action")
end
 
function manufacture_app:register_reboot_methods()
    -- 注册平滑重启回调函数
    -- Prepare准备重启回调
    reboot_manage.on_prepare(function()
        self:on_reboot_prepare()
        return 0
    end)
    -- Action执行重启回调
    reboot_manage.on_action(function()
        self:on_reboot_action()
        return 0
    end)
    -- Cancel取消重启回调
    reboot_manage.on_cancel(function()
        self:on_reboot_cancel()
    end)
end

function manufacture_app:main()
    skynet.fork(function ()
        skynet.sleep(4000)
        -- 在初始化阶段获取一次全部版本并缓存，避免ipmi超时
        ipmi_read_version_data.read_version_data({
            FruId = 0,
            VerType = common.ALL_VERSION,
            Offset = 0,
            Length = 0xff  -- 默认获取ipmi全部返回，最大长度255
        })
    end)

    local M_ARENA_MAX<const> = -8
    local M_TRIM_THRESHOLD<const> = -1

    -- M_ARENA_MAX: 最大ARENA数量,可以理解成进程拥有的堆内存池最大数量
    utils_core.mallopt(M_ARENA_MAX, 1)
    -- M_TRIM_THRESHOLD: 自动回收堆顶空闲内存空间给内核的阈值,单元:byte
    utils_core.mallopt(M_TRIM_THRESHOLD, 4 * 1024)

    skynet.fork(function()
        while true do
            utils_core.malloc_trim(0)
            skynet.sleep(10 * 60 * 100) -- 10分钟trim一次
        end
    end)
end
return manufacture_app
