-- 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 lu = require 'luaunit'
local c_valve = require 'valve_object'
local c_valves = require 'valves_object'
local c_object_manage = require 'mc.orm.object_manage'
local c_tasks = require 'mc.orm.tasks'
local thermal_db = require 'thermal_mgmt.db'
local hook_tasks = require 'test_common.hook_tasks'
local test_utils = require 'test_utils'
local valve_enums = require 'valve_enums'

TestValve = {}

function TestValve:flush()
    c_tasks.get_instance():run_all_task()
    self.database.db:flush()
end

function TestValve:setUp()
    self.database = thermal_db(':memory:')

    hook_tasks.hook()
    self.object_manage = c_object_manage.new(self.database)
    self.object_manage.app = self

    local valve  = {
        Id = 0,
        Slot = 1,
        LastPatrolTimestamp = 9999,
        PatrolState = "Idle",
        PatrolType = 0,
        Presence = 1,
        InvalidLocationId = 1,
        StandardOpeningDegree = 0,
        OpeningDegree = 0,
        OpeningDegreeState = 0,
        StartPatrol = function ()
            return 1
        end
    }

    local valves = {
        Id = 0,
        PatrolState = "Idle",
        LastPatrolTimestamp = 0
    }

    local valve_obj = test_utils.add_valve_obj(self.object_manage, 'Valve_1', valve)
    local valves_obj = test_utils.add_valves_obj(self.object_manage, 'Valves_1', valves)
    self.object_manage.mc:before_add_object(c_valve.__class_name, valve_obj)
    self.object_manage.mc:add_object(c_valve.__class_name, valve_obj, '010107')
    self.object_manage.mc:before_add_object(c_valves.__class_name, valves_obj)
    self.object_manage.mc:add_object(c_valves.__class_name, valves_obj, '010107')
    self.object_manage.mc:prepare_ok()
    self:flush()
end

function TestValve:tearDown()
    c_object_manage.destroy()
    self.database.db:close()
    hook_tasks.unhook()
end

function TestValve:test_fan_group_ctor_init()
    local obj = c_valve.collection:find({
        Id = 0
    })
    lu.assertEquals(obj.PatrolState,  "Idle")
    lu.assertIsFunction(obj.StartPatrol)
end

function TestValve:test_do_patrol()
    local obj = c_valve.collection:find({
        Id = 0
    })
    -- 无效标准开度
    obj.StandardOpeningDegree = 1200
    lu.assertEquals(obj:do_patrol(), valve_enums.Patrol_Result.Failed)

    -- 当前开度超过100%
    obj.StandardOpeningDegree = 900
    lu.assertEquals(obj:do_patrol(), valve_enums.Patrol_Result.Success)
    lu.assertEquals(obj.OpeningDegreeState, valve_enums.Opening_Degree_State.Abnormal)

    -- 正常巡检触发
    obj.StandardOpeningDegree = 800
    lu.assertEquals(obj:do_patrol(), valve_enums.Patrol_Result.Success)
    lu.assertEquals(obj.OpeningDegreeState, valve_enums.Opening_Degree_State.Normal)

    -- 标定开度不超过87%，82%之上时在巡检过程中能达到阀的开度临界点（95%），巡检也应该正常触发
    obj.StandardOpeningDegree = 870
    lu.assertEquals(obj:do_patrol(), valve_enums.Patrol_Result.Success)
    lu.assertEquals(obj.OpeningDegreeState, valve_enums.Opening_Degree_State.Normal)
    
    obj.StandardOpeningDegree = 0
    lu.assertEquals(obj:do_patrol(), valve_enums.Patrol_Result.Success)
    lu.assertEquals(obj.OpeningDegreeState, valve_enums.Opening_Degree_State.Abnormal)
end

function TestValve:test_start_patrol()
    local valve_obj = c_valve.collection:find({
        Id = 0
    })
    local valves_obj = c_valves.collection:find({
        Id = 0
    })

    -- 当前开度为0的情况下不执行巡检
    valve_obj.OpeningDegree = 0
    valves_obj:start_patrol(true, 0)
    lu.assertEquals(valves_obj.LastPatrolTimestamp, 0)

    -- 当前阀门不在位的情况下不执行巡检
    valve_obj.Presence = 0
    valves_obj:start_patrol(true, 0)
    lu.assertEquals(valves_obj.LastPatrolTimestamp, 0)
end