%%%-----------------------------------
%%% @Module  : mod_kf_1vn_mgr
%%% @Email   : ming_up@foxmail.com
%%% @Created : 2018.1.24
%%% @Description: 跨服1vN(跨服中心)
%%%-----------------------------------
-module(mod_kf_1vn_mgr).

-include("common.hrl").
-include("kf_1vn.hrl").

%% API
-export([start_link/0, check_open/0, ac_end/0]).
-export([gm_start_1/3, gm_start_2/2, gm_stage_change/1, reset_sign_time/0]).

%% gen_server callbacks
-export([init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,code_change/3]).

%% 进程启动
start_link() ->
    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).

%% 检查是否开启活动
check_open() ->
    gen_server:cast(?MODULE, check_open).

gm_start_1(SignTime, Race1PreTime, Race1Time) ->
    gen_server:cast(?MODULE, {gm_start_1, SignTime, Race1PreTime, Race1Time}).

gm_start_2(Race2PreTime, Race2Time) ->
    gen_server:cast(?MODULE, {gm_start_2, Race2PreTime, Race2Time}).

gm_stage_change(Stage) ->
    gen_server:cast(?MODULE, {gm_stage_change, Stage}).

ac_end() ->
    gen_server:cast(?MODULE, ac_end).

reset_sign_time() ->
    gen_server:cast(?MODULE, reset_sign_time).

%% 初始化
init([]) ->
    AcIds    = data_kf_1vn:get_ac_ids(),
    Now      = utime:unixtime(),       %% 当前时间戳
    DateTime = utime:unixdate(Now),    %% 当天0点时间戳
    Week     = utime:day_of_week(Now), %% 周几
    State = case check_is_open(AcIds, Week, DateTime, Now) of
        false ->
             #kf_1vn_info{
                all_time = #kf_1vn_time{},
                stage = ?KF_1VN_FREE,
                state = ?KF_1VN_STATE_WAIT};
        {true, _} ->
            #kf_1vn_info{
                all_time = #kf_1vn_time{},
                stage = ?KF_1VN_FREE,
                state = ?KF_1VN_STATE_WAIT}
    end,
    State = #kf_1vn_info{%% 这里暂时不写时间，等活动主进程开启完毕后在检测开启
            all_time = #kf_1vn_time{},
            stage = ?KF_1VN_FREE,
            state = ?KF_1VN_STATE_WAIT},
    {ok, State}.

handle_call(_Request, _From, State) ->
    ?ERR("Handle unkown request[~p]~n", [_Request]),
    Reply = ok,
    {reply, Reply, State}.

handle_cast(Msg, State) ->
    case catch do_handle_cast(Msg, State) of
        {noreply, NewState} ->
            {noreply, NewState};
        Err ->
            ?ERR("Handle msg[~p] error:~p~n", [Msg, Err]),
            {noreply, State}
    end.

do_handle_cast(check_open, State) ->
    #kf_1vn_info{stage=Stage} = State,
    case Stage of
        ?KF_1VN_FREE ->
            AcIds = data_kf_1vn:get_ac_ids(),
            Now = utime:unixtime(),
            DateTime = utime:unixdate(Now),
            Week = utime:day_of_week(Now),
            case check_is_open(AcIds, Week, DateTime, Now) of
                false -> {noreply, State};
                {true, AcR} ->
                    State1 = init_state(AcR, DateTime, State),
                    self() ! {stage_change, ?KF_1VN_SIGN},
                    {noreply, State1#kf_1vn_info{stage=?KF_1VN_SIGN}}
            end;
        _ -> {noreply, State}
    end;

do_handle_cast({gm_start_1, SignTime, Race1PreTime, Race1Time}, State) ->
    #kf_1vn_info{ref=ORef} = State,
    util:cancel_timer(ORef),
    Now = utime:unixtime(),
    AcR = data_kf_1vn:get_info(1),
    #kf_1vn_time_cfg{
        race_2_pre = Race2PreTime, race_2 = Race2Time} = AcR,
    Kf1vNTime = #kf_1vn_time{
        sign_start=Now,
        race_1_pre_start=Now+SignTime,
        race_1_start=Now+SignTime+Race1PreTime,
        race_1_end=Now+SignTime+Race1PreTime+Race1Time,
        race_2_pre_start=Now+SignTime+Race1PreTime+Race1Time,
        race_2_start=Now+SignTime+Race1PreTime+Race1Time+Race2PreTime,
        race_2_end=Now+SignTime+Race1PreTime+Race1Time+Race2PreTime+Race2Time
    },
    Ref = erlang:send_after(50, self(), {stage_change, ?KF_1VN_SIGN}),
    {noreply, State#kf_1vn_info{ac_id=1, all_time=Kf1vNTime, ref=Ref}};

do_handle_cast({gm_end}, State) ->
    mod_kf_1vn:gm_end(),
    {noreply, State};

%% 比赛结束，开启1vn竞拍
do_handle_cast(ac_end, State) ->
    #kf_1vn_info{ref=Ref} = State,
    util:cancel_timer(Ref),
    mod_kf_1vn_auction:auction_start( data_kf_1vn:get_value(?KF_1VN_CFG_AUCTION_START_TIME) * 3600 ),
    {noreply, #kf_1vn_info{ac_id=1, stage=?KF_1VN_FREE, state=?KF_1VN_STATE_WAIT}};

%% 重置报名时间
do_handle_cast(reset_sign_time, State) ->
    #kf_1vn_info{all_time=#kf_1vn_time{race_1_pre_start=Race1PreStart}, ref=Ref} = State,
    Now = utime:unixtime(),
    case Now < Race1PreStart of
        true ->
            Ref1 = util:send_after(Ref, (Race1PreStart - Now) * 1000, self(), {stage_change, ?KF_1VN_RACE_1_PRE}),
            {noreply, State#kf_1vn_info{ref=Ref1}};
        false -> skip
    end;

do_handle_cast({gm_stage_change, Stage}, State) ->
    self() ! {stage_change, Stage},
    {noreply, State};

do_handle_cast(_Msg, State) ->
    ?ERR("Handle unkown msg[~p]~n", [_Msg]),
    {noreply, State}.

handle_info(Info, State) ->
    case catch do_handle_info(Info, State) of
        {noreply, NewState} ->
            {noreply, NewState};
        Err ->
            ?ERR("Handle info[~p] error:~w~n", [Info, Err]),
            {noreply, State}
    end.

%% 阶段转换
do_handle_info({stage_change, Stage}, State) ->
    #kf_1vn_info{ac_id=AcId, all_time = AllTime, ref = Ref} = State,
    #kf_1vn_time{sign_start=_SignStart, race_1_pre_start=Race1PreStart, race_1_start=Race1Start, race_1_end=Race1End,
        race_2_pre_start=_Race2PreStart, race_2_start=Race2Start, race_2_end=Race2End
    } = AllTime,
    util:cancel_timer(Ref),
    Now = utime:unixtime(),
    Next = case Stage of
        ?KF_1VN_SIGN        ->
            mod_kf_1vn_auction:stage_change(2, Race2End + ?KF_1VN_SEND_OUT_TIME), %% 报名阶段就通知打开竞拍和商城图标
            {?KF_1VN_RACE_1_PRE, Race1PreStart-Now};
        ?KF_1VN_RACE_1_PRE  -> {?KF_1VN_RACE_1, Race1Start-Now};
        ?KF_1VN_RACE_1      -> {?KF_1VN_RACE_2_PRE, Race1End-Now};
        ?KF_1VN_RACE_2_PRE  -> {?KF_1VN_RACE_2, Race2Start-Now};
        ?KF_1VN_RACE_2      -> {?KF_1VN_FREE, Race2End-Now};
        %% ?KF_1VN_FREE 不处理，由mod_kf_1vn比赛结束后通知
        _ -> false
    end,
    case Next of
        {NextStage, TimeSec} ->
            if
                TimeSec >= 0 ->
                    mod_kf_1vn:stage_change(Stage, Now, Now+TimeSec, AcId),
                    Ref1 = erlang:send_after(max(TimeSec*1000, 50), self(), {stage_change, NextStage}),
                    {noreply, State#kf_1vn_info{stage=Stage, ref=Ref1}};
                true -> %% 配置有误，关闭活动
                    erlang:send_after(50, self(), {stage_change, ?KF_1VN_FREE}),
                    % ?ERR("---------- kf_1vn TimeCfg Mistake -----------~nData:~p~n", [{stage_change, NextStage, TimeSec}]),
                    {noreply, State}
            end;
        _ ->
            {noreply, State}
    end;

do_handle_info(_Info, State) ->
    ?ERR("Handle unkown info[~p]~n", [_Info]),
    {noreply, State}.

terminate(_Reason, _State) ->
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.
%% 检测是否开启，这里用的是跨服1vn中的配置，不是走的活动日历开启
check_is_open([Id|T], Week, DateTime, Now) ->
    case data_kf_1vn:get_info(Id) of
        #kf_1vn_time_cfg{open_week=OpenWeekL, signtime={Hour, Min}, optime={OpHour, OpMin}} = AcR ->
            case lists:member(Week, OpenWeekL) of
                true ->
                    SignBegin = DateTime+Hour*3600+Min*60,
                    OpTime = DateTime+OpHour*3600+OpMin*60,
                    if
                        Now >= SignBegin andalso Now < OpTime -> {true, AcR}; %% @return
                        true -> check_is_open(T, Week, DateTime, Now)
                    end;
                false -> check_is_open(T, Week, DateTime, Now)
            end;
        _ -> check_is_open(T, Week, DateTime, Now)
    end;
check_is_open(_, _, _, _) -> false.

%% 初始化state，在这边协商各个阶段的时间
init_state(AcR, DateTime, State) ->
    #kf_1vn_time_cfg{id=AcId, signtime = {SHour, SMin}, optime = {OHour, OMin},
        race_1_pre = Race1PreTime, race_1 = Race1Time,
        race_2_pre = Race2PreTime, race_2 = Race2Time} = AcR,
    SignStart = DateTime+SHour*3600+SMin*60,
    OpTime = DateTime+OHour*3600+OMin*60,
    AllTime = #kf_1vn_time{
        sign_start=SignStart,
        race_1_pre_start=OpTime,
        race_1_start=OpTime+Race1PreTime,
        race_1_end=OpTime+Race1PreTime+Race1Time,
        race_2_pre_start=OpTime+Race1PreTime+Race1Time,
        race_2_start=OpTime+Race1PreTime+Race1Time+Race2PreTime,
        race_2_end=OpTime+Race1PreTime+Race1Time+Race2PreTime+Race2Time
    },
    State#kf_1vn_info{ac_id=AcId, all_time=AllTime}.
