-- 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 Databases = require 'database'
local Col = require 'database.column'

local def_types = require 'class.types.types'

---@class ChassisFruCtrlTable: Table
---@field PowerState FieldBase
---@field PowerOnStrategy FieldBase
---@field PreviousPowerState FieldBase
---@field Id FieldBase
---@field PowerGDState FieldBase
---@field StaggeredPowerOnInterval FieldBase
---@field PowerCycleInterval FieldBase
---@field PowerCycleType FieldBase
---@field PowerCycleState FieldBase

---@class FruCtrlTable: Table
---@field PwrOnLocked FieldBase
---@field Reasons FieldBase
---@field Mode FieldBase
---@field Seconds FieldBase
---@field PowerState FieldBase
---@field SysResetDetected FieldBase
---@field FruType FieldBase
---@field CurrentRestartCause FieldBase
---@field CurrentRestartCauseId FieldBase
---@field CurrentRestartType FieldBase
---@field RestartCauseRecords FieldBase
---@field RestartCount FieldBase
---@field PowerOnStrategy FieldBase
---@field PowerOnStrategyExceptions FieldBase
---@field PanelPowerButtonEnabled FieldBase
---@field GracefulShutdownTimeoutEnabled FieldBase
---@field GracefulShutdownTimeoutSeconds FieldBase
---@field GracefulShutdownDefaultTimeoutSeconds FieldBase
---@field GracefulShutdownMaxTimeoutSeconds FieldBase
---@field GracefulShutdownMinTimeoutSeconds FieldBase
---@field HotswapState FieldBase
---@field LastPowerEvent FieldBase
---@field PowerCtrlFault FieldBase
---@field PowerCycleType FieldBase
---@field PreviousPowerState FieldBase
---@field ACCycleEnabled FieldBase
---@field Action FieldBase
---@field TimeDelaySeconds FieldBase
---@field Id FieldBase
---@field FruID FieldBase
---@field PwrCycleDelaySeconds FieldBase
---@field PwrStateBeforeACLost FieldBase
---@field BmcResetFlag FieldBase
---@field PwrRestoreRecord FieldBase
---@field PwrOnLockedRecord FieldBase
---@field PowerOnTimeoutSeconds FieldBase
---@field IsValid FieldBase
---@field ACPISystemPowerState FieldBase
---@field ACPIDevicePowerState FieldBase
---@field ActionModified FieldBase
---@field TimeDelaySecondsModified FieldBase

---@class ButtonEvtTable: Table
---@field Id FieldBase
---@field PowerBtnLock FieldBase
---@field GetPowerBtnEvt FieldBase
---@field SetPowerBtnEvt FieldBase
---@field PowerBtnShield FieldBase
---@field PowerButtonShieldEnabled FieldBase

---@class SystemLockDownTable: Table
---@field SystemLockDownSupport FieldBase
---@field SystemLockDownStatus FieldBase
---@field FruID FieldBase
---@field SystemId FieldBase
---@field IsValid FieldBase

---@class FructrlDBDatabase
---@field db DataBase
---@field select fun(db:DataBase, table: any, ...): SelectStatement
---@field update fun(db:DataBase, table: any, ...): UpdateStatement
---@field insert fun(db:DataBase, table: any, ...): InsertStatement
---@field ChassisFruCtrl ChassisFruCtrlTable
---@field FruCtrl FruCtrlTable
---@field ButtonEvt ButtonEvtTable
---@field SystemLockDown SystemLockDownTable
local FructrlDBDatabase = {}
FructrlDBDatabase.__index = FructrlDBDatabase

function FructrlDBDatabase.new(path, datas)
    local db = Databases(path)
    local obj = {db = db}

    obj.ChassisFruCtrl = db:Table('t_chassis_fructrl_tb', {
        PowerState = Col.TextField():cid(1):persistence_key('protect_reset'):null(),
        PowerOnStrategy = Col.TextField():cid(2):persistence_key('protect_power_off'):null()
            :default('\'AlwaysPowerOn\''),
        PreviousPowerState = Col.TextField():cid(3):persistence_key('protect_power_off'):null():default('\'ON\''),
        Id = Col.IntegerField():cid(4):primary_key():max_length(8),
        PowerGDState = Col.IntegerField():cid(5):null():max_length(8),
        StaggeredPowerOnInterval = Col.IntegerField():cid(6):null():max_length(8):default(60),
        PowerCycleInterval = Col.IntegerField():cid(7):null():max_length(8):default(10),
        PowerCycleType = Col.IntegerField():cid(8):persistence_key('protect_reset'):null():max_length(8):default(0),
        PowerCycleState = Col.IntegerField():cid(9):persistence_key('protect_reset'):null():max_length(8):default(0)
    }):create_if_not_exist(datas and datas['t_chassis_fructrl_tb'])
    obj.FruCtrl = db:Table('t_fructrl_tb', {
        PwrOnLocked = Col.BooleandField():cid(1):persistence_key('protect_temporary'):null(),
        Reasons = Col.JsonField():cid(2):persistence_key('protect_temporary'):null(),
        Mode = Col.TextField():cid(3):persistence_key('protect_power_off'):null():default('\'DefaultDelay\''),
        Seconds = Col.RealField():cid(4):persistence_key('protect_power_off'):null(),
        PowerState = Col.TextField():cid(5):persistence_key('protect_reset'):null(),
        SysResetDetected = Col.IntegerField():cid(6):null():max_length(8),
        FruType = Col.TextField():cid(7):null(),
        CurrentRestartCause = Col.TextField():cid(8):persistence_key('protect_reset'):null(),
        CurrentRestartCauseId = Col.IntegerField():cid(9):persistence_key('protect_reset'):null():max_length(8),
        CurrentRestartType = Col.IntegerField():cid(10):null():max_length(8):default(255),
        RestartCauseRecords = Col.JsonField():cid(11):persistence_key('protect_reset'):null(),
        RestartCount = Col.IntegerField():cid(12):null():max_length(8),
        PowerOnStrategy = Col.TextField():cid(13):persistence_key('protect_power_off'):null():default(
            '\'AlwaysPowerOn\''),
        PowerOnStrategyExceptions = Col.IntegerField():cid(14):persistence_key('protect_power_off'):null()
            :max_length(32),
        PanelPowerButtonEnabled = Col.BooleandField():cid(15):persistence_key('protect_power_off'):null():default(true),
        GracefulShutdownTimeoutEnabled = Col.IntegerField():cid(16):persistence_key('protect_power_off'):null()
            :max_length(32),
        GracefulShutdownTimeoutSeconds = Col.IntegerField():cid(17):persistence_key('protect_power_off'):null()
            :max_length(32):default(600),
        GracefulShutdownDefaultTimeoutSeconds = Col.IntegerField():cid(18):null():max_length(32):default(600),
        GracefulShutdownMaxTimeoutSeconds = Col.IntegerField():cid(19):null():max_length(32):default(6000),
        GracefulShutdownMinTimeoutSeconds = Col.IntegerField():cid(20):null():max_length(32):default(10),
        HotswapState = Col.TextField():cid(21):null(),
        LastPowerEvent = Col.IntegerField():cid(22):persistence_key('protect_reset'):null():max_length(8),
        PowerCtrlFault = Col.IntegerField():cid(23):persistence_key('protect_reset'):null():max_length(8),
        PowerCycleType = Col.IntegerField():cid(24):persistence_key('protect_power_off'):null():max_length(8),
        PreviousPowerState = Col.TextField():cid(25):persistence_key('protect_power_off'):null(),
        ACCycleEnabled = Col.BooleandField():cid(26):persistence_key('protect_power_off'):null(),
        Action = Col.IntegerField():cid(27):persistence_key('protect_power_off'):null():max_length(8):default(1),
        TimeDelaySeconds = Col.IntegerField():cid(28):persistence_key('protect_power_off'):null():max_length(32)
            :default(300),
        Id = Col.IntegerField():cid(29):primary_key():max_length(8),
        FruID = Col.IntegerField():cid(30):null():max_length(8):default(0),
        PwrCycleDelaySeconds = Col.IntegerField():cid(31):persistence_key('protect_power_off'):null():max_length(32)
            :default(10),
        PwrStateBeforeACLost = Col.BooleandField():cid(32):persistence_key('protect_power_off'):null(),
        BmcResetFlag = Col.IntegerField():cid(33):persistence_key('protect_reset'):null():max_length(8):default(0),
        PwrRestoreRecord = Col.JsonField():cid(34):persistence_key('protect_power_off'):null(),
        PwrOnLockedRecord = Col.JsonField():cid(35):persistence_key('protect_temporary'):null(),
        PowerOnTimeoutSeconds = Col.IntegerField():cid(36):null():max_length(32):default(10),
        IsValid = Col.BooleandField():cid(37):null():default(true),
        ACPISystemPowerState = Col.TextField():cid(38):persistence_key('protect_reset'):null():default('\'\''),
        ACPIDevicePowerState = Col.TextField():cid(39):persistence_key('protect_reset'):null():default('\'\''),
        ActionModified = Col.BooleandField():cid(40):persistence_key('protect_power_off'):null():default(false),
        TimeDelaySecondsModified = Col.BooleandField():cid(41):persistence_key('protect_power_off'):null()
            :default(false)
    }):create_if_not_exist(datas and datas['t_fructrl_tb'])
    obj.ButtonEvt = db:Table('t_powerbtn_tb', {
        Id = Col.IntegerField():cid(1):primary_key():max_length(8),
        PowerBtnLock = Col.IntegerField():cid(2):null():max_length(8),
        GetPowerBtnEvt = Col.IntegerField():cid(3):null():max_length(8),
        SetPowerBtnEvt = Col.IntegerField():cid(4):null():max_length(8),
        PowerBtnShield = Col.IntegerField():cid(5):null():max_length(8),
        PowerButtonShieldEnabled = Col.BooleandField():cid(6):persistence_key('protect_power_off'):null():default(false)
    }):create_if_not_exist(datas and datas['t_powerbtn_tb'])
    obj.SystemLockDown = db:Table('t_system_lockdown', {
        SystemLockDownSupport = Col.TextField():cid(1):persistence_key('protect_power_off'):null():default(
            '\'Unsupported\''),
        SystemLockDownStatus = Col.TextField():cid(2):persistence_key('protect_power_off'):null()
            :default('\'Unlocked\''),
        FruID = Col.IntegerField():cid(3):null():max_length(8):default(0),
        SystemId = Col.IntegerField():cid(4):primary_key():max_length(8),
        IsValid = Col.BooleandField():cid(5):null():default(true)
    }):create_if_not_exist(datas and datas['t_system_lockdown'])

    obj.tables = db.tables
    return setmetatable(obj, FructrlDBDatabase)
end

function FructrlDBDatabase:select(table, ...)
    return self.db:select(table, ...)
end

function FructrlDBDatabase:update(table, ...)
    return self.db:update(table, ...)
end

function FructrlDBDatabase:insert(table, ...)
    return self.db:insert(table, ...)
end

function FructrlDBDatabase:delete(table, ...)
    return self.db:delete(table, ...)
end

function FructrlDBDatabase:exec(...)
    return self.db:exec(...)
end

return FructrlDBDatabase.new
