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

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

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

%% 重新加载对应的主机信息
handle_request("POST", "/device/reload", _, #{<<"host_id">> := HostId, <<"device_uuid">> := DeviceUUID}) when is_integer(HostId), is_binary(DeviceUUID) ->
    lager:debug("[device_handler] host_id: ~p, will reload device uuid: ~p", [HostId, DeviceUUID]),
    AliasName = iot_host:get_alias_name(HostId),
    case global:whereis_name(AliasName) of
        undefined ->
            {ok, 200, iot_util:json_error(404, <<"reload device failed">>)};
        HostPid when is_pid(HostPid) ->
            case iot_host:reload_device(HostPid, DeviceUUID) of
                ok ->
                    {ok, 200, iot_util:json_data(<<"success">>)};
                {error, Reason} ->
                    lager:debug("[device_handler] reload device: ~p, get error: ~p", [DeviceUUID, Reason]),
                    {ok, 200, iot_util:json_error(404, <<"reload device failed">>)}
            end
    end;

%% 删除对应的主机信息
handle_request("POST", "/device/delete", _, #{<<"host_id">> := HostId, <<"device_uuid">> := DeviceUUID}) when is_integer(HostId), is_binary(DeviceUUID) ->
    AliasName = iot_host:get_alias_name(HostId),
    case global:whereis_name(AliasName) of
        undefined ->
            {ok, 200, iot_util:json_error(404, <<"delete device failed">>)};
        HostPid when is_pid(HostPid) ->
            ok = iot_host:delete_device(HostPid, DeviceUUID),
            {ok, 200, iot_util:json_data(<<"success">>)}
    end;

%% 处理主机的授权的激活
handle_request("POST", "/device/activate", _, #{<<"host_id">> := HostId, <<"device_uuid">> := DeviceUUID, <<"auth">> := Auth})
    when is_integer(HostId), is_binary(DeviceUUID), is_boolean(Auth) ->

    AliasName = iot_host:get_alias_name(HostId),
    case global:whereis_name(AliasName) of
        undefined ->
            {ok, 200, iot_util:json_error(404, <<"activate device failed">>)};
        HostPid when is_pid(HostPid) ->
            case iot_host:activate_device(HostPid, DeviceUUID, Auth) of
                ok ->
                    {ok, 200, iot_util:json_data(<<"success">>)};
                {error, Reason} ->
                    lager:debug("[device_handler] activate device: ~p, get error: ~p", [DeviceUUID, Reason]),
                    {ok, 200, iot_util:json_error(404, <<"activate device failed">>)}
            end
    end;

%% 重新加载对应的主机信息
handle_request("POST", "/device/query", _, Params = #{<<"device_uuid">> := DeviceUUID}) when is_binary(DeviceUUID) ->
    lager:debug("[device_handler] query device uuid: ~p, params: ~p", [DeviceUUID, Params]),
    case iot_device:get_pid(DeviceUUID) of
        undefined ->
            {ok, 200, iot_util:json_error(404, <<"device not found">>)};
        DevicePid when is_pid(DevicePid) ->
            Tags = maps:get(<<"tags">>, Params, #{}),
            StartTs = maps:get(<<"start_ts">>, Params, 0),
            StopTs = maps:get(<<"stop_ts">>, Params, 0),
            Limit = maps:get(<<"limit">>, Params, 0),

            case is_map(Tags) andalso is_integer(StartTs) andalso is_integer(StopTs) andalso is_integer(Limit)
                andalso StartTs >= 0 andalso StopTs >= 0 andalso Limit >= 0 of

                true ->
                    {ok, DeviceDataList} = iot_device:query(DevicePid, Tags, StartTs, StopTs, Limit),
                    DataItems = lists:map(fun(#device_data{tags = Tags0, val = Val, timestamp = Timestamp}) ->
                        #{<<"tags">> => Tags0, <<"val">> => Val, <<"timestamp">> => Timestamp}
                                          end, DeviceDataList),
                    {ok, 200, iot_util:json_data(DataItems)};
                false ->
                    {ok, 200, iot_util:json_error(404, <<"invalid params">>)}
            end
    end;

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