%%%-------------------------------------------------------------------
%%% @author licheng5
%%% @copyright (C) 2020, <COMPANY>
%%% @doc
%%%
%%% @end
%%% Created : 26. 4月 2020 3:36 下午
%%%-------------------------------------------------------------------
-module(host_handler).
-author("licheng5").
-include("iot.hrl").

%% API
-export([handle_request/4]).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% helper methods
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

handle_request("GET", "/host/metric", #{<<"uuid">> := UUID}, _) ->
    lager:debug("[host_handler] get host metric uuid is: ~p", [UUID]),
    case iot_host:get_pid(UUID) of
        undefined ->
            {ok, 200, iot_util:json_error(404, <<"host not found">>)};
        Pid when is_pid(Pid) ->
            {ok, MetricInfo} = iot_host:get_metric(Pid),
            case map_size(MetricInfo) > 0 of
                true ->
                    {ok, 200, iot_util:json_data(MetricInfo)};
                false ->
                    {ok, 200, iot_util:json_error(404, <<"no metric info">>)}
            end
    end;

%% 处理主机的授权的 取消激活
handle_request("GET", "/host/status", #{<<"uuid">> := UUID}, _) when is_binary(UUID) ->
    case iot_host:get_pid(UUID) of
        undefined ->
            {ok, 200, iot_util:json_error(404, <<"host not found">>)};
        Pid when is_pid(Pid) ->
            {ok, StatusInfo} = iot_host:get_status(Pid),
            {ok, 200, iot_util:json_data(StatusInfo)}
    end;

%% 重新加载对应的主机信息
handle_request("POST", "/host/reload", _, #{<<"uuid">> := UUID}) when is_binary(UUID) ->
    lager:debug("[host_handler] will reload host uuid: ~p", [UUID]),
    case iot_host_sup:ensured_host_started(UUID) of
        {ok, Pid} when is_pid(Pid) ->
            {ok, #{<<"authorize_status">> := AuthorizeStatus}} = host_bo:get_host_by_uuid(UUID),
            ok = iot_host:activate(Pid, AuthorizeStatus =:= 1),
            lager:debug("[host_handler] already_started reload host uuid: ~p, success", [UUID]),
            {ok, 200, iot_util:json_data(<<"success">>)};
        Error ->
            lager:debug("[host_handler] reload host uuid: ~p, error: ~p", [UUID, Error]),
            {ok, 200, iot_util:json_error(404, <<"reload error">>)}
    end;

%% 删除对应的主机信息
handle_request("POST", "/host/delete", _, #{<<"uuid">> := UUID}) when is_binary(UUID) ->
    case iot_host_sup:delete_host(UUID) of
        ok ->
            lager:debug("[host_handler] will delete host uuid: ~p", [UUID]),
            {ok, 200, iot_util:json_data(<<"success">>)};
        {error, Reason} ->
            lager:debug("[host_handler] delete host uuid: ~p, get error is: ~p", [UUID, Reason]),
            {ok, 200, iot_util:json_error(404, <<"error">>)}
    end;

%% 下发参数
handle_request("POST", "/host/publish_command", _,
    PostParams = #{<<"uuid">> := UUID, <<"command_type">> := CommandType, <<"task_id">> := TaskId, <<"timeout">> := Timeout, <<"params">> := Params})
    when is_binary(UUID), is_integer(TaskId), is_integer(Timeout), is_integer(CommandType) ->

    lager:debug("[http_host_handler] publish_command body is: ~p", [PostParams]),
    case iot_host:get_pid(UUID) of
        undefined ->
            {ok, 200, iot_util:json_error(404, <<"host not found">>)};
        Pid when is_pid(Pid) ->
            Reply = #{
                <<"t_id">> => integer_to_binary(TaskId),
                <<"t">> => Timeout,
                <<"ts">> => iot_util:current_time(),
                <<"m">> => iolist_to_binary(jiffy:encode(Params, [force_utf8]))
            },

            Reply1 = append_service_name(PostParams, Reply),
            lager:debug("[http_host_handler] publish message is: ~p", [Reply1]),
            BinReply = iolist_to_binary(jiffy:encode(Reply1, [force_utf8])),

            case iot_host:publish_message(Pid, CommandType, {aes, BinReply}, Timeout * 1000) of
                {error, timeout} ->
                    lager:debug("[iot_host_handler] host_id uuid: ~p, publish topic success, but get ack timeout", [UUID]),
                    {ok, _} = task_logs_bo:change_status(TaskId, ?TASK_STATUS_FAILED),
                    {ok, 200, iot_util:json_error(401, <<"命令执行超时, 请重试"/utf8>>)};
                {error, Reason} when is_binary(Reason) ->
                    task_logs_bo:change_status(TaskId, ?TASK_STATUS_FAILED),
                    {ok, 200, iot_util:json_error(400, Reason)};
                ok ->
                    {ok, _} = task_logs_bo:change_status(TaskId, ?TASK_STATUS_OK),
                    {ok, 200, iot_util:json_data(<<"success">>)};
                {ok, Response} ->
                    case jiffy:decode(Response, [return_maps]) of
                        #{<<"code">> := 1} ->
                            {ok, _} = task_logs_bo:change_status(TaskId, ?TASK_STATUS_OK),
                            {ok, 200, iot_util:json_data(<<"success">>)};
                        #{<<"code">> := 0, <<"message">> := Message} when is_binary(Message) ->
                            {ok, _} = task_logs_bo:change_status(TaskId, ?TASK_STATUS_FAILED),
                            {ok, 200, iot_util:json_error(401, <<"操作失败: "/utf8, Message/binary>>)}
                    end
            end
    end;

%% 处理主机的授权的激活
handle_request("POST", "/host/activate", _, #{<<"uuid">> := UUID, <<"auth">> := true}) when is_binary(UUID) ->
    case iot_host_sup:ensured_host_started(UUID) of
        {error, Reason} ->
            lager:debug("[host_handler] activate host_id: ~p, failed with reason: ~p", [UUID, Reason]),
            {ok, 200, iot_util:json_error(400, <<"host not found">>)};
        {ok, Pid} when is_pid(Pid) ->
            lager:debug("[host_handler] activate host_id: ~p, start", [UUID]),
            ok = iot_host:activate(Pid, true),

            {ok, 200, iot_util:json_data(<<"success">>)}
    end;

%% 处理主机的授权的 取消激活
handle_request("POST", "/host/activate", _, #{<<"uuid">> := UUID, <<"auth">> := false}) when is_binary(UUID) ->
    case iot_host_sup:ensured_host_started(UUID) of
        {error, Reason} ->
            lager:debug("[host_handler] activate host_id: ~p, failed with reason: ~p", [UUID, Reason]),
            {ok, 200, iot_util:json_error(400, <<"host not found">>)};
        {ok, Pid} when is_pid(Pid) ->
            lager:debug("[host_handler] activate host_id: ~p, start", [UUID]),
            ok = iot_host:activate(Pid, false),

            {ok, 200, iot_util:json_data(<<"success">>)}
    end;

handle_request(_, Path, _, _) ->
    Path1 = list_to_binary(Path),
    {ok, 200, iot_util:json_error(-1, <<"url: ", Path1/binary, " not found">>)}.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% helper methods
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% 追加service_name参数
append_service_name(#{<<"service_name">> := ServiceName}, Reply) when is_binary(ServiceName), ServiceName =/= <<"">> ->
    Reply#{<<"to">> => ServiceName};
append_service_name(_, Reply) ->
    Reply.