%% ---------------------------------------------------------------------------
%% @doc 定制活动-作战活动。
%% @author zmh
%% @since  20201207
%% ---------------------------------------------------------------------------
-module(custom_act_days_plan).


-export([
    act_days_plan_data/3,              %% 获取数据
    send_days_plan_info/1              %% 发送作战活动信息
    ,send_days_plan_info/2             %% 发送作战活动信息
    ,update_days_plan_task/3           %% 更新作战进度
    ,update_days_plan_task/4           %% 更新作战进度
    ,days_plan_task_award/5            %% 作战任务完成奖励
    ,days_plan_task_buy/3              %% 作战物资购买
    ,handle_event/2
    ,finish_dungeon/2
]).


-include("custom_act.hrl").
-include("common.hrl").
-include("server.hrl").
-include("errcode.hrl").
-include("def_goods.hrl").
-include("goods.hrl").
-include("figure.hrl").
-include("predefine.hrl").
-include("def_event.hrl").
-include("rec_event.hrl").
-include("dungeon.hrl").


%% @doc 角色作战数据
act_days_plan_data(_Status, Type, SubType) ->
    #custom_act_data{
        act_data = ActData
    } = lib_custom_act_data:custom_act_data(Type, SubType),
    case ActData of
            #act_days_plan{} ->
                ActData;
        _ ->
            #act_days_plan{}
    end.

%% @doc 发送作战活动信息
send_days_plan_info(Status)->
    Type = ?CUSTOM_ACT_TYPE_DAYS_PLAN,
    case lib_custom_act_util:get_open_subtype_list(Type) of
        [_|_] = ActInfos ->
            [send_days_plan_info(Status, ActInfo) || ActInfo <- ActInfos];
        _ ->
            ok
    end,
    ok.
%% @doc 发送作战活动信息
send_days_plan_info(Status,SubType) when is_integer(SubType)->
    Type = ?CUSTOM_ACT_TYPE_DAYS_PLAN,
    ActInfo = lib_custom_act_util:get_custom_act_open_info(Type, SubType),
    send_days_plan_info_do(Status, ActInfo),
    ok;
send_days_plan_info(Status, ActInfo) ->
    send_days_plan_info_do(Status, ActInfo).

send_days_plan_info_do(Status, ActInfo = #act_info{}) ->
    #player_status{sid=Sid}=Status,
    #act_info{key = {_, SubType}} = ActInfo,
    Now = utime:unixtime(),
    DayInfoList = case ActInfo of
        #act_info{etime = ETime} when ETime > Now ->
            days_plan_info(Status, ActInfo, Now);
        _ ->
            []
    end,
    {ok, Bin} = pt_332:write(33275, [SubType, DayInfoList]),
    lib_server_send:send_to_sid(Sid, Bin),
    ok;
send_days_plan_info_do(_Status, _ActInfo) ->
    ok.

%% 作战活动信息
days_plan_info(Status, ActInfo, Now) ->
    #act_info{key = {Type, SubType}, stime = StartTime} = ActInfo,
    NowDay  = utime:day_span(StartTime, Now),
    Suit    = get_condition_value(Type, SubType,suit),
    DayList = data_act_days_plan:get_day_list(Suit),
    ActData = act_days_plan_data(Status, Type, SubType),
    DayInfoList = day_info_list(DayList, ActData, ActInfo,Suit,NowDay, Status, []),
    DayInfoList.

%% 作战每天信息
day_info_list([], _ActData, _ActInfo,_Suit, _NowDay, _Status, DayInfoList) ->
    DayInfoList;
day_info_list([Day | T], ActData, ActInfo,Suit, NowDay, Status, DayInfoList) ->
    TypeIdList = data_act_days_plan:get_task_type_id_list(Suit, Day),
    #act_days_plan{day_list = DayDataList, task_stat = TaskStat} = ActData,
    TaskDayData = case lists:keyfind(Day, #days_buy.day, DayDataList) of
        TDayData = #days_buy{} ->
            TDayData;
        _ ->
            #days_buy{day = Day}
    end,
    #days_buy{day = Day, buy_times = BuyTimes} = TaskDayData,
    DayTaskList = day_task_list(TypeIdList, TaskDayData, TaskStat, ActInfo, NowDay, Status, []),
    DayInfo = {Day, BuyTimes, DayTaskList},
    DayInfoList2 = [DayInfo | DayInfoList],
    day_info_list(T, ActData, ActInfo,Suit, NowDay, Status, DayInfoList2).

%% 每天的任务展示内容
day_task_list([], _TaskDayData, _TaskStat, _ActInfo, _NowDay, _Role, DayTaskList) ->
    DayTaskList;
day_task_list([TaskTypeId | T], TaskDayData, TaskStat, ActInfo, NowDay, Role, DayTaskList) ->
    TaskIdList = data_act_days_plan:get_task_id_list(TaskTypeId),
    DayTaskList2 = type_task_list(TaskIdList, TaskTypeId, TaskDayData, TaskStat, ActInfo, NowDay, Role, DayTaskList),
    day_task_list(T, TaskDayData, TaskStat, ActInfo, NowDay, Role, DayTaskList2).

%% 每种类型的任务只显示一个任务
type_task_list([], _TaskType, _TaskDayData, _TaskStat, _ActInfo, _NowDay, _Role, TypeTaskList) ->
    TypeTaskList;
type_task_list([TaskId | T], TaskType, TaskDayData, TaskStat, ActInfo, NowDay, Role, TypeTaskList) ->
    #days_buy{day = Day} = TaskDayData,
    case data_act_days_plan:get_task_cfg(TaskType, TaskId) of
        TaskCfg = #custom_act_days_plan_task{} ->
            {Status, Progress} = task_award_status(ActInfo, TaskDayData, TaskStat, TaskCfg, Role),
            Status2 = case NowDay >= Day of
                true -> Status;
                _ -> ?ACT_REWARD_CAN_NOT_GET
            end,
            TaskInfo = {TaskType, TaskId, Progress, Status2},
            %% 每种类型的任务只显示一个任务
            case Status2 of
                ?ACT_REWARD_CAN_GET -> %% 可以领取，展示这个任务
                    [TaskInfo | TypeTaskList];
                ?ACT_REWARD_CAN_NOT_GET -> %% 还没完成，展示这个任务
                    [TaskInfo | TypeTaskList];
                _ -> %% 任务奖励已经领取
                    case T of
                        [] -> %% 这个类型的任务，最后一个也完成了
                            [TaskInfo | TypeTaskList];
                        _ -> %% 还有下一个任务
                            type_task_list(T, TaskType, TaskDayData, TaskStat, ActInfo,NowDay, Role, TypeTaskList)
                    end
            end;
        _ ->
            type_task_list(T, TaskType, TaskDayData, TaskStat, ActInfo, NowDay, Role, TypeTaskList)
    end.


%% @doc 作战任务奖励状态
task_award_status(ActInfo, TaskDayData, TaskStat, TaskCfg, Role) ->
    #custom_act_days_plan_task{
        task_type = TaskType,
        task_id = TaskId,
        open_lv = NeedLev
        ,content = NeedValue
    } = TaskCfg,
    #days_buy{logs = TaskAwardLog} = TaskDayData,
    IsMember = lists:member({TaskType, TaskId}, TaskAwardLog),
    #act_info{stime = STime, etime = ETime} = ActInfo,
    #player_status{id=RoleId,figure = #figure{lv = RoleLev}} = Role,
    Progress = case TaskType of
        1->
            lib_recharge_data:get_my_recharge_between(RoleId, STime, ETime);
        _->
            case lists:keyfind(TaskType, #days_task.task_type, TaskStat) of
                #days_task{value = Num} ->
                    Num;
                _ ->
                    0
            end
    end,
    %io:format("--------:~p~n",[{{TaskType, TaskId},IsMember,TaskAwardLog}]),
    if
        NeedLev > RoleLev ->
            {?ACT_REWARD_CAN_NOT_GET, Progress};
        IsMember ->
            {?ACT_REWARD_HAS_GET, Progress};
        Progress >= NeedValue ->
            {?ACT_REWARD_CAN_GET, Progress};
        true ->
            {?ACT_REWARD_CAN_NOT_GET, Progress}
    end.


%%获取指定kV
get_condition_value(Type, SubType,Key)->
    get_condition_value(Type, SubType,Key,0).
get_condition_value(Type, SubType,Key,DValue)->
    case data_custom_act:get_act_info(Type,SubType) of
        #custom_act_cfg{condition=Cons}->
            case lists:keyfind(Key,1,Cons) of
                {_,Value}->
                    skip;
                _->
                    Value = DValue
            end;
        _->
            Value = DValue
    end,
    Value.


% @doc 作战任务完成奖励
days_plan_task_award(Role, SubType, Day, TaskType, TaskId) ->
    Type = ?CUSTOM_ACT_TYPE_DAYS_PLAN,
    Now = utime:unixtime(),
    {
        IsOpen, NowDay, ActInfo
    } = case lib_custom_act_util:get_custom_act_open_info(Type, SubType) of
        ActInfo0 = #act_info{stime = StartTime, etime = ETime} when ETime > Now ->
            {true, utime:day_span(StartTime, Now), ActInfo0};
        _ ->
            {false, 0, #act_info{}}
    end,
    TaskCfg = data_act_days_plan:get_task_cfg(TaskType, TaskId),
    {AwardList, NeedLev} = case TaskCfg of
        #custom_act_days_plan_task{reward = Award, open_lv = NLev} ->
            {Award, NLev};
        _ ->
            {[], false}
    end,
    IsBagFull = lib_goods_api:can_give_goods(Role, AwardList),
    Suit     = get_condition_value(Type, SubType,suit),
    TypeList = data_act_days_plan:get_task_type_id_list(Suit, Day),
    TaskIdList = data_act_days_plan:get_task_id_list(TaskType),
    IsDayAward = lists:member(TaskType, TypeList)
    andalso lists:member(TaskId, TaskIdList),
    #player_status{figure = #figure{lv = Lev}, id = RoleId} = Role,
    if
        IsOpen =:= false ->
            {false, ?ERRCODE(err331_act_closed)};
        AwardList =:= [] ->
            {false, ?ERRCODE(err331_no_act_reward_cfg)};
        not IsDayAward ->
            {false, ?ERRCODE(err280_error_args)};
        Day > NowDay ->
            {false, ?ERRCODE(err331_act_can_not_get)};
        NeedLev > Lev ->
            {false, ?ERRCODE(err331_lv_unreach)};
        not IsBagFull ->
            {false, ?ERRCODE(err150_no_cell)};
        true ->
            DaysPlanData = #act_days_plan{
                day_list = DayDataList, task_stat = TaskStat
            } = act_days_plan_data(Role, Type, SubType),
            {
                TaskDayData, RestDayDataList
            } = case lists:keytake(Day, #days_buy.day, DayDataList) of
                {value, TDayData = #days_buy{}, RestList} ->
                    {TDayData, RestList};
                _ ->
                    {#days_buy{day = Day}, DayDataList}
            end,
            {
                Status, _Progress
            } = task_award_status(ActInfo, TaskDayData, TaskStat, TaskCfg, Role),
            if
                Status =:= ?ACT_REWARD_HAS_GET ->
                    {false, ?ERRCODE(err331_already_get_reward)};
                Status =:= ?ACT_REWARD_CAN_NOT_GET ->
                    {false, ?ERRCODE(err331_act_can_not_get)};
                true ->
                    #days_buy{logs = AwardLog} = TaskDayData,
                    AwardLog2 = [{TaskType, TaskId} | AwardLog],
                    TaskDayData2 = TaskDayData#days_buy{logs = AwardLog2},
                    DayDataList2 = [TaskDayData2 | RestDayDataList],
                    DaysPlanData2 = DaysPlanData#act_days_plan{day_list = DayDataList2},
                    ActData = #custom_act_data{type = Type, subtype = SubType, act_data = DaysPlanData2},
                    %% 保存数据
                    lib_custom_act_data:save_custom_data(RoleId, ActData),

                    %% 发奖励
                    Produce = #produce{
                        type = days_plan_task_award, subtype = SubType, reward = AwardList
                        ,remark = io_lib:format("~w,~w", [TaskType, TaskId])
                    },
                    Role2 = lib_goods_api:send_reward(Role, Produce),
                    lib_log_api:custom_act_reward_log(Role2, Role, Type, SubType, 0, io_lib:format("day:~w,TaskType:~w,TaskId:~w", [Day,TaskType, TaskId]), AwardList),
                    {ok, Role2}
            end
    end.

%% @doc 作战物资购买
days_plan_task_buy(Role, SubType, Day) ->
    Type = ?CUSTOM_ACT_TYPE_DAYS_PLAN,
    Now = utime:unixtime(),
    {
        IsOpen, NowDay
    } = case lib_custom_act_util:get_custom_act_open_info(Type, SubType) of
        #act_info{stime = StartTime, etime = ETime} when ETime > Now ->
            {true, utime:day_span(StartTime, Now)};
        _ ->
            {false, 0}
    end,
    AwardCfg = lib_custom_act_util:get_act_reward_cfg_info(Type, SubType, Day),
    AwardList = case AwardCfg of
        #custom_act_reward_cfg{reward = Award} -> Award;
        _ -> []
    end,
    IsBagFull = lib_goods_api:can_give_goods(Role, AwardList),
    if
        IsOpen =:= false ->
            {false, ?ERRCODE(err331_act_closed)};
        AwardList =:= [] ->
            {false, ?ERRCODE(err331_no_act_reward_cfg)};
        Day > NowDay ->
            {false, ?ERRCODE(err331_act_can_not_get)};
        not IsBagFull ->
            {false, ?ERRCODE(err150_no_cell)};
        true ->
            #custom_act_reward_cfg{condition = Condition} = AwardCfg,
            Cost = case lists:keyfind(limit_cost, 1, Condition) of
                {limit_cost, LCost} when is_integer(LCost) andalso LCost > 0 -> LCost;
                _ -> 9999999
            end,
            MaxTimes = case lists:keyfind(limit_times, 1, Condition) of
                {limit_times, LTimes} when is_integer(LTimes) -> LTimes;
                _ -> 0
            end,
            DaysPlanData = #act_days_plan{
                day_list = DayDataList
            } = act_days_plan_data(Role, Type, SubType),
            {
                TaskDayData, RestDayDataList
            } = case lists:keytake(Day, #days_buy.day, DayDataList) of
                {value, TDayData = #days_buy{}, RestList} ->
                    {TDayData, RestList};
                _ ->
                    {#days_buy{day = Day}, DayDataList}
            end,
            #days_buy{buy_times = BuyTimes} = TaskDayData,
            CostList = [{?TYPE_GOLD, 0, Cost}],
            BuyTimes2 = BuyTimes + 1,
            case check_day_task_buy(Role, SubType, Day, MaxTimes, BuyTimes2, CostList) of
                {false, Reason, _RoleTemp} ->
                    {false, Reason};
                {true, Role2} ->
                    TaskDayData2 = TaskDayData#days_buy{buy_times = BuyTimes2},
                    DayDataList2 = [TaskDayData2 | RestDayDataList],
                    DaysPlanData2 = DaysPlanData#act_days_plan{day_list = DayDataList2},
                    ActData = #custom_act_data{
                        type = Type, subtype = SubType, act_data = DaysPlanData2
                    },
                    #player_status{id = RoleId} = Role,
                    %% 保存数据
                    lib_custom_act_data:save_custom_data(RoleId, ActData),

                    %% 发奖励
                    Produce = #produce{
                        type = days_plan_task_buy, subtype = Day, reward = AwardList
                    },
                    Role3 = lib_goods_api:send_reward(Role2, Produce),
                    lib_log_api:custom_act_reward_log(Role2, Role, Type, SubType, 1, io_lib:format("Day:~w", [Day]), AwardList),
                    {ok, Role3, BuyTimes2, AwardList}
            end
    end.

%% 作战物资是否可以购买
check_day_task_buy(Role, SubType, Day, MaxTimes, BuyTimes, CostList) ->
    case BuyTimes > MaxTimes of
        true ->
            {false, ?ERRCODE(err331_cloud_buy_not_enough), Role};
        false ->
            About = lib_custom_act_api:custom_act_consume_about(SubType, Day),
            case lib_goods_api:cost_object_list_with_check(
                    Role, CostList, days_plan_task_buy, About) of
                {true, TmpNewPlayer,_} ->
                    {true, TmpNewPlayer};
                Other ->
                    Other
            end
    end.




%% @doc 更新作战进度
update_days_plan_task(RoleId, TaskType, Add) ->
    update_days_plan_task(RoleId, TaskType, Add, false).



%% @doc 更新作战进度 IsDayLimit  :: boolean(). %% 是否每日只统计一次
update_days_plan_task(RoleId, TaskType, Add, IsDayLimit) when is_integer(RoleId) ->
    Args = [TaskType, Add, IsDayLimit],
    lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, ?MODULE, update_days_plan_task, Args);
update_days_plan_task(Role, TaskType, Add, IsDayLimit) ->
    Type = ?CUSTOM_ACT_TYPE_DAYS_PLAN,
    case lib_custom_act_api:get_open_custom_act_infos(Type) of
        [_|_] = Acts ->
            [update_days_plan_task(Role, ActInfo, TaskType, Add, IsDayLimit)|| ActInfo = #act_info{} <- Acts];
        _ ->
            ok
    end,
    ok.

update_days_plan_task(Role, ActInfo, TaskType, Add, IsDayLimit) ->
    #act_info{key = {Type, SubType}} = ActInfo,
    Suit    = get_condition_value(Type, SubType,suit),
    TypeIdList = data_act_days_plan:get_task_type_list_by_suit(Suit),
    case lists:member(TaskType, TypeIdList) of
        false -> %% 此活动没有此类型的任务
            ok;
        true ->
            update_days_plan_task_do(Role, ActInfo, TaskType, Add, IsDayLimit)
    end.

update_days_plan_task_do(Role, ActInfo, TaskType, Add, IsDayLimit) ->
    #act_info{key = {Type, SubType}} = ActInfo,
    FiveDayData = #act_days_plan{
        task_stat = TaskStatList
    } = act_days_plan_data(Role, Type, SubType),
    Now = utime:unixtime(),
    KeyPos = #days_task.task_type,
    {TaskStatList2, IsUpdate} = case lists:keytake(TaskType, KeyPos, TaskStatList) of
        {
            value, Task = #days_task{value = Num, time = Time}, RestList
        } when IsDayLimit ->
            case utime:is_same_day(Time, Now) of
                true ->
                    {TaskStatList, false};
                _ ->
                    {[Task#days_task{value = Num + Add, time = Now} | RestList], true}
            end;
        {value, Task = #days_task{value = Num}, RestList} ->
            {[Task#days_task{value = Num + Add, time = Now} | RestList], true};
        _ ->
            Task = #days_task{task_type = TaskType, value = Add, time = Now},
            {[Task | TaskStatList], true}
    end,
    case IsUpdate of
        true ->
            FiveDayData2 = FiveDayData#act_days_plan{task_stat = TaskStatList2},
            ActData = #custom_act_data{
                type = Type, subtype = SubType, act_data = FiveDayData2
            },
            #player_status{id = RoleId} = Role,
            lib_custom_act_data:save_custom_data(RoleId, ActData),
            send_days_plan_info(Role, ActInfo);
        _ ->
            ok
    end,
    ok.



%%充值事件
handle_event(Status, #event_callback{type_id = ?EVENT_RECHARGE,data = #callback_recharge_data{gold = Gold}}) ->
    update_days_plan_task(Status, 1, Gold, false),
    {ok,Status};
handle_event(Status, Event = #event_callback{type_id = ?EVENT_ADD_LIVENESS}) ->
    #event_callback{data = #callback_activity_live{add_live = Add}} = Event,
    update_days_plan_task(Status, 3, Add, false),
    {ok,Status};
handle_event(Status,#event_callback{type_id = ?EVENT_ZERO_CLOCK}) ->
    send_days_plan_info(Status),
    {ok,Status};
handle_event(Status, _) -> {ok, Status}.
finish_dungeon(RoleId,DunType)->
    case DunType of
        ?DUNGEON_TYPE_MATERIAL->
            update_days_plan_task(RoleId, 4, 1);
        _->
            skip
    end.
