%%%-------------------------------------------------------------------
%%% @author liushl
%%% @doc
%%%     式神接口
%%% @end
%%%-------------------------------------------------------------------
-module(god_api).
-author("liushl").
-include("server.hrl").
-include("god.hrl").
-include("common.hrl").
-include("goods.hrl").
-include("def_goods.hrl").
-include("def_fun.hrl").
-include("figure.hrl").
-include("def_module.hrl").
-include("predefine.hrl").
-include("attr.hrl").
-include("battle.hrl").
-include("scene.hrl").
-include("errcode.hrl").
-include("def_event.hrl").
-include("rec_event.hrl").
-include("skill.hrl").
%% API
-export([
    login/2,
    % login_god_info/1,               %% 
    calc_god_power/3,               %% 统计额外战力
    get_attr/2,                     %% 基础属性
    % use_goods/2,                    %% 使用式神类物品
    % active_by_card/3,               %% 使用式神激活卡
    handle_event/2
]).
-export([
    scene_summon_god/3,             %% 场景处理 由玩家开始召唤
    scene_summon_exist_god/2,       %% 场景处理 召唤已上阵的
    scene_summon_new_god/3,         %% 场景处理 召唤新的或已过时移除的
    % active_switch_god/1,          %% 场景处理 主动切换式神
    scene_god_expire/2,
    check_use_skill/2,              %% 玩家进程 出手检查技能
    scene_init_user/1,              %% 场景处理 出手初始化战斗信息
    is_un_control/1,                %% 战斗计算 抵抗所有控制
    check_sp_skill/3,               %% 战斗计算 特殊战斗效果
    scene_after_battle_attack/2,    %% 场景处理 攻击者复原战斗信息
    scene_after_battle_defend/4,    %% 场景处理 战斗后防守者复原战斗信息
    role_after_be_attack/3,         %% 玩家进程 被攻击后

    is_in_god_fighting/1,
    get_fighting_god_hp/2,
    get_fighting_role_hp/2,
    pack_scene_user/1,
    pack_role_user/1,
    enter_scene/1,                  %% 玩家加入场景
    init_god_summon_time/1
]).

-export([
    reset_god/1
    ,reset_god_cd/2
    ]).

%% 登陆加载数据
login(RoleId, GoodsStatus) ->
    GodList =
        case god_logic:db_get_all_god(RoleId) of
            [_|_] = List ->
                GodEquip = lib_goods_util:get_goods_list_by_type(RoleId, ?GOODS_LOC_GOD_EQUIP, ?GOODS_TYPE_GOD_EQUIP, GoodsStatus#goods_status.dict),
                [
                    begin
                        God = #god{
                            id = GodId, star = Star, lv = Lv, exp = Exp, pos = Pos, skills = util:to_term(Skills)
                        },
                        {EquipAttr, SuitInfo} = god_logic:get_god_equip_attr(GodId, GodEquip),

                        GodLast = god_logic:calc_one_god_attr(God#god{equip_attr = EquipAttr, suit_info = SuitInfo}),
                        GodLast
                    end
                    || [GodId, Star, Lv, Exp, Pos, Skills] <- List
                ];
            _ -> []
        end,
    SummonTimeList = init_god_summon_time(GodList),
    RoleGod = god_logic:calc_all_god_attr_1(#role_god{
        god_info = GodList,
        unlock = [],   %% 初始值
        summon_time = SummonTimeList
    }),
    case god_logic:db_get_role_god(RoleId) of
        [Unlock|_] ->
            RoleGod#role_god{unlock = util:to_term(Unlock)};
        _ ->
            RoleGod
    end.

init_god_summon_time([]) -> [];
init_god_summon_time(GodList = [#god{}|_]) -> 
    Time = utime:unixtime(),
    [{Pos, Time} || #god{pos = Pos} <- GodList, Pos =/= 0];
init_god_summon_time(GodList = [_|_]) ->
    Time = utime:unixtime(),
    [{Pos, Time} || {_GodId, _, _, _, Pos, _} <- GodList, Pos =/= 0];
init_god_summon_time(_) -> [].

%%%===================================================================
%% 统计额外战力 ??式神虚战力??
calc_god_power(Player, AttrPower, BaseAttr) ->
    NewPlayer = god_logic:calc_all_god_attr_2(Player, AttrPower, BaseAttr),
    RoleGod = NewPlayer#player_status.role_god,
    case RoleGod of
        #role_god{god_power = GodPower} ->
            {NewPlayer, round(GodPower)};
        _ ->
            {NewPlayer, 0}
    end.

%% 基础属性
get_attr(Player, Args) ->
    #player_status{role_god = RoleGod} = Player,
    case RoleGod of
        #role_god{attr = Attr, temp_attr = TempAttr} -> 
            case Args of
                [god_summon|_] ->
                    TempAttr ++ Attr;
                _ ->
                    Attr
            end;
        _ -> 
            []
    end.
%%%===================================================================
%%% @doc 式神：战斗流程处理
%%%===================================================================
%% 场景进程处理 由玩家开始召唤
scene_summon_god(RoleId, GodId, GodFighting) ->
    case lib_scene_agent:get_user(RoleId) of
        #ets_scene_user{} = User ->
            NewGodFighting = scene_switch_god(User, GodId, GodFighting),
            lib_scene_agent:put_user(User#ets_scene_user{god_fighting = NewGodFighting});
        _ ->
            ok
    end.

%% 召唤已上阵的
scene_summon_exist_god(RoleId, GodId) ->
    case lib_scene_agent:get_user(RoleId) of
        #ets_scene_user{god_fighting = GodFighting} = User ->
            %% 过滤已召唤的
            GodFighting1 = [FightingGod || FightingGod <- GodFighting, FightingGod#god_fighting.time == 0],
            NewGodFighting = scene_switch_god(User, GodId, GodFighting1),
            lib_scene_agent:put_user(User#ets_scene_user{god_fighting = NewGodFighting});
        _A -> ok
    end.

%% 召唤新的或已过时移除的式神
scene_summon_new_god(RoleId, FightingGod, GodPos) ->
    case lib_scene_agent:get_user(RoleId) of
        #ets_scene_user{god_fighting = GodFightings} = User ->
            %% 过滤已召唤的
            GodFightings1 = [FightingGodX || FightingGodX <- GodFightings, FightingGodX#god_fighting.time == 0],
            SortGodFightings = add_new_fighting_god(FightingGod, GodFightings1, GodPos),
            NewGodFightings  = scene_switch_god(User, FightingGod#god_fighting.id, SortGodFightings),
            lib_scene_agent:put_user(User#ets_scene_user{god_fighting = NewGodFightings});
        _ -> ok
    end.

add_new_fighting_god(FightingGod, GodFightings, GodPos) ->
    #god_fighting{id = GodId} = FightingGod,
    lists:foldr(
     fun
        ({_Pos, GodIdX}, AccFighters) when GodIdX == GodId -> 
            [FightingGod | AccFighters];
        ({_Pos, GodIdX1}, AccFighters) ->
            case lists:keyfind(GodIdX1, #god_fighting.id, GodFightings) of
                FightingGod1 = #god_fighting{} ->
                    [FightingGod1 | AccFighters];
                _ -> AccFighters
            end
     end, [], GodPos).

%% 场景进程处理 玩家主动切换式神/超时自动切换式神
% active_switch_god(RoleId) ->
%     case lib_scene_agent:get_user(RoleId) of
%         #ets_scene_user{god_fighting = GodFighting} = User ->
%             case GodFighting of
%                 [_, NextGod|T] ->
%                     #god_fighting{id = NextGodId} = NextGod,
%                     NewGodFighting = scene_switch_god(User, NextGodId, [NextGod|T]),
%                     lib_scene_agent:put_user(User#ets_scene_user{god_fighting = NewGodFighting});
%                 _ ->
%                     ok
%             end;
%         _ ->
%             ok
%     end.

%% 场景进程处理 玩家手动召唤的式神超时
scene_god_expire(RoleId, GodId) ->
    case lib_scene_agent:get_user(RoleId) of
        #ets_scene_user{god_fighting = GodFighting} = User ->
            %% 移除场景玩家的超时的上阵式神数据
            NewGodFighting = lists:keydelete(GodId, #god_fighting.id, GodFighting),
            %% 广播变身结束
            send_to_scene(User, #god_fighting{}),
            lib_scene_agent:put_user(User#ets_scene_user{god_fighting = NewGodFighting});
        _ -> ok
    end.
 
%% 出手检查技能
check_use_skill(Player, SkillId) ->
    #player_status{role_god = RoleGod} = Player,
    #role_god{god_summon = GodSummon} = RoleGod,
    case GodSummon of
        #god_summon{fighters = [#god_fighting{skills = Skills, time = Time}|_]} when Time =/= 0 ->
            lists:keyfind(SkillId, 1, Skills);
        _ -> false
    end.

%% 场景:出手初始化战斗信息
scene_init_user(User) ->
    %% 式神状态下出手，需要转换为式神属性
    GodFighting = User#ets_scene_user.god_fighting,
    BA = User#ets_scene_user.battle_attr,
    Attr = BA#battle_attr.attr,
    case GodFighting of
        [#god_fighting{att = GodAtt, def = GodDef, hp = GodHp, hp_lim = GodHpLim, time = Time}|_] when Time =/= 0 ->
            {BA#battle_attr{attr = Attr#attr{att = GodAtt, def = GodDef}, hp = GodHp, hp_lim = GodHpLim}, BA#battle_attr.hp};
        _ ->
            {BA, BA#battle_attr.hp}
    end.

%% 战斗计算：是否无敌 抵抗所有控制 减速/流血/眩晕
check_sp_skill(SkillBuffer, GodFighting, Now) ->
    case GodFighting of

        [#god_fighting{battle_effect = BattleEffect, time = Time}|_] when Time =/= 0 ->
            %% 是否免控
            Superarmor = ?IF(lists:member(?SUIT_SKILL_ROLE_NO_CTRL, BattleEffect), 1, 0),
            %% 是否无敌 每个式神都有2秒无敌/套装技能增加2秒
            Immue = ?IF((Now - Time < 2000), 1,
                ?IF(lists:member(?SUIT_SKILL_ROLE_NO_HURT, BattleEffect) andalso (Now - Time < 4000), 1, 0)),
            SkillBuffer#skill_effect{superarmor = Superarmor, immue = Immue, un_speed = Superarmor, current_un_dizzy = Superarmor};
        _ ->
            SkillBuffer
    end.
is_un_control(GodFighting) ->
    case GodFighting of
        [#god_fighting{battle_effect = BattleEffect, time = Time}|_] when Time =/= 0 ->
            lists:member(?SUIT_SKILL_ROLE_NO_CTRL, BattleEffect);
        _ ->
            false
    end.
%% 场景:攻击者复原战斗信息 这里只复原血量信息 attr 会在之后的一步进行复原
%% OriginUser 场景玩家战斗前数据
%% OldbattleAttr 场景玩家最新的战斗属性
scene_after_battle_attack(OriginUser, OldBattleAttr) ->
    GodFighting = OriginUser#ets_scene_user.god_fighting,
    case GodFighting of
        [God = #god_fighting{time = Time}|Last] when Time =/= 0 ->
            %% 更新上阵唤神的最新血量
            Hp = OldBattleAttr#battle_attr.hp,
            NewGodFighting = [God#god_fighting{hp = Hp}|Last],
            %% 校正回玩家的原始血量
            #battle_attr{hp = InitHp, hp_lim = InitHpLim} = OriginUser#ets_scene_user.battle_attr,
            {NewGodFighting, OldBattleAttr#battle_attr{hp = InitHp, hp_lim = InitHpLim}};
        _ ->
            {GodFighting, OldBattleAttr}
    end.

%% 场景:战斗后防守者复原战斗信息 如果式神死亡，手动结束变身
%% OriginUser 场景玩家战斗前数据
%% OldbattleAttr 场景玩家最新的战斗属性
scene_after_battle_defend(OriginUser, Der, OldBattleAttr, _NowTime) ->
    GodFighting = Der#battle_status.god_fighting,
    case GodFighting of
        [God|T] when God#god_fighting.time =/= 0 ->
            Hp = OldBattleAttr#battle_attr.hp,
            case Hp > 0 of
                true  ->
                    NewGodFighting = [God#god_fighting{hp = Hp}|T];
                false ->
                    #battle_status{x = X, y = Y} = Der,
                    DerUser = OriginUser#ets_scene_user{x = X, y = Y},
                    send_to_scene(DerUser, #god_fighting{}),
                    NewGodFighting = T
                    % #god_fighting{id = NextGodId} = NextGod,
                    % scene_switch_god(OriginUser, 0, [], NowTime)
            end,
            #battle_attr{hp = InitHp, hp_lim = InitHpLim} = OriginUser#ets_scene_user.battle_attr,
            {NewGodFighting, OldBattleAttr#battle_attr{hp = InitHp, hp_lim = InitHpLim}};
        _ ->
            {GodFighting, OldBattleAttr}
    end.

%% 玩家进程:被攻击后
%% 式神死了,结束变身
role_after_be_attack(Player, GodId, 0) ->
    #player_status{role_god = RoleGod} = Player,
    #role_god{god_summon = GodSummon, temp_attr = TempAttr} = RoleGod,
    #god_summon{fighters = GodFighting} = GodSummon,
    NewGodFighting = lists:keydelete(GodId, #god_fighting.id, GodFighting),
    AddAttr = [],
    Player1 = Player#player_status{role_god = RoleGod#role_god{temp_attr = AddAttr, god_summon = GodSummon#god_summon{fighters = NewGodFighting}}},
    case AddAttr of
        TempAttr ->
            Player2 = Player1,
            Player2;
        _ ->
            Player2 = lib_player:count_player_attribute(Player1, ?MOD_GOD, god_summon, [god_summon]),
            mod_scene_agent:update(Player2, [{battle_attr, Player2#player_status.battle_attr}]),
            Player2
    end;
    % case NewGodFighting of
    %     [#god_fighting{id = NextGodId}|_] ->
    %         NewPlayer = god_logic:role_switch_god(Player#player_status{role_god = RoleGod#role_god{god_summon = GodSummon#god_summon{fighters = NewGodFighting}}}, NextGodId),
    %         NewPlayer;
    %     _ ->
    %         NewPlayer = Player#player_status{role_god = RoleGod#role_god{god_summon = GodSummon#god_summon{fighters = NewGodFighting}}},
    %         NewPlayer
    % end;
role_after_be_attack(Player, GodId, Hp) ->
    #player_status{role_god = RoleGod} = Player,
    #role_god{god_summon = GodSummon} = RoleGod,
    case GodSummon of
        #god_summon{fighters = [#god_fighting{id = GodId, time = Time} = One|T]} when Time =/= 0 ->
            NewGod = [One#god_fighting{hp = Hp}|T],
            NewGodSummon = GodSummon#god_summon{fighters = NewGod},
            Player#player_status{role_god = RoleGod#role_god{god_summon = NewGodSummon}};
        _ ->
            Player
    end.
%% 死亡处理
handle_event(Player, #event_callback{type_id = ?EVENT_PLAYER_DIE}) ->
    #player_status{
        role_god = RoleGod, scene = Scene, scene_pool_id = PoolId, id = RoleId
    } = Player,
    case RoleGod#role_god.god_summon of
        #god_summon{ref = Ref} ->
            mod_scene_agent:apply_cast(
                Scene, PoolId, god_api, scene_summon_god, [RoleId, 0, []]
            ),
            util:cancel_timer(Ref);
        _ ->
            ok
    end,
    {ok, Player#player_status{role_god = RoleGod#role_god{god_summon = undefined}}};

handle_event(Player, _) ->
    {ok, Player}.

%% 场景处理唤神切换
%% 将新的式神数据 广播
scene_switch_god(User, GodId, GodFighting) ->
    Now = utime:longunixtime(),
    scene_switch_god(User, GodId, GodFighting, Now).

scene_switch_god(User, GodId, GodFighting, Now) ->
    NewGodFighting = do_scene_switch_god(Now, GodId, GodFighting),
    case NewGodFighting of
        [God|_] ->
            send_to_scene(User, God);
        _ -> % 变身结束
            send_to_scene(User, #god_fighting{})
    end,
    NewGodFighting.

do_scene_switch_god(Now, GodId, GodFighting) ->
    case lists:keytake(GodId, #god_fighting.id, GodFighting) of
        {value, God, T} ->
            [God#god_fighting{time = Now}|T];
        _ -> GodFighting %% 没有式神
    end.

send_to_scene(#ets_scene_user{scene = Scene, id = RoleId, copy_id = CopyId, x = X, y = Y},
    #god_fighting{id = GodId, hp = Hp, hp_lim = HpLime}) ->
    {ok, Bin} = pt_173:write(17319, [RoleId, GodId, Hp, HpLime]),
    case lib_scene:is_broadcast_scene(Scene) of
        true  -> lib_scene_agent:send_to_local_scene(CopyId, Bin);
        false -> lib_scene_agent:send_to_local_area_scene(CopyId, X, Y, Bin)
    end.

%%--------------------------------------------------------------------
%% 式神数据
%%--------------------------------------------------------------------
%% 战斗消息 是否处于式神战斗中
is_in_god_fighting(BattleAttr) ->
    case BattleAttr#battle_status.god_fighting of
        [#god_fighting{id = GodId, time = Time}|_] when Time =/= 0 -> GodId;
        _ -> 0
    end.

%% 式神血量 攻击者和防守者都会调用该方法
get_fighting_god_hp(BattleStatus, Hp) ->
    case BattleStatus#battle_status.god_fighting of
        [#god_fighting{time = Time}|_] when Time =/= 0 ->
            case Hp > 0 of
                true  -> Hp;
                false -> 0
            end;
        _ -> 0
    end.

%% 玩家血量 攻击者和防守者都会调用该方法
get_fighting_role_hp(BattleStatus, Hp) ->
    case BattleStatus#battle_status.god_fighting of
        [#god_fighting{time = Time}|_] when Time =/= 0 -> 
            BattleStatus#battle_status.origin_hp;
        _ ->
            Hp
    end.

%% 场景玩家式神信息
pack_scene_user(User) ->
    case User#ets_scene_user.god_fighting of
        [#god_fighting{time = Time}|_] when Time =/= 0 ->
            pack_user_god_info(User#ets_scene_user.god_fighting);
        _ ->
            {0, 0, 0}
    end.

pack_user_god_info([]) -> {0, 0, 0};
pack_user_god_info([#god_fighting{hp = Hp, hp_lim = HpLim, id = GodId}|_Rest]) ->
    {GodId, Hp, HpLim}.

%% 人物发送玩家式神信息
pack_role_user(Player) ->
    #player_status{role_god = RoleGod} = Player,
    #role_god{god_summon = GodSummon} = RoleGod,
    case GodSummon of
        #god_summon{fighters = Fighters = [#god_fighting{time = Time}|_]} when Time =/= 0 ->
            pack_user_god_info(Fighters);
        _ ->
            {0, 0, 0}
    end.

%% 玩家加入场景
enter_scene(Player) ->
    #player_status{role_god = RoleGod} = Player,
    case RoleGod of
        #role_god{god_summon = GodSummon} ->
            case GodSummon of
                #god_summon{fighters = Gods} -> Gods;
                _ -> []
            end;
        _ ->
            []
    end.

%% 秘籍重置
reset_god(Player) ->
    #player_status{id = RoleId, role_god = RoleGod} = Player,
    case RoleGod of
        #role_god{} ->
            db:execute(<<"DELETE FROM role_god WHERE role_id = ~p">>, [RoleId]),
            db:execute(<<"DELETE FROM role_god_info WHERE role_id = ~p">>, [RoleId]),
            GoodsStatus = lib_goods_do:get_goods_status(),
            ok = lib_goods_dict:start_dict(),
            GodEquips = lib_goods_util:get_goods_list_by_type(RoleId, ?GOODS_LOC_GOD_EQUIP, ?GOODS_TYPE_GOD_EQUIP, GoodsStatus#goods_status.dict),
            CostL = [{GoodsInfo, GoodsInfo#goods.num} || GoodsInfo <- GodEquips, is_record(GoodsInfo, goods)],
            {ok, GoodsStatus1} = goods_del:delete_goods_list(GoodsStatus, CostL),
            {Dict, GoodsL} = lib_goods_dict:handle_dict_and_notify(GoodsStatus1#goods_status.dict),
            GoodsStatus2   = GoodsStatus1#goods_status{dict = Dict},
            lib_goods_do:set_goods_status(GoodsStatus2),
            lib_goods_api:notify_client_num(RoleId, [G#goods{num = 0} || G <- GoodsL, is_record(G, goods)]),
            Player#player_status{role_god = #role_god{}};
        _ ->
            Player
    end.

reset_god_cd(Player, Pos) ->
    #player_status{sid = Sid, role_god = RoleGod} = Player,
    Now = utime:unixtime(),
    case RoleGod of
        #role_god{god_info = GodInfo, summon_time = SummonTimeList} ->
            case lists:keyfind(Pos, #god.pos, GodInfo) of
                #god{} when ?IS_PRIMARY_GOD(Pos) ->
                    Cd = data_god:get_kv(god_summon_cd),
                    case lists:keyfind(Pos, 1, SummonTimeList) of
                        {_, Time} ->
                            Last = Now - Time,
                            if Last >= Cd -> Player;
                                true ->
                                    NewSummonTimeList = lists:keystore(Pos, 1, SummonTimeList,{Pos, Now-(Cd+1)}),
                                    lib_server_send:send_to_sid(Sid, pt_173, 17312, [NewSummonTimeList]),
                                    Player#player_status{role_god = RoleGod#role_god{summon_time = NewSummonTimeList}}
                            end;
                        _A -> Player
                    end;
                _A -> Player
            end;
        _ -> Player
    end.

%%%===================================================================
%% @doc 使用物品
% use_goods(PlayerStatus, GoodsInfo) ->
%     case GoodsInfo#goods.subtype of
%         ?GOODS_GOD_ACTIVE_CARD ->
%             case data_god:get_god_by_goods_id(GoodsInfo#goods.goods_id) of
%                 [GodId|_] ->
%                     case data_god:get_god_info(GodId, 0) of
%                         #base_god_info{} ->
%                             %% 异步处理
%                             lib_player:apply_cast(PlayerStatus#player_status.pid, ?APPLY_CAST_STATUS, ?MODULE, active_by_card, [GodId, GoodsInfo#goods.goods_id]),
%                             ok;
%                         _ -> {fail, ?FAIL}
%                     end;
%                 _ ->
%                     {fail, ?FAIL}
%             end;
%         _ -> {fail, ?FAIL}
%     end.
%% 异步进行处理
% active_by_card(Player, GodId, GoodsId) ->
%     #player_status{role_god = RoleGod} = Player,
%     #role_god{god_info = GodInfo} = RoleGod,
%     #base_god_info{skills = Skills, cost = Cost} = data_god:get_god_info(GodId, 0),
%     case lists:keymember(GodId, #god.id, GodInfo) of
%         true  ->
%             Player1 = lib_goods_api:send_reward(Player, Cost, god_active_card);
%         false ->
%             God = #god{skills = Skills, id = GodId},
%             Player1 = god_logic:do_active(Player, God, [{?TYPE_GOODS, GoodsId, 1}])
%     end,
%     {ok, Player1}.



