-- 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 singleton = require 'mc.singleton'
local class = require 'mc.class'
local log = require 'mc.logging'
local singal = require 'mc.signal'
local client = require 'iam.client'
local context = require 'mc.context'
local error = require 'iam.errors'
local base_msg = require 'messages.base'
local vos = require 'utils.vos'
local SessionCollection = class()

local session = require 'session.domain.session'


function SessionCollection:ctor()
    self.session_type = 255
end

function SessionCollection:singles_init()
    self.m_session_config_create = singal.new()
    self.m_session_config_modified = singal.new()
end

function SessionCollection:init()
    self:singles_init()
    self:get_config_from_db()
    self.collection = {}
end

function SessionCollection:get_config_from_db()
    self.session_maxcount = 4
    self.session_timeout = 300
    self.session_mode = 0
end

function SessionCollection:create(account_info, password, ip)
    local session_obj = session.new(account_info, password, ip, self.session_type_string)
    table.insert(self.collection, session_obj)
    return session_obj
end

function SessionCollection:delete(session_id)
    local target_index = nil
    for index, session_obj in pairs(self.collection) do
        if session_obj.session_id == session_id then
            target_index = index
            break
        end
    end
    if target_index == nil then
        log:error('delete sessions((%s)) failed, invalid session id', session_id)
        error(base_msg.InternalError())
    end
    table.remove(self.collection, target_index)
end

function SessionCollection:all_delete(logout_type)
    local id_collection = {}
    for _, session_obj in pairs(self.collection) do
        table.insert(id_collection, session_obj.session_id)
    end
    self.collection = {}
    return id_collection
end

function SessionCollection:get_session_by_session_id(session_id)
    for _, session_obj in pairs(self.collection) do
        if session_obj.session_id == session_id then
            return session_obj
        end
    end
    return nil
end

function SessionCollection:set_timeout(value)
    self.session_timeout = value
end

function SessionCollection:set_mode(value)
    self.session_mode = value
end

function SessionCollection:set_max_count(value)
    self.session_maxcount = value
end

function SessionCollection:get_session_by_token(token, csrf_token)
    local target_index = nil
    for index, session_obj in pairs(self.collection) do
        if csrf_token == nil or session_obj.csrf_token == csrf_token and session_obj.token == token then
            target_index = index
            break
        end
    end
    return target_index and self.collection[target_index]
end

function SessionCollection:remove_timeout_sessions()
    local timeout_session_id_list = {}
    local cur_time = vos.vos_get_cur_time_stamp()
    for _, session_obj in pairs(self.collection) do
        if cur_time > session_obj.session_last_renew_time + self.session_timeout then
            table.insert(timeout_session_id_list, session_obj.session_id)
        end
    end
    for _, timeout_session_id in pairs(timeout_session_id_list) do
        log:notice("session ((%s)) timeout, have to remove this session", timeout_session_id)
        self:delete(timeout_session_id)
    end
end

return singleton(SessionCollection)
