local Time = {
    timeZoneOffset = 0,
    differenceTime = 0,
    todayTime = 0,
}

local SECONDS_PRE_DAY = 86400
local SECONDS_PRE_HOUR = 3600
local SECONDS_PRE_MINUTE = 60
local DAY_PER_HOUR = 24

local ZERO_TIME_STR = "00:00:00"
local ZERO_TIME_STR_2 = "00:00"

local UnityTime = CS.UnityEngine.Time

-- 获取服务器的当前时间戳
function Time:getServerTime()
    if not self.serverTime then
        return os.time()
    end
    return self.serverTime + self.differenceTime + GFunc.getTickCount()
end

function Time:getRealtimeSinceStartup()
    return UnityTime.realtimeSinceStartup
end

-- 获取客户端时间戳
-- function Time:getClientTime()
--     return os.time()
-- end

-- 得到特定时间的时间戳
function Time:getCertainTime(data)
    local year = data.year or 0
    local month = data.month or 0
    local day = data.day or 0
    local hour = data.hour or 0
    local minute = data.minute or 0
    local second = data.second or 0
    return os.time({day = day, month = month, year = year, hour = hour, min = minute, sec = second})
end

-- 得到特定时间的时间戳
function Time:getCertainTimeByStr(timeStr)
    -- "2022-08-9 00:00:00"
    if type(timeStr) ~= "string" then
        return 0
    end
    timeStr = string.trim(timeStr)
    local timeTab = {}
    for i,v in string.gmatch(timeStr, "%d+") do
        -- print(i, v)
        table.insert(timeTab, i)
    end
    local year = timeTab[1]
    local month = timeTab[2]
    local day = timeTab[3]
    local hour = timeTab[4]
    local minute = timeTab[5]
    local second = timeTab[6]
    local time = os.time({day = day, month = month, year = year, hour = hour, min = minute, sec = second}) + Time:getClientTimeZone()*3600
    return math.floor(time)
end

-- 格式化时间，返回os.data(finalTime)
function Time:formatTimeExact(time)
    local endTime = self:getServerTime() + time
    return os.date("*t", endTime)
end

-- 格式化y/m/d时间，返回os.data(finalTime)
function Time:formatTimeYMD(time)
    time = time or Time:getServerTime()
    local date = os.date("!*t", time)
    return date.year .. "/" .. date.month .. "/" .. date.day
end

-- 格式化y/m/d/h/m/s时间，返回os.data(finalTime)
function Time:formatTimeYMDHMS(time)
    time = time or Time:getServerTime()
    local date = os.date("!*t", time)
    return date.year .. "/" .. date.month .. "/" .. date.day .. " " .. date.hour .. ":" .. date.min .. ":" .. date.sec
end


function Time:updateServerTimeToday(todayTime)
    todayTime = todayTime or 0
    self.todayTime = GFunc.formatTimeStep(todayTime)
end

function Time:updateServerTime(serverTime)
    self.serverTime = (serverTime or 0) // 1000
    self.differenceTime = -GFunc.getTickCount()
    if EDITOR_MODE then
        Logger.log("updateServerTime:%s", self.differenceTime)
    end
end

function Time:updateByServer(serverTime, todayTime)
    self:updateServerTime(serverTime)
    self:updateServerTimeToday(todayTime)
end

function Time:setServerTimeZone(timeZone)
    self.timeZoneOffset = timeZone - self:getClientTimeZone()
end

function Time:getClientTimeZone()
    local now = os.time()
    local utcdate = os.date("!*t", now)
    local localdate = os.date("*t", now)
    localdate.isdst = false
    return os.difftime(os.time(localdate), os.time(utcdate)) / SECONDS_PRE_HOUR
end

function Time:getTimeZoneOffset()
    return self.timeZoneOffset
end

function Time:getBeginningOfServerToday()
    if Time:getServerTime() > self.todayTime + 86400 then
        self.todayTime = self.todayTime + 86400
    end
    return self.todayTime
end

function Time:getOverOfServerToday(time)
    if time then
        local passS = time % SECONDS_PRE_DAY
        if passS > 0 then
            return time + SECONDS_PRE_DAY - passS
        end
        return time + SECONDS_PRE_DAY
    end
    return self:getBeginningOfServerToday() + SECONDS_PRE_DAY
end

-- 获取今日剩余时间
function Time:getTodaySurplusTime()
    local result = self:getOverOfServerToday() - self:getServerTime()
    if result < 0 then
		result = 0
	end
    return result
end

function Time:getBeginningOfToday()
	local now = os.date('*t', self:getServerTime() + self:getTimeZoneOffset()*SECONDS_PRE_HOUR)
    local beginDay = os.time{year = now.year, month = now.month, day = now.day, hour = 0}
    return beginDay - self:getTimeZoneOffset()*SECONDS_PRE_HOUR
end

function Time:getBeginningOfOneDay(t)
    local now = os.date('*t', t + self:getTimeZoneOffset()*SECONDS_PRE_HOUR)
    local beginDay = os.time{year = now.year, month = now.month, day = now.day, hour = 0}
    return beginDay - self:getTimeZoneOffset()*SECONDS_PRE_HOUR
end

-- 判断时间是否是大于等于今天
function Time:getTimeIsToday(time)
    local todayBegin = self:getBeginningOfToday()
    return time >= todayBegin
end

function Time:splitTime(time)
    time = math.floor(time)
    local reduceD = time % SECONDS_PRE_DAY
    local day = math.floor(time/SECONDS_PRE_DAY)
    local reduceH = reduceD % SECONDS_PRE_HOUR
    local hour = math.floor(reduceD/SECONDS_PRE_HOUR)
    local minute = math.floor(reduceH / SECONDS_PRE_MINUTE)
    local second = reduceH % SECONDS_PRE_MINUTE
    return day, hour, minute, second
end

-- 根据秒换算成向上取整hour的时间
function Time:getCeilHourTime(time)
    local count = time // 3600
    if time % 3600 > 0 then
        count = count + 1
    end
    return count
end

--每几秒 向上取整
function Time:getCeilPerSecend(time, per)
    local count = time // per
    if time % per > 0 then
        count = count + 1
    end
    return count
end

function Time:getDayofWeek(time)
    local curTime = time or self:getServerTime()
    local day = tonumber(os.date("%w", curTime))
    day = day == 0 and 7 or day
    return day
end

function Time:getDayofWeekUTC(time)
    local curTime = time or self:getServerTime()
    local day = tonumber(os.date("!%w", curTime))
    day = day == 0 and 7 or day
    return day
end

-- 00:00:00
function Time:formatNumTime(time)
    if time <= 0 then
        return ZERO_TIME_STR
    end
    local reduceH = time % SECONDS_PRE_HOUR
    local hour = math.floor(time / SECONDS_PRE_HOUR)
    local minute = math.floor(reduceH / SECONDS_PRE_MINUTE)
    local second = reduceH % SECONDS_PRE_MINUTE
    return string.format("%.2d:%.2d:%.2d", hour, minute, second)
end

-- 00:00
function Time:formatNumTimeMS(time)
    if time <= 0 then
        return ZERO_TIME_STR_2
    end
    local minute = math.floor(time / SECONDS_PRE_MINUTE)
    local second = time % SECONDS_PRE_MINUTE
    return string.format("%.2d:%.2d", minute, second)
end

-- 大于1天显示：X天X时 globalkey:ACTIVITY_TIME_STR_DH 小于1天显示：X时X分 globalkey:ACTIVITY_TIME_STR_HM 小于1小时显示：X分X秒 globalkey:ACTIVITY_TIME_STR_MS
function Time:formatNumTimeStr(time)
    if time <= 0 then
        return I18N:getGlobalText(I18N.GlobalConst.TIME_STR_MS, 0, 0)
    end
    local day, hour, minute, second = Time:splitTime(time)
    if time >= SECONDS_PRE_DAY then -- 大于1天显示：X天X时
        return I18N:getGlobalText(I18N.GlobalConst.TIME_STR_DH, day, hour)
    else
        if time >= SECONDS_PRE_HOUR then  -- 小于1天显示：X时X分
            return I18N:getGlobalText(I18N.GlobalConst.TIME_STR_HM, hour, minute)
        else    --小于1小时显示：X分X秒
            return I18N:getGlobalText(I18N.GlobalConst.TIME_STR_MS, minute, second)
        end
    end
end

-- 大于1小时显示：X时前 globalkey:TIME_BEFORE_STR_H 小于1小时显示：X分钟前 globalkey:TIME_BEFORE_STR_M 小于1分钟显示：1分钟前
function Time:formatBeforeTimeStr(time)
    local passTime = Time:getServerTime() - time
    if passTime <= 0 then
        return GConst.EMPTY_STRING
    end

    local hour = math.floor(passTime // SECONDS_PRE_HOUR)
    if hour >= 1 then -- 大于1小时显示：X时前
        return I18N:getGlobalText(I18N.GlobalConst.TIME_BEFORE_STR_H, hour)
    else
        if passTime < SECONDS_PRE_MINUTE then
            passTime = SECONDS_PRE_MINUTE
        end
        local min = math.floor(passTime // SECONDS_PRE_MINUTE)
        return I18N:getGlobalText(I18N.GlobalConst.TIME_BEFORE_STR_M, min)
    end
end

---- 得到time周开始时的时间戳
function Time:getWeekBeginTimeStamp(time)
    time = time or self:getServerTime()
    local remainDay = -self:getDayofWeek(time)
    return self:getOverOfServerToday(time) + remainDay * SECONDS_PRE_DAY
end

---- 得到time周结束时的时间戳
function Time:getWeekOverTimeStamp(time)
    time = time or self:getServerTime()
    local remainDay = 7 - self:getDayofWeek(time)
    return self:getOverOfServerToday(time) + remainDay * SECONDS_PRE_DAY
end

---- 得到time月结束的时间戳
function Time:getMonthOverTimeStamp(time)
    time = time or self:getServerTime()
    local now = os.date('!*t', time)
    now.month = now.month + 1
    if now.month > 12 then
        now.year = now.year + now.month // 12
        now.month = now.month % 12
    end
    local remainDay = os.date("%d", os.time({year = now.year, month = now.month, day = 0})) - now.day
    return self:getOverOfServerToday(time) + remainDay * SECONDS_PRE_DAY
end

---- 得到当前处于本月的第几天
function Time:getDayByTimeStamp(time)
    time = time or self:getServerTime()
    local now = os.date('!*t', time)
    return now.day
end

-- 获取当前处于星期几
function Time:getWeekByTimeStamp(time)
    time = time or self:getServerTime()
    local now = os.date('!*t', time)

    local weekTab = {7, 1, 2, 3, 4, 5, 6}
    return weekTab[now.wday]
end

-- 获取今天距目标日期的天数
function Time:getDistanceDays(time)
    local nowNum = self:getBeginningOfOneDay(self:getServerTime())
    local targetNum = self:getBeginningOfOneDay(time)
    return (nowNum - targetNum)/24/60/60
end

-- 转换服务器时间字符串(ISO 8601)的对应的时间戳,例如2022-09-10T18:10:00.000Z
function Time:convertServerTimeStringToTimestamp(str)
    local dateTime = CS.System.DateTime.Parse(str)
	local dateTimeOffset = CS.System.DateTimeOffset(dateTime)
	return dateTimeOffset:ToUnixTimeSeconds()
end

return Time