%%%-------------------------------------------------------------------
  @author  
   ( C ) 2021 ACK CYFRONET AGH
  This software is released under the MIT license
  cited in ' LICENSE.txt ' .
%%% @end
%%%-------------------------------------------------------------------
%%% @doc
%%% This module handles middleware operations (create, get, update, delete)
%%% corresponding to automation workflow schemas.
%%% @end
%%%-------------------------------------------------------------------
-module(atm_workflow_schema_middleware_plugin).
-author("Bartosz Walkowicz").

-behaviour(middleware_router).
-behaviour(middleware_handler).

-include("middleware/middleware.hrl").
-include_lib("ctool/include/errors.hrl").
-include_lib("ctool/include/logging.hrl").
-include_lib("ctool/include/privileges.hrl").

%% middleware_router callbacks
-export([resolve_handler/3]).

%% middleware_handler callbacks
-export([data_spec/1, fetch_entity/1, authorize/2, validate/2]).
-export([create/1, get/2, update/1, delete/1]).


%%%===================================================================
%%% middleware_router callbacks
%%%===================================================================


%%--------------------------------------------------------------------
%% @doc
%% {@link middleware_router} callback resolve_handler/3.
%% @end
%%--------------------------------------------------------------------
-spec resolve_handler(middleware:operation(), gri:aspect(), middleware:scope()) ->
    module() | no_return().
resolve_handler(get, instance, private) -> ?MODULE;

resolve_handler(_, _, _) -> throw(?ERROR_NOT_SUPPORTED).


%%%===================================================================
%%% middleware_handler callbacks
%%%===================================================================


%%--------------------------------------------------------------------
%% @doc
%% {@link middleware_handler} callback data_spec/1.
%% @end
%%--------------------------------------------------------------------
-spec data_spec(middleware:req()) -> undefined | middleware_sanitizer:data_spec().
data_spec(#op_req{operation = get, gri = #gri{aspect = instance}}) ->
    undefined.


%%--------------------------------------------------------------------
%% @doc
%% {@link middleware_handler} callback fetch_entity/1.
%%
%% For now fetches only records for authorized users.
%% @end
%%--------------------------------------------------------------------
-spec fetch_entity(middleware:req()) ->
    {ok, middleware:versioned_entity()} | errors:error().
fetch_entity(#op_req{auth = ?NOBODY}) ->
    ?ERROR_UNAUTHORIZED;

fetch_entity(#op_req{auth = Auth, gri = #gri{id = AtmWorkflowSchemaId, scope = private}}) ->
    case atm_workflow_schema_logic:get(Auth#auth.session_id, AtmWorkflowSchemaId) of
        {ok, #document{value = AtmWorkflowSchema}} ->
            {ok, {AtmWorkflowSchema, 1}};
        {error, _} = Error ->
            Error
    end.


%%--------------------------------------------------------------------
%% @doc
%% {@link middleware_handler} callback authorize/2.
%% @end
%%--------------------------------------------------------------------
-spec authorize(middleware:req(), middleware:entity()) -> boolean().
authorize(#op_req{auth = ?GUEST}, _) ->
    false;

authorize(#op_req{operation = get, gri = #gri{aspect = instance}}, _) ->
    % authorization was checked by oz in `fetch_entity`
    true.


%%--------------------------------------------------------------------
%% @doc
%% {@link middleware_handler} callback validate/2.
%% @end
%%--------------------------------------------------------------------
-spec validate(middleware:req(), middleware:entity()) -> ok | no_return().
validate(#op_req{operation = get, gri = #gri{aspect = instance}}, _) ->
    % validation was checked by oz in `fetch_entity`
    ok.


%%--------------------------------------------------------------------
%% @doc
  { @link middleware_handler } callback create/1 .
%% @end
%%--------------------------------------------------------------------
-spec create(middleware:req()) -> middleware:create_result().
create(_) ->
    ?ERROR_NOT_SUPPORTED.


%%--------------------------------------------------------------------
%% @doc
  { @link middleware_handler } callback get/2 .
%% @end
%%--------------------------------------------------------------------
-spec get(middleware:req(), middleware:entity()) -> middleware:get_result().
get(#op_req{gri = #gri{aspect = instance, scope = private}}, AtmWorkflowSchema) ->
    {ok, AtmWorkflowSchema}.


%%--------------------------------------------------------------------
%% @doc
%% {@link middleware_handler} callback update/1.
%% @end
%%--------------------------------------------------------------------
-spec update(middleware:req()) -> middleware:update_result().
update(_) ->
    ?ERROR_NOT_SUPPORTED.


%%--------------------------------------------------------------------
%% @doc
%% {@link middleware_handler} callback delete/1.
%% @end
%%--------------------------------------------------------------------
-spec delete(middleware:req()) -> middleware:delete_result().
delete(_) ->
    ?ERROR_NOT_SUPPORTED.

-------------------------------------------------------------------
 @end
-------------------------------------------------------------------
 @doc
 This module handles middleware operations (create, get, update, delete)
 corresponding to automation workflow schemas.
 @end
-------------------------------------------------------------------
 middleware_router callbacks
 middleware_handler callbacks
===================================================================
 middleware_router callbacks
===================================================================
--------------------------------------------------------------------
 @doc
 {@link middleware_router} callback resolve_handler/3.
 @end
--------------------------------------------------------------------
===================================================================
 middleware_handler callbacks
===================================================================
--------------------------------------------------------------------
 @doc
 {@link middleware_handler} callback data_spec/1.
 @end
--------------------------------------------------------------------
--------------------------------------------------------------------
 @doc
 {@link middleware_handler} callback fetch_entity/1.

 For now fetches only records for authorized users.
 @end
--------------------------------------------------------------------
--------------------------------------------------------------------
 @doc
 {@link middleware_handler} callback authorize/2.
 @end
--------------------------------------------------------------------
 authorization was checked by oz in `fetch_entity`
--------------------------------------------------------------------
 @doc
 {@link middleware_handler} callback validate/2.
 @end
--------------------------------------------------------------------
 validation was checked by oz in `fetch_entity`
--------------------------------------------------------------------
 @doc
 @end
--------------------------------------------------------------------
--------------------------------------------------------------------
 @doc
 @end
--------------------------------------------------------------------
--------------------------------------------------------------------
 @doc
 {@link middleware_handler} callback update/1.
 @end
--------------------------------------------------------------------
--------------------------------------------------------------------
 @doc
 {@link middleware_handler} callback delete/1.
 @end
--------------------------------------------------------------------
  @author  
   ( C ) 2021 ACK CYFRONET AGH
  This software is released under the MIT license
  cited in ' LICENSE.txt ' .
-module(atm_workflow_schema_middleware_plugin).
-author("Bartosz Walkowicz").

-behaviour(middleware_router).
-behaviour(middleware_handler).

-include("middleware/middleware.hrl").
-include_lib("ctool/include/errors.hrl").
-include_lib("ctool/include/logging.hrl").
-include_lib("ctool/include/privileges.hrl").

-export([resolve_handler/3]).

-export([data_spec/1, fetch_entity/1, authorize/2, validate/2]).
-export([create/1, get/2, update/1, delete/1]).




-spec resolve_handler(middleware:operation(), gri:aspect(), middleware:scope()) ->
    module() | no_return().
resolve_handler(get, instance, private) -> ?MODULE;

resolve_handler(_, _, _) -> throw(?ERROR_NOT_SUPPORTED).




-spec data_spec(middleware:req()) -> undefined | middleware_sanitizer:data_spec().
data_spec(#op_req{operation = get, gri = #gri{aspect = instance}}) ->
    undefined.


-spec fetch_entity(middleware:req()) ->
    {ok, middleware:versioned_entity()} | errors:error().
fetch_entity(#op_req{auth = ?NOBODY}) ->
    ?ERROR_UNAUTHORIZED;

fetch_entity(#op_req{auth = Auth, gri = #gri{id = AtmWorkflowSchemaId, scope = private}}) ->
    case atm_workflow_schema_logic:get(Auth#auth.session_id, AtmWorkflowSchemaId) of
        {ok, #document{value = AtmWorkflowSchema}} ->
            {ok, {AtmWorkflowSchema, 1}};
        {error, _} = Error ->
            Error
    end.


-spec authorize(middleware:req(), middleware:entity()) -> boolean().
authorize(#op_req{auth = ?GUEST}, _) ->
    false;

authorize(#op_req{operation = get, gri = #gri{aspect = instance}}, _) ->
    true.


-spec validate(middleware:req(), middleware:entity()) -> ok | no_return().
validate(#op_req{operation = get, gri = #gri{aspect = instance}}, _) ->
    ok.


  { @link middleware_handler } callback create/1 .
-spec create(middleware:req()) -> middleware:create_result().
create(_) ->
    ?ERROR_NOT_SUPPORTED.


  { @link middleware_handler } callback get/2 .
-spec get(middleware:req(), middleware:entity()) -> middleware:get_result().
get(#op_req{gri = #gri{aspect = instance, scope = private}}, AtmWorkflowSchema) ->
    {ok, AtmWorkflowSchema}.


-spec update(middleware:req()) -> middleware:update_result().
update(_) ->
    ?ERROR_NOT_SUPPORTED.


-spec delete(middleware:req()) -> middleware:delete_result().
delete(_) ->
    ?ERROR_NOT_SUPPORTED.
