%%%-------------------------------------------------------------------
%%% @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}, _) ->
    logger: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/delete", _, #{<<"uuid">> := UUID}) when is_binary(UUID) ->
    case iot_host:get_pid(UUID) of
        Pid when is_pid(Pid) ->
            ok = iot_host_sup:delete_host(UUID),
            {ok, 200, iot_util:json_data(<<"success">>)};
        undefined ->
            {ok, 200, iot_util:json_error(404, <<"error">>)}
    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} ->
            logger: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) ->
            logger:debug("[host_handler] activate host_id: ~p, start", [UUID]),
            auth_response(iot_host:activate(Pid, true))
    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} ->
            logger: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) ->
            logger:debug("[host_handler] activate host_id: ~p, start", [UUID]),
            auth_response(iot_host:activate(Pid, false))
    end;

%% 主机事件发布
handle_request("POST", "/host/pub", _, #{<<"uuid">> := UUID, <<"topic">> := Topic, <<"qos">> := Qos0, <<"content">> := Content})
    when is_binary(UUID), is_binary(Topic), is_binary(Content), is_integer(Qos0) ->

    Qos = case Qos0 > 0 of true -> 1; false -> 0 end,
    case iot_host_sup:ensured_host_started(UUID) of
        {error, Reason} ->
            logger:debug("[host_handler] pub host_id: ~p, topic: ~p, failed with reason: ~p", [UUID, Topic, Reason]),
            {ok, 200, iot_util:json_error(400, <<"host not found">>)};
        {ok, Pid} when is_pid(Pid) ->
            case iot_host:pub(Pid, Topic, Qos, Content) of
                ok ->
                    {ok, 200, iot_util:json_data(<<"success">>)};
                {error, Reason} ->
                    {ok, 200, iot_util:json_error(400, Reason)}
            end
    end;

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

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

auth_response(ok) ->
    {ok, 200, iot_util:json_data(<<"success">>)};
auth_response({error, Reason}) ->
    {ok, auth_error_status(Reason), iot_util:json_error(auth_error_status(Reason), reason_to_binary(Reason))}.

auth_error_status(timeout) ->
    504;
auth_error_status(<<"timeout">>) ->
    504;
auth_error_status(_) ->
    400.

reason_to_binary(Reason) when is_binary(Reason) ->
    Reason;
reason_to_binary(timeout) ->
    <<"timeout">>;
reason_to_binary(invalid_response) ->
    <<"invalid response">>;
reason_to_binary({failed, Reason}) ->
    reason_to_binary(Reason);
reason_to_binary({channel_closed, Reason}) ->
    <<"channel closed: ", (reason_to_binary(Reason))/binary>>;
reason_to_binary(Reason) ->
    unicode:characters_to_binary(io_lib:format("~p", [Reason])).
