%%%------------------------------------
%%% @Module  : lib_common_rank
%%% @Author  :  xiaoxiang
%%% @Created :  2016-11-17
%%% @Description: 通用榜单
%%%------------------------------------

-module(lib_rush_rank).

-include("server.hrl").
-include("rush_rank.hrl").
-include("figure.hrl").
-include("title.hrl").
-include("common.hrl").
-include("custom_act.hrl").
-include("def_fun.hrl").
-include("errcode.hrl").
-include("goods.hrl").
-include("warsoul.hrl").
-include("role_foster.hrl").
-include("equipment.hrl").
-compile(export_all).

%% 冲榜增加榜单类型
%% 1 头文件加上榜单类型宏定义，包括RANK_TYPE_LIST内的定义
%% 2 get_sel_value函数加上获取对应数据的方法
%% 3 当目标奖励或阈值配置有修改时到value_transform方法进行转换
%% 4 好像没了

%% record基础数据
make_record([{RankType, SubType}, Player]) ->
    #player_status{id = RoleId} = Player,
    {Value,Value2,Value3,Value4,Value5} = get_sel_value(Player, RankType),
    #rush_rank_role{
        role_key  = {RankType, SubType, RoleId},
        rank_type = RankType,
        sub_type  = SubType,
        role_id   = RoleId,
        value     = Value,
        value2    = Value2,
        value3    = Value3,
        value4    = Value4,
        value5    = Value5,
        time      = utime:unixtime()
    }.

%% 榜单
refresh_rush_rank({RankType, SubType}, Player) ->
    RushRank = make_record([{RankType, SubType}, Player]),
    mod_rush_rank:refresh_rush_rank(RankType, SubType, RushRank),
    ok.

%% 根据榜单类型解析对应排序值 （获取自己的）
get_sel_value(Player, RankType) ->
    #player_status{
        id = RoleId,
        combat_power = Combat,
        role_war_soul = RoleWarSoul,
        equipment = Equipment,
        role_base_attr = {AttrPower, BaseAttr}
    } = Player,
    case RankType of
        ?RANK_TYPE_RUSH_COMBAT ->
            {Combat,0,0,0,0};
        ?RANK_TYPE_RUSH_WARSOUL ->
            #role_war_soul{total_power = TotalPower} = RoleWarSoul,
            {_, _, SumStar} = warsoul_logic:calc_war_soul_on(RoleId),
            {TotalPower,SumStar,0,0,0};
        ?RANK_TYPE_RUSH_RED_EQUIP ->
            #equipment{empower_attr = EmpowerAttr0} = Equipment,
            EmpowerAttr = attr_conv:to_attr_record(EmpowerAttr0),
            EmpowerPower = lib_player_attr:calc_attr_power_partial(AttrPower, BaseAttr, EmpowerAttr),
            {EmpowerPower,0,0,0,0};
        _ ->
            get_foster_rush_data(RankType,Player)
    end.

is_exist(_I, []) -> false;
is_exist(I, [H | T]) ->
    case I == H of
        true ->
            true;
        false ->
            is_exist(I, T)
    end.

%% 获取配置榜单最大长度
get_max_len(RankType) ->
    case data_rush_rank:get_rush_rank_cfg(RankType) of
        #base_rush_rank{max_len = MaxLen} -> MaxLen;
        _ -> 0
    end.

%% 获取配置上榜阈值
get_rank_limit(RankType) ->
    case data_rush_rank:get_rank_reward_ids(RankType) of
        [] -> 0;
        RankList ->
            LastRewardId = lists:max(RankList), %% 最后一档奖励的限制条件就是上榜阈值
            get_rank_reward_limit(RankType, LastRewardId)
    end.

%% 根据排名获取上榜阈值
get_rank_limit_by_rank(RankType, Rank) ->
    case data_rush_rank:get_reward_id_by_rank(RankType, Rank) of
        0 -> 0;
        RewardId -> get_rank_reward_limit(RankType, RewardId)
    end.

%% 获取奖励阈值
get_rank_reward_limit(RankType, RewardId) ->
    case data_rush_rank:get_rank_reward_cfg(RankType, RewardId) of
        #base_rush_rank_reward{rank_limit = Limit} ->
            case Limit of
                [{_, Value}] ->
                    Value;
                ERR ->
                    ?ERR("rush rank limit config error: ~p~n", [ERR]),
                    0
            end;
        _ -> 0
    end.

%% 根据开服天数获取要结算榜单id
get_id_by_clear_day() ->
    OpenDay = util:get_open_day(),
    IdList = data_rush_rank:get_id_list(),
    do_get_id_by_clear_day(OpenDay, IdList,[]).

do_get_id_by_clear_day(_OpenDay, [],CList) ->
    CList;
do_get_id_by_clear_day(OpenDay, [H | T],CList) ->
    case data_rush_rank:get_rush_rank_cfg(H) of
        #base_rush_rank{clear_day = CfgDay} ->
            case OpenDay =:= CfgDay of
                true ->
                    do_get_id_by_clear_day(OpenDay,T,[H|CList]);
                _ ->
                    do_get_id_by_clear_day(OpenDay, T,CList)
            end;
        _ ->
            do_get_id_by_clear_day(OpenDay, T,CList)
    end.

get_refresh_limit(RankType) ->
    case data_rush_rank:get_rush_rank_cfg(RankType) of
        #base_rush_rank{clear_day = ClDay} ->
            util:get_open_day() < ClDay;
        _ ->
            % ?ERR("rush rank config err:~p~n", [RankType]),
            false
    end.

%% 获取配置奖励
get_rank_reward(RankType, Rank, _Career) ->
    IdList = data_rush_rank:get_rank_reward_ids(RankType),
    do_get_rank_reward(RankType, Rank, IdList, []).

do_get_rank_reward(_RankType, _Rank, [], TmpL) -> TmpL;
do_get_rank_reward(RankType, Rank, [H | T], TmpL) ->
    case data_rush_rank:get_rank_reward_cfg(RankType, H) of
        #base_rush_rank_reward{rank_min = Min, rank_max = Max, reward = Reward} -> ok;
        _ -> Max = Min = 0, Reward = []
    end,
    case Max >= Rank andalso Rank >= Min of
        true ->
            do_get_rank_reward(RankType, Rank, T, Reward ++ TmpL);
        _ ->
            do_get_rank_reward(RankType, Rank, T, TmpL)
    end.

%% 获取配置的目标奖励
get_cfg_goal_reward(RankType, GoalId) ->
    case data_rush_rank:get_goal_reward_cfg(RankType, GoalId) of
        #base_rush_goal_reward{reward = Reward} -> ok;
        _ -> Reward = []
    end,
    Reward.

get_new_reward_state(RankType, RushRankRole, GoalId) ->
    #rush_rank_role{
        value     = Value,
        value4    = Value4,
        value5    = Value5
    } = RushRankRole,
    case data_rush_rank:get_goal_reward_cfg(RankType, GoalId) of
        #base_rush_goal_reward{goal_value = GoalCfg} ->
            case GoalCfg of
                [{_, CfgValue}] ->
                    if
                        Value >= CfgValue andalso CfgValue =/= 0 ->
                            ?HAVE_REWARD;
                        true ->
                            ?NOT_REWARD
                    end;
                [{foster,_,CfgGrade,CfgStar}]->
                    if
                        Value4>CfgGrade->
                            ?HAVE_REWARD;
                        Value4 == CfgGrade andalso Value5>=CfgStar->
                            ?HAVE_REWARD;
                        true->
                            ?NOT_REWARD
                    end;
                _ ->
                    ?NOT_REWARD
            end;
        _ ->
            ?NOT_REWARD
    end.



get_open_lv(ActType, SubType) ->
    case lib_custom_act_util:get_act_cfg_info(ActType, SubType) of
        #custom_act_cfg{condition = Condition} when is_list(Condition) ->
            case lists:keyfind(role_lv, 1, Condition) of
                {_, Lv} when is_integer(Lv) -> Lv;
                _ -> 99999
            end;
        _ -> 99999
    end.

%% 获取结算时间
get_rank_end_time(RankType) ->
    case data_rush_rank:get_rush_rank_cfg(RankType) of
        #base_rush_rank{clear_day = ClDay} ->
            OpenTime = util:get_open_time(), %% 开服时间戳
            OpenDate = utime:unixdate(OpenTime), %% 开服当天0点
            ClTime = OpenDate + (ClDay - 1) * ?ONE_DAY_SECONDS; %% 结束当天0点
        _ ->
            ClTime = 0
    end,
    ClTime.

%% 发送配置
send_cfg(Sid) ->
    {RankTypeCfgList, RushRankRewardCfgList, RushRankGoalRewardCfgList} = get_cfg(),
    lib_server_send:send_to_sid(Sid, pt_225, 22510, [RankTypeCfgList, RushRankRewardCfgList, RushRankGoalRewardCfgList]).
send_cfg_to_all() ->
    {RankTypeCfgList, RushRankRewardCfgList, RushRankGoalRewardCfgList} = get_cfg(),
    {ok, Bin} = pt_225:write(22510, [RankTypeCfgList, RushRankRewardCfgList, RushRankGoalRewardCfgList]),
    lib_server_send:send_to_all(Bin).
%% 获取配置
get_cfg() ->
    RushRankCfgIds = data_rush_rank:get_id_list(),
    F1 = fun(RushRankCfgId, {RushRankCfgList, RushRankRewardCfgList, RushRankGoalRewardCfgList}) ->
        %% 冲榜活动配置表
        #base_rush_rank{name = Name,start_day = StartDay,clear_day = ClearDay,limit = Limit,figure_id = FigureId}
            = data_rush_rank:get_rush_rank_cfg(RushRankCfgId),
        NewRankTypeCfgList = [{RushRankCfgId, Name, StartDay, ClearDay, util:term_to_string(Limit), util:term_to_string(FigureId)} | RushRankCfgList],

        %% 冲榜排行奖励配置表
        RankRewardIds = data_rush_rank:get_rank_reward_ids(RushRankCfgId),
        F2 = fun(RewardId, TmpRushRankRewardCfgList) ->
            #base_rush_rank_reward{rank_min = RankMin, rank_max = RankMax, rank_limit = RankLimit, reward = Reward, about = About}
                 = data_rush_rank:get_rank_reward_cfg(RushRankCfgId, RewardId),
            [{RushRankCfgId, RewardId, RankMin, RankMax, util:term_to_string(RankLimit), util:term_to_string(Reward), About} | TmpRushRankRewardCfgList]
        end,
        NewRushRankRewardCfgList = lists:foldl(F2, RushRankRewardCfgList, RankRewardIds),

        %% 冲榜目标奖励配置表
        GoalRewardIds = data_rush_rank:get_goal_reward_ids(RushRankCfgId),
        F3 = fun(RewardId, TmpRushRankGoalRewardCfgList) ->
            #base_rush_goal_reward{goal_value = GoalValue, reward = Reward, about = About}
                 = data_rush_rank:get_goal_reward_cfg(RushRankCfgId, RewardId),
            [{RushRankCfgId, RewardId, util:term_to_string(GoalValue), util:term_to_string(Reward), About} | TmpRushRankGoalRewardCfgList]
        end,
        NewRushRankGoalRewardCfgList = lists:foldl(F3, RushRankGoalRewardCfgList, GoalRewardIds),

        {NewRankTypeCfgList, NewRushRankRewardCfgList, NewRushRankGoalRewardCfgList}
    end,
    lists:foldl(F1, {[], [], []}, RushRankCfgIds).

%% 配置检测
check([]) -> true;
check([Check|CheckList]) ->
    case do_check(Check) of
        true -> check(CheckList);
        {false, Error} -> {false, Error}
    end.
do_check({is_opened, RankType}) ->
    OpDay = util:get_open_day(),
    case data_custom_act:get_act_info(?CUSTOM_ACT_TYPE_RUSH_RANK,1) of
        #custom_act_cfg{opday_lim=[{Min,Max}]} when Min=<OpDay andalso OpDay=<Max ->
            case data_rush_rank:get_rush_rank_cfg(RankType) of
                #base_rush_rank{start_day = StDay} ->
                    case OpDay >= StDay of
                        true ->
                            true;
                        _ ->
                            {false, ?FAIL}
                    end;
                _ ->
                    {false, ?MISSING_CONFIG}
            end;
        _->
            {false, ?FAIL}
    end;
do_check({rush_rank_cfg, RankType}) ->
    case data_rush_rank:get_rush_rank_cfg(RankType) of
        #base_rush_rank{} -> true;
        _ -> {false, ?MISSING_CONFIG}
    end;
do_check({goal_reward_cfg, RankType, GoalId}) ->
    case data_rush_rank:get_goal_reward_cfg(RankType, GoalId) of
        #base_rush_goal_reward{} -> true;
        _ -> {false, ?MISSING_CONFIG}
    end;
do_check(_) -> {false, ?FAIL}.


%%获取榜单需要的数据
get_foster_rush_data(RankType,Player)->
    #player_status{
        role_foster = RoleFoster,
        role_foster_skin = RoleSkin
    } = Player,
    CellType = case lists:member(RankType,?RANK_TYPE_FOSTER_GRADE_LIST) of
        true->
            RankType-?OFFSET_TYPE;
        _->
            RankType
    end,
    #role_foster{fosters=CellFosters}=RoleFoster,
    #role_foster_skin{fosters=CellSkins}=RoleSkin,
    case lists:keyfind(CellType,#cell_foster.type,CellFosters) of
        #cell_foster{combat=BaseCombat,grade=Grade,star=Star}->
            skip;
        _->
            BaseCombat = 0,Grade=0,Star=0
    end,
    case lists:keyfind(CellType,#cell_foster_skin.type,CellSkins) of
        #cell_foster_skin{combat=SkinCombat}->
            skip;
        _->
            SkinCombat = 0
    end,
    case lists:member(RankType,?RANK_TYPE_FOSTER_GRADE_LIST) of
        true->
            {Grade,Star,BaseCombat+SkinCombat,Grade,Star};
        _->
            {BaseCombat+SkinCombat,Grade,Star,BaseCombat,SkinCombat}
    end.