-- 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 log = require 'mc.logging'
local frudata_intf = require 'frudata_intf'
local common = require 'common'
local manage = require 'frudata_object.manage'
local context = require 'mc.context'
local crc16 = require 'mc.crc16'

local frudata_object = {}

frudata_object.__index = frudata_object

function frudata_object:new(fruinfo_manage, obj)
    return setmetatable({
        fruinfo_manage = fruinfo_manage,
        obj = obj
    }, frudata_object)
end

local function frudev_read_from_eeprom(obj)
    local ctx = context.get_context_or_default()
    local fru_id = obj.FruId
    local fru_offset = 0
    local system_data = ''
    local file_len = common.FRU_DATA_LEN
    -- 从0开始，读取2040长度的数据
    local fru_data = obj.FruDev:Read(ctx, fru_offset, file_len)
    -- 计算crc16校验码
    local ok, crc = pcall(function ()
        return crc16(fru_data, 0)
    end)
    if not ok then
        log:error('cal crc failed, err is %s', crc)
        return nil, nil, nil
    end
    local crc_l = crc & 0xff
    local crc_h = crc >> 8
    -- 填充flag("FRU，4字节")、len(fru信息长度，2字节)、crc(fru信息的crc校验，2字节)
    local fru_header = "FRU" .. string.char(0) .. string.char(248) .. string.char(7) .. string.char(crc_l) .. string.char(crc_h)
    local fru_file = fru_header .. fru_data
    log:notice('read eeprom data, frudata(%d) offset = %d, fru_file = [%s]', fru_id, fru_offset, fru_file)
    return fru_file, system_data, fru_offset
end

function frudata_object:init()
    local fru_id = self.obj.FruId
    local fru_file, system_data, fru_offset

    fru_file, system_data, fru_offset = frudev_read_from_eeprom(self.obj)
    if not fru_file or not system_data or not fru_offset then
        return
    end
    -- EepromV2类型电子标签eeprom_format为0，其他类型默认使用TianChi规范类型为1
    local eeprom_format = 0
    local is_sup_dft = 1
    local is_sys_area = fru_id == 0 and 1 or 0

    self.fruinfo_manage[fru_id] = {
        IsSupportDft = is_sup_dft,
        EepFormat = eeprom_format,
        FruOffset = fru_offset,
        SystemOffset = common.SYSTEM_OFFSET
    }

    frudata_intf.frudata_init(fru_id, fru_file, system_data, is_sup_dft, eeprom_format, is_sys_area)
end

function frudata_object:write_system_area_to_eep(fru_id)
    log:error('StorageType is readonly standrad eeprom, not supported for writing')
end

function frudata_object:write_fru_area(fru_id, _)
    log:error('StorageType is readonly standrad eeprom, not supported for writing')
end

function frudata_object:update_sys_data_to_dbus(fru_id)
    manage:update_sys_data_to_dbus(fru_id, self.obj)
end

function frudata_object:update_fru_data_to_dbus(fru_id)
    manage:update_fru_data_to_dbus(fru_id, self.obj)
end

return frudata_object