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

---@class IpmiSelListTable: Table
---@field RecordId FieldBase
---@field SelType FieldBase
---@field Timestamp FieldBase
---@field GenerateId FieldBase
---@field SelMsgVersion FieldBase
---@field SensorType FieldBase
---@field SensorNumber FieldBase
---@field SelEventType FieldBase
---@field SelData1 FieldBase
---@field SelData2 FieldBase
---@field SelData3 FieldBase
---@field SensorId FieldBase
---@field SensorName FieldBase
---@field SubjectName FieldBase
---@field RecordSeq FieldBase

---@class PersistPropertyTable: Table
---@field PerId FieldBase
---@field Key FieldBase
---@field Value FieldBase

---@class SensorDBDatabasePoweroff
---@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 IpmiSelList IpmiSelListTable
---@field PersistProperty PersistPropertyTable

local SensorDBDatabasePoweroff = {}
SensorDBDatabasePoweroff.__index = SensorDBDatabasePoweroff

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

    obj.IpmiSelList = db:Table('t_ipmi_sel_list', {
        RecordId = Col.IntegerField():cid(1):primary_key():max_length(16),
        SelType = Col.IntegerField():cid(2):max_length(8),
        Timestamp = Col.IntegerField():cid(3):max_length(32),
        GenerateId = Col.IntegerField():cid(4):null():max_length(16),
        SelMsgVersion = Col.IntegerField():cid(5):null():max_length(8),
        SensorType = Col.IntegerField():cid(6):null():max_length(8),
        SensorNumber = Col.IntegerField():cid(7):null():max_length(8),
        SelEventType = Col.IntegerField():cid(8):null():max_length(8),
        SelData1 = Col.IntegerField():cid(9):null():max_length(8),
        SelData2 = Col.IntegerField():cid(10):null():max_length(8),
        SelData3 = Col.IntegerField():cid(11):null():max_length(8),
        SensorId = Col.TextField():cid(12):null(),
        SensorName = Col.TextField():cid(13):null(),
        SubjectName = Col.TextField():cid(14):null(),
        RecordSeq = Col.IntegerField():cid(15):null():max_length(64)
    }):create_if_not_exist(datas and datas['t_ipmi_sel_list'])
    obj.PersistProperty = db:Table('t_persist_property', {
        PerId = Col.TextField():cid(1):primary_key(),
        Key = Col.TextField():cid(2):primary_key(),
        Value = Col.TextField():cid(3):null()
    }):create_if_not_exist(datas and datas['t_persist_property'])

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

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

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

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

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

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

db_selector['poweroff'] = SensorDBDatabasePoweroff.new

---@class SelMsgListTable: Table
---@field SensorId FieldBase
---@field EventMsgVersion FieldBase
---@field SensorType FieldBase
---@field SensorNumber FieldBase
---@field EventType FieldBase
---@field EventDir FieldBase
---@field EventData1 FieldBase
---@field EventData2 FieldBase
---@field EventData3 FieldBase
---@field Level FieldBase

---@class SensorDBDatabaseReset
---@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 SelMsgList SelMsgListTable

local SensorDBDatabaseReset = {}
SensorDBDatabaseReset.__index = SensorDBDatabaseReset

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

    obj.SelMsgList = db:Table('t_sel_msg_list', {
        SensorId = Col.TextField():cid(1):primary_key(),
        EventMsgVersion = Col.IntegerField():cid(2):null():max_length(8),
        SensorType = Col.IntegerField():cid(3):null():max_length(8),
        SensorNumber = Col.IntegerField():cid(4):null():max_length(8),
        EventType = Col.IntegerField():cid(5):null():max_length(8),
        EventDir = Col.IntegerField():cid(6):null():max_length(8),
        EventData1 = Col.IntegerField():cid(7):primary_key():max_length(8),
        EventData2 = Col.IntegerField():cid(8):primary_key():max_length(8),
        EventData3 = Col.IntegerField():cid(9):primary_key():max_length(8),
        Level = Col.IntegerField():cid(10):null():max_length(8)
    }):create_if_not_exist(datas and datas['t_sel_msg_list'])

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

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

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

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

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

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

db_selector['reset'] = SensorDBDatabaseReset.new

local SensorDBDatabase = {}
SensorDBDatabase.__index = SensorDBDatabase

function SensorDBDatabase.new(path, datas, type)
    return db_selector[type] and db_selector[type](path, datas) or nil
end

return SensorDBDatabase.new
