-- 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'

---@class IpmiSelDescTable: Table
---@field SensorType FieldBase
---@field ReadingType FieldBase
---@field AlarmLevel FieldBase
---@field SelDesc FieldBase
---@field SelData1 FieldBase
---@field SelData2 FieldBase
---@field SelData3 FieldBase
---@field ShieldFlag FieldBase

---@class IpmiSelFilterTable: Table
---@field SensorType FieldBase
---@field ReadingType FieldBase
---@field FilterMask1 FieldBase
---@field FilterMask2 FieldBase
---@field FilterMask3 FieldBase

---@class SensorSelInfoTable: Table
---@field SelMode FieldBase
---@field RecordSeq FieldBase
---@field CurRecordId FieldBase
---@field QueryMaxCount FieldBase
---@field AddTimestamp FieldBase
---@field DelTimestamp FieldBase
---@field ReceiverAddr FieldBase
---@field Id FieldBase

---@class IpmiPefConfigTable: Table
---@field Enabled FieldBase
---@field ActionEnabled FieldBase
---@field StartupDelayDisabled FieldBase
---@field AlertStartupDelayDisabled FieldBase
---@field AlertEnabled FieldBase
---@field PowerOffEnabled FieldBase
---@field ResetEnabled FieldBase
---@field PowerCycleEnabled FieldBase
---@field OEMEnabled FieldBase
---@field DiagInterruptEnabled FieldBase
---@field SystemGUIDEnabled FieldBase
---@field StartupDelay FieldBase
---@field AlertStartupDelay FieldBase
---@field SystemGUID FieldBase
---@field Id FieldBase

---@class IpmiPefControlTable: Table
---@field InProgress FieldBase
---@field PostponeTimeout FieldBase
---@field StartupDelayTID FieldBase
---@field Action FieldBase
---@field UnqueuedEvent FieldBase
---@field LastEventBMC FieldBase
---@field LastEventSMS FieldBase
---@field NextEvent FieldBase
---@field Id FieldBase

---@class BootErrorTable: Table
---@field SensorType FieldBase
---@field ReadingType FieldBase
---@field EventData FieldBase
---@field Id FieldBase

---@class SensorDBDatabase
---@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 IpmiSelDesc IpmiSelDescTable
---@field IpmiSelFilter IpmiSelFilterTable
---@field SensorSelInfo SensorSelInfoTable
---@field IpmiPefConfig IpmiPefConfigTable
---@field IpmiPefControl IpmiPefControlTable
---@field BootError BootErrorTable
local SensorDBDatabase = {}
SensorDBDatabase.__index = SensorDBDatabase

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

    obj.IpmiSelDesc = db:Table('t_ipmi_sel_descs', {
        SensorType = Col.IntegerField():cid(1):primary_key():max_length(8),
        ReadingType = Col.IntegerField():cid(2):primary_key():max_length(8),
        AlarmLevel = Col.IntegerField():cid(3):max_length(8),
        SelDesc = Col.TextField():cid(4),
        SelData1 = Col.IntegerField():cid(5):primary_key():max_length(8):default(255),
        SelData2 = Col.IntegerField():cid(6):primary_key():max_length(8):default(255),
        SelData3 = Col.IntegerField():cid(7):primary_key():max_length(8):default(255),
        ShieldFlag = Col.IntegerField():cid(8):null():max_length(8):default(0)
    }, 'protect_power_off'):create_if_not_exist(datas and datas['t_ipmi_sel_descs'])
    obj.IpmiSelFilter = db:Table('t_ipmi_sel_filters', {
        SensorType = Col.IntegerField():cid(1):primary_key():max_length(8),
        ReadingType = Col.IntegerField():cid(2):primary_key():max_length(8),
        FilterMask1 = Col.IntegerField():cid(3):primary_key():max_length(16):default(65535),
        FilterMask2 = Col.IntegerField():cid(4):null():max_length(16):default(65535),
        FilterMask3 = Col.IntegerField():cid(5):null():max_length(16):default(65535)
    }, 'protect_power_off'):create_if_not_exist(datas and datas['t_ipmi_sel_filters'])
    obj.SensorSelInfo = db:Table('t_sel_info', {
        SelMode = Col.IntegerField():cid(1):max_length(8),
        RecordSeq = Col.IntegerField():cid(2):max_length(64),
        CurRecordId = Col.IntegerField():cid(3):max_length(16):default(0),
        QueryMaxCount = Col.IntegerField():cid(4):max_length(16):default(2000),
        AddTimestamp = Col.IntegerField():cid(5):max_length(32):default(4294967295),
        DelTimestamp = Col.IntegerField():cid(6):max_length(32):default(4294967295),
        ReceiverAddr = Col.IntegerField():cid(7):max_length(8):default(255),
        Id = Col.IntegerField():cid(8):primary_key():max_length(8):default(1)
    }, 'protect_power_off'):create_if_not_exist(datas and datas['t_sel_info'])
    obj.IpmiPefConfig = db:Table('t_pef_config', {
        Enabled = Col.IntegerField():cid(1):null():max_length(8):default(1),
        ActionEnabled = Col.IntegerField():cid(2):null():max_length(8):default(0),
        StartupDelayDisabled = Col.IntegerField():cid(3):null():max_length(8):default(0),
        AlertStartupDelayDisabled = Col.IntegerField():cid(4):null():max_length(8):default(0),
        AlertEnabled = Col.IntegerField():cid(5):null():max_length(8):default(1),
        PowerOffEnabled = Col.IntegerField():cid(6):null():max_length(8):default(1),
        ResetEnabled = Col.IntegerField():cid(7):null():max_length(8):default(1),
        PowerCycleEnabled = Col.IntegerField():cid(8):null():max_length(8):default(1),
        OEMEnabled = Col.IntegerField():cid(9):null():max_length(8):default(0),
        DiagInterruptEnabled = Col.IntegerField():cid(10):null():max_length(8):default(0),
        SystemGUIDEnabled = Col.IntegerField():cid(11):null():max_length(8):default(0),
        StartupDelay = Col.IntegerField():cid(12):null():max_length(8):default(0),
        AlertStartupDelay = Col.IntegerField():cid(13):null():max_length(8):default(0),
        SystemGUID = Col.TextField():cid(14):null():default('\'000000000000000000\''),
        Id = Col.IntegerField():cid(15):primary_key():max_length(8):default(1)
    }, 'protect_power_off'):create_if_not_exist(datas and datas['t_pef_config'])
    obj.IpmiPefControl = db:Table('t_pef_control', {
        InProgress = Col.IntegerField():cid(1):null():max_length(8):default(0),
        PostponeTimeout = Col.IntegerField():cid(2):null():max_length(8):default(0),
        StartupDelayTID = Col.IntegerField():cid(3):null():max_length(16):default(0),
        Action = Col.IntegerField():cid(4):null():max_length(32):default(0),
        UnqueuedEvent = Col.IntegerField():cid(5):null():max_length(16):default(0),
        LastEventBMC = Col.IntegerField():cid(6):null():max_length(16):default(0),
        LastEventSMS = Col.IntegerField():cid(7):null():max_length(16):default(0),
        NextEvent = Col.IntegerField():cid(8):null():max_length(16):default(0),
        Id = Col.IntegerField():cid(9):primary_key():max_length(8):default(1)
    }, 'protect_power_off'):create_if_not_exist(datas and datas['t_pef_control'])
    obj.BootError = db:Table('t_boot_error', {
        SensorType = Col.IntegerField():cid(1):null():max_length(8):default(30),
        ReadingType = Col.IntegerField():cid(2):persistence_key('protect_reset'):null():max_length(8):default(111),
        EventData = Col.IntegerField():cid(3):persistence_key('protect_reset'):null():max_length(32):default(4294967295),
        Id = Col.IntegerField():cid(4):primary_key():max_length(8):default(1)
    }):create_if_not_exist(datas and datas['t_boot_error'])

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

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

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

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

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

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

return SensorDBDatabase.new
