-- 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 c_object = require 'mc.orm.object'
local log = require 'mc.logging'
local crc16 = require 'mc.crc16'
local skynet = require 'skynet'

local c_super_pod_label = c_object('SuperPodLabel')
local RETRY_TIMES <const> = 3

function c_super_pod_label:ctor()
end

function c_super_pod_label:init()
    log:notice('init SuperPodId: %d, ServerIndex : %d, SuperPodSize : %d,',
        self['SuperPodId'], self['ServerIndex'], self['SuperPodSize'])
    local ok, err = pcall(function ()
        self.SuperPodIdAcc =  self.SuperPodId
        self.ServerIndexAcc =  self.ServerIndex
        self.SuperPodSizeAcc =  self.SuperPodSize
        self.Crc16 = self:cal_crc16(self.ServerIndex, self.SuperPodSize, self.SuperPodId)
    end)

    if not ok then
        log:error('init SuperPodLabel failed, error : %s', err)
    end

    c_super_pod_label.super.init(self)
end

function c_super_pod_label:cal_crc16(server_index, super_pod_size, super_pod_id)
    local data = string.pack('I2I2I4', server_index, super_pod_size, super_pod_id)
    local req_crc = crc16(data)
    log:notice('%d, %d, %d crc16 : %d', server_index, super_pod_size, super_pod_id, req_crc)
    return req_crc
end

function c_super_pod_label:update_super_pod_id(super_pod_id)
    log:notice('update super pod id, value : %d', super_pod_id)
    local times = 1
    local res = false
    while not res and times <= RETRY_TIMES do
        res = pcall(function ()
            self.SuperPodIdAcc = super_pod_id
            self.Crc16 = self:cal_crc16(self.ServerIndex, self.SuperPodSize, super_pod_id)
        end)
        skynet.sleep(1)
        times = times + 1
    end
    if not res then
        log:error("update super pod id failed")
        return false
    end
    if self.SuperPodId ~= super_pod_id then
        self.SuperPodId = super_pod_id
    end
    return res
end

function c_super_pod_label:update_server_index(server_index)
    log:notice('update server index, value : %d', server_index)
    local times = 1
    local res = false
    while not res and times <= RETRY_TIMES do
        res = pcall(function ()
            self.ServerIndexAcc = server_index
            self.Crc16 = self:cal_crc16(server_index, self.SuperPodSize, self.SuperPodId)
        end)
        skynet.sleep(1)
        times = times + 1
    end
    if not res then
        log:error("update server index failed")
        return false
    end
    if self.ServerIndex ~= server_index then
        self.ServerIndex = server_index
    end
    return res
end

function c_super_pod_label:update_super_pod_size(super_pod_size)
    log:notice('update super pod size, value : %d', super_pod_size)
    local times = 1
    local res = false
    while not res and times <= RETRY_TIMES do
        res = pcall(function ()
            self.SuperPodSizeAcc = super_pod_size
            self.Crc16 = self:cal_crc16(self.ServerIndex, super_pod_size, self.SuperPodId)
        end)
        skynet.sleep(1)
        times = times + 1
    end
    if not res then
        log:error("update super pod size failed")
        return false
    end
    if self.SuperPodSize ~= super_pod_size then
        self.SuperPodSize = super_pod_size
    end
    return res
end

function c_super_pod_label:restore_defaults()
    return self:update_super_pod_id(self.DefaultSuperPodId) and
    self:update_server_index(self.DefaultServerIndex) and self:update_super_pod_size(self.DefaultSuperPodSize)

end

return c_super_pod_label