%% ---------------------------------------------------------------------------
%% @doc 转职
%% @author zhaoyu
%% @since  2019-02-18
%% ---------------------------------------------------------------------------
-module(transform).

-include("transform.hrl").
-include("server.hrl").
-include("predefine.hrl").
-include("figure.hrl").
-include("common.hrl").
-include("def_event.hrl").
-include("def_module.hrl").

-export([
    login/1                         %% 角色登录加载数据
    ,trigger_task/2                 %% 接任务后触发
    ,finish_task/3                  %% 完成任务
    ,get_transform_attr/1           %% 转职属性
    ,save_transform_data/2          %% 保存角色转职数据
    ,transform_up/1                 %% 转职成功
    ,calc_transform/1               %% 计算转职属性等
    ,get_turn_from_db/1             %% 从数据库加载角色转职
    ,is_skill_matching/4            %% 检查技能是否符合当前转职阶段
    ,get_model_id/2                 %% 获得转职等级模型
    ,get_unlock_equipment_series/1  %% 获得解锁的装备代数
    ,get_transform_id/1             %% 获得当前转职Id
]).

%% ---------------------------------------------------------------------------
%% @doc 角色登录加载数据
-spec login(RoleId) -> TransformInfo when
    RoleId          :: integer(),
    TransformInfo   :: #transform_info{}.
%% ---------------------------------------------------------------------------
login(RoleId) ->
    load_transform_info(RoleId).


%% ---------------------------------------------------------------------------
%% @doc 接任务后触发
-spec trigger_task(Role, TaskId) -> {ok, NewRole} when
    Role        :: #player_status{},
    TaskId      :: integer(),
    NewRole     :: #player_status{}.
%% ---------------------------------------------------------------------------
trigger_task(Role, TaskId) ->
    #player_status{
        sid = Sid, figure = Figure, transform_data = TransformData, id = RoleId
    } = Role,
    #transform_info{stage = Stage} = TransformData,
    NewStage = case data_transform:get_transform_step_cfg_by_task_id(TaskId) of
        #transform_step{id = _TId, stage = NStage, need_lev = _NeedLev} ->
            NStage;
        _ ->
            ?ERR("~p trigger_task important error ~p", [?MODULE, TaskId]),
            Stage
    end,
    TransformData2 = TransformData#transform_info{stage = NewStage},
    save_transform_data(RoleId, TransformData2),
    lib_server_send:send_to_sid(Sid, pt_130, 13041, [NewStage]),
    Figure2 = Figure#figure{turn_stage = NewStage},
    Role2 = Role#player_status{figure = Figure2, transform_data = TransformData2},
    {ok, Role2}.


%% ---------------------------------------------------------------------------
%% @doc 完成任务
-spec finish_task(Role, TaskId, NextTaskId) -> {ok, NewRole} when
    Role        :: #player_status{},
    TaskId      :: integer(),
    NextTaskId  :: integer(),
    NewRole     :: #player_status{}.
%% ---------------------------------------------------------------------------
finish_task(Role, TaskId, NextTaskId) ->
    case data_transform:get_transform_step_cfg_by_task_id(TaskId) of
        TransformStep = #transform_step{} ->
            finish_task(Role, TaskId, NextTaskId, TransformStep);
        _ ->
            ?ERR("~p finish_task important error ~p", [?MODULE, TaskId]),
            {ok, Role}
    end.

finish_task(Role, TaskId, NextTaskId, TransformStep) ->
    #player_status{
        figure = Figure, transform_data = TransformData, id = RoleId
    } = Role,
    #transform_info{
        transform_id = TransformId, stage = Stage, attr_list = Attr
    } = TransformData,
    #transform_step{id = TaskTransformId, stage = TaskStage, reward = Reward} = TransformStep,
    {NewTransformId, NewStage} = case NextTaskId of
        0 -> %% 完成当前转职所有任务
            {TaskTransformId, 0};
        _ ->
            {TransformId, TaskStage}
    end,

    TransformData2 = TransformData#transform_info{
        transform_id = NewTransformId, stage = NewStage
    },
    TransformData3 = #transform_info{
        attr_list = NewAttr
    } = calc_transform(TransformData2),
    case {NewTransformId, NewStage} of
        {TransformId, Stage} -> %% 没变
            {ok, Role};
        _ ->
            save_transform_data(RoleId, TransformData3),
            Figure2 = Figure#figure{turn = NewTransformId, turn_stage = NewStage},
            Role2 = Role#player_status{
                figure = Figure2, transform_data = TransformData3
            },
            NewRole = case NewAttr =/= Attr of
                false -> %% 属性没发生变化不用重新计算
                    Role2;
                true ->
                    Role3 = lib_player:count_player_attribute(Role2),
                    lib_player:send_attribute_change_notify(Role3, ?NOTIFY_ATTR),
                    Role3
            end,
            NewRole2 = case NewTransformId =:= TaskTransformId of
                true -> %% 转职成功
                    transform_up(NewRole);
                _ ->
                    NewRole
            end,
            %% 发奖
            NewRole3 = case Reward =/= [] of
                           true  -> lib_goods_api:send_reward(NewRole2, Reward, transform_up);
                           false -> Role2
                       end,
            %% 日志
            lib_log_api:log_transform(RoleId, NewTransformId, TaskId, Figure#figure.lv),
            {ok, NewRole3}
    end.


%% ---------------------------------------------------------------------------
%% @doc 计算转职属性等
-spec calc_transform(TransformData) -> NewTransformData when
    TransformData    :: #transform_info{},
    NewTransformData :: #transform_info{}.
%% ---------------------------------------------------------------------------
calc_transform(TransformData) ->
    #transform_info{transform_id = TransformId} = TransformData,
    case get_cur_transform_cfg(TransformId) of
        #transform_step{skill_list = SkillList, attr_list = AttrList} ->
            %% 累加每转的属性
            NewAttrList = calc_transform_attr(TransformId - 1, AttrList),
            TransformData#transform_info{
                skill_list = SkillList, attr_list = NewAttrList
            };
        _ ->
            TransformData
    end.

calc_transform_attr(TransformId, AttrList) ->
    case get_cur_transform_cfg(TransformId) of
        #transform_step{attr_list = AttrL} ->
            NewAttrList = util:combine_list(AttrL ++ AttrList),
            calc_transform_attr(TransformId - 1, NewAttrList);
        _ ->
            AttrList
    end.


%% ---------------------------------------------------------------------------
%% @doc 转职成功
-spec transform_up(Role) -> NewRole when
    Role        :: #player_status{},
    NewRole     :: #player_status{}.
%% ---------------------------------------------------------------------------
transform_up(Role) ->
    #player_status{sid = Sid, id = RoleId, figure = Figure} = Role,
    #figure{
        name = Name, turn = NewTurn, career = Career, sex = Sex, lv = Lv
    } = Figure,

    NewLvModel = lib_player:get_model_list(Career, Sex, NewTurn, Lv),
    %% 等级模型是否需要更换？
    Figure2 = Figure#figure{lv_model = NewLvModel},
    {ok, Role2} = lib_skill:auto_learn_skill(
        Role#player_status{figure = Figure2}, {turn, NewTurn, []}
    ),
    lib_server_send:send_to_sid(Sid, pt_130, 13040, [Career, Sex, NewTurn, 0]),

    {ok, Role3} = lib_player_event:dispatch(Role2, ?EVENT_TURN_UP),
    %% 转生传闻
    TransformName = data_transform:get_career_transform_name(Career, NewTurn),
    lib_chat:send_TV({all}, ?MOD_TRANSFORM, 1, [Name, RoleId, NewTurn, TransformName]),
    %% 更新场景玩家的数据
    mod_scene_agent:update(Role3, [{turn, NewTurn}, {lv_model, NewLvModel}]),
    lib_scene:broadcast_player_attr(Role3, NewLvModel),
    Role3.


%% ---------------------------------------------------------------------------
%% @doc 检查技能是否符合当前转职阶段
-spec is_skill_matching(Career, Sex, Turn, SkillId) -> true | false when
    Career      :: integer(),
    Sex         :: integer(),
    Turn        :: integer(),
    SkillId     :: integer().
%% ---------------------------------------------------------------------------
is_skill_matching(_Career, _Sex, Turn, SkillId) when Turn > 0 ->
    MaxStage = data_transform:get_transform_max_stage(Turn),
    SkillList = case data_transform:get_transform_step_cfg(Turn, MaxStage) of
        #transform_step{skill_list = SList} -> SList;
        _ -> []
    end,
    %% 如果技能是转生过程中需要替换掉的技能则不允许玩家使用
    case lists:member(SkillId, SkillList) of
        false -> true;
        _ -> false
    end;
is_skill_matching(_, _, _, _) ->
    true.


%% ---------------------------------------------------------------------------
%% @doc 转职属性
-spec get_transform_attr(TransformData) -> AttrList when
    TransformData:: #transform_info{},
    AttrList    :: [{AttrId :: integer(), Value :: integer()}].
%% ---------------------------------------------------------------------------
get_transform_attr(TransformData = #transform_info{}) ->
    TransformData#transform_info.attr_list;
get_transform_attr(_) ->
    [].


%% ---------------------------------------------------------------------------
%% @doc 从数据库加载角色转职
-spec get_turn_from_db(RoleId) -> Turn when
    RoleId      :: integer(),
    Turn        :: integer().
%% ---------------------------------------------------------------------------
get_turn_from_db(RoleId) ->
    #transform_info{transform_id = Turn} = login(RoleId),
    Turn.

%% ---------------------------------------------------------------------------
%% @doc 加载角色转职数据
-spec load_transform_info(RoleId) -> TransformInfo when
    RoleId      :: integer(),
    TransformInfo:: #transform_info{}.
%% ---------------------------------------------------------------------------
load_transform_info(RoleId) ->
    case db:get_row(io_lib:format(?LOAD_TRANSFORM_INFO, [RoleId])) of
        [TranferId, Stage] ->
            TransformData = #transform_info{transform_id = TranferId, stage = Stage},
            TransformData2 = calc_transform(TransformData),
            TransformData2;
        _ ->
            #transform_info{}
    end.


%% ---------------------------------------------------------------------------
%% @doc 保存角色转职数据
-spec save_transform_data(RoleId, TransformData) -> ok when
    RoleId      :: integer(),
    TransformData:: #transform_info{}.
%% ---------------------------------------------------------------------------
save_transform_data(RoleId, TransformData) ->
    #transform_info{transform_id = TransferId, stage = Stage} = TransformData,
    db:execute(io_lib:format(?SAVE_TRANSFORM_INFO, [RoleId, TransferId, Stage])),
    ok.


%% ---------------------------------------------------------------------------
%% @doc 获得转职等级模型
-spec get_model_id(Career, TransformId) -> ModelId when
    Career      :: integer(),
    TransformId :: integer(),
    ModelId     :: integer().
%% ---------------------------------------------------------------------------
get_model_id(Career, TransformId) ->
    data_transform:get_transform_model_id(Career, TransformId).

%% ---------------------------------------------------------------------------
%% @doc 获得当前转职的配置
get_cur_transform_cfg(TransformId) ->
    MaxStage = data_transform:get_transform_max_stage(TransformId),
    data_transform:get_transform_step_cfg(TransformId, MaxStage).

%% ---------------------------------------------------------------------------
%% @doc 获得解锁的装备代数
get_unlock_equipment_series(Player) ->
    #player_status{
        transform_data = #transform_info{transform_id = TransformId}
    } = Player,
    case get_cur_transform_cfg(TransformId) of
        #transform_step{equipment_series = Series} -> Series;
        _ -> 1
    end.

%% ---------------------------------------------------------------------------
%% @doc 获得当前转职Id
get_transform_id(Player) ->
    #player_status{
        transform_data = #transform_info{transform_id = TransformId}
    } = Player,
    TransformId.
