local MailData = class("MailData", BaseData)

local MailEntity = "app/userdata/mail/mail_entity"

local TIME_TYPE = {
    DAY = 1,
    WEEK = 2,
    MONTH = 3,
}
function MailData:ctor()
    self.mails = {}
    self.checkNewMailTimsList = {}
    self.needGetNewMail = false
    self.data.isDirty = false
    self.data.redPoint = false
    self.maxMailId = 0
end

function MailData:clear()
    self.mails = {}
    self.data.redPoint = false
    self.lastMailId = nil
    self.mailIsOpen = false
    DataManager:unregisterDataCd("MailData")
    DataManager:unregisterCrossDayFunc("MailData")
end

function MailData:init(data)
    data = data or GConst.EMPTY_TABLE
    self.mails = {}
    self.needGetNewMail = false
    self:addMails(data.mails)

    self:updateRedPointCd()
    DataManager:registerDataCd("MailData")
    DataManager:registerCrossDayFunc("MailData", function()
		self:updateRedPointCd()
    end)
end

function MailData:updateRedPointCd()
    for i = 1, #self.checkNewMailTimsList do
        table.remove(self.checkNewMailTimsList)
    end
    local cfg = ConfigManager:getConfig("mail")
    for i,v in ipairs(cfg) do
        if v.time_type == TIME_TYPE.DAY then
            if #v.time_send == 3 then
                local time = v.time_send[1] * 3600 + v.time_send[2] * 60 + v.time_send[3] + 1
                local currTime = Time:getServerTime() % 86400
                if time >= currTime then
                    local find = false
                    for k, v in ipairs(self.checkNewMailTimsList) do
                        if v == time then
                            find = true
                            break
                        end
                    end
                    if not find then
                        table.insert(self.checkNewMailTimsList, time)
                    end
                end
            end
        elseif v.time_type == TIME_TYPE.WEEK then
            if #v.time_send == 4 then -- 周几，时，分，秒
                local day = v.time_send[1]
                if day == Time:getDayofWeekUTC() then
                    local time = v.time_send[2] * 3600 + v.time_send[3] * 60 + v.time_send[4] + 1
                    local currTime = Time:getServerTime() % 86400
                    if time >= currTime then
                        local find = false
                        for k, v in ipairs(self.checkNewMailTimsList) do
                            if v == time then
                                find = true
                                break
                            end
                        end
                        if not find then
                            table.insert(self.checkNewMailTimsList, time)
                        end
                    end
                end
            end
        elseif v.time_type == TIME_TYPE.MONTH then
            if #v.time_send == 4 then -- 几号，时，分，秒
                local offsetSeconds = math.floor(Time:getClientTimeZone() * 3600)
                local time = Time:getServerTime()
                local utcNow = os.date('!*t', time)
                local targetTime = math.floor(os.time({day = v.time_send[1], month = utcNow.month, year = utcNow.year, hour = v.time_send[2], min = v.time_send[3], sec = v.time_send[4]})) + offsetSeconds
                if targetTime >= time then -- 还没到目标时间
                    local diff = targetTime - time
                    local todayRemainTime = time % 86400 -- 到今天24点还剩余的秒数
                    if diff <= todayRemainTime then -- 今天内就能达到目标时间
                        local targetRemainTime = targetTime % 86400
                        local find = false
                        for k, v in ipairs(self.checkNewMailTimsList) do
                            if v == targetRemainTime then
                                find = true
                                break
                            end
                        end
                        if not find then
                            table.insert(self.checkNewMailTimsList, targetRemainTime)
                        end
                    end
                end
            end
        end
    end
end

function MailData:checkNewMail()
    if #self.checkNewMailTimsList <= 0 then
        return
    end
    local nowTime = Time:getServerTime() % 86400
    for i = #self.checkNewMailTimsList, 1, -1 do
        if self.checkNewMailTimsList[i] <= nowTime then
            table.remove(self.checkNewMailTimsList, i)
            EventManager:dispatchEvent(EventManager.CUSTOM_EVENT.TIME_TRIGGERED_NEW_EMAIL)
            break
        end
    end
end

function MailData:updateCd()
    self:checkNewMail()
end

function MailData:addMails(mails)
    if not mails then
        return
    end

    for _, info in pairs(mails) do
        local entity = require(MailEntity):create(info)
        self.mails[info.id] = entity
        if self.maxMailId < info.id then
            self.maxMailId = info.id
        end
    end

    self:setDirty()
    self:refreshRedPoint()
end

function MailData:getMails()
    return self.mails
end

function MailData:setDirty()
    self.data.isDirty = not self.data.isDirty
end

function MailData:setMailReceived(id)
    if not self.mails[id] then
        return
    end
    self.mails[id]:receivedThis()

    self:setDirty()
    self:refreshRedPoint()
end

function MailData:setMailRead(id)
    if not self.mails[id] then
        return
    end
    self.mails[id]:readThis()

    self:refreshRedPoint()
    self:setDirty()
end

function MailData:deleteMail(ids)
    if not ids then
        return
    end

    for _, id in ipairs(ids) do
        self.mails[id] = nil
    end

    self:setDirty()
end

function MailData:refreshRedPoint()
    if self.needGetNewMail then
        self.data.redPoint = true
        self.isAdRedPoint = false
        return
    end

    local reset = true
    local haveNoAdRp = false
    for id, entity in pairs(self.mails) do
        if entity:canClaim() then
            self.data.redPoint = true
            if entity:getIsAdMail() then
                if not haveNoAdRp then
                    self.isAdRedPoint = true
                end
            else
                haveNoAdRp = true
                self.isAdRedPoint = false
            end
            reset = false
        end
    end
    if reset then
        self.data.redPoint = false
        self.isAdRedPoint = false
    end
end

function MailData:getRedPoint()
    return self.data.redPoint, self.isAdRedPoint
end

function MailData:setNeedGetNewMail(need)
    self.needGetNewMail = need == true
    if self.needGetNewMail then
        self:refreshRedPoint()
    end
end

function MailData:getNeedGetNewMail()
    return self.needGetNewMail
end

function MailData:getLastMailId()
    if not self.lastMailId then
        self.lastMailId = LocalData:getLastMailId()
    end
    return self.lastMailId
end

function MailData:setLastMailId()
    if not self.maxMailId or not self.lastMailId then
        return
    end

    if self.lastMailId < self.maxMailId then
        self.lastMailId = self.maxMailId
        LocalData:setLastMailId(self.lastMailId)
    end
end

function MailData:getIsOpen()
    return ModuleManager:getIsOpen(ModuleManager.MODULE_KEY.MAIL, true)
end

return MailData