%% Copyright 2015 Kolab Systems AG (http://www.kolabsys.com)
%%
%% Aaron Seigo (Kolab Systems) <seigo a kolabsys.com>
%%
%% This program is free software: you can redistribute it and/or modify
%% it under the terms of the GNU General Public License as published by
%% the Free Software Foundation, either version 3 of the License, or
%% (at your option) any later version.
%%
%% This program is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%% GNU General Public License for more details.
%%
%% You should have received a copy of the GNU General Public License
%% along with this program.  If not, see <http://www.gnu.org/licenses/>.

-module(kolab_guam_rule_audit_SUITE).

% easier than exporting by name
-compile(export_all).

% required for common_test to work
-include_lib("common_test/include/ct.hrl").
-include("../src/rules/kolab_guam_rule_audit.hrl").

%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% common test callbacks %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Specify a list of all unit test functions
all() -> [
          kolab_guam_rule_audit_test
         ].

% required, but can just return Config. this is a suite level setup function.
init_per_suite(Config) ->
        Config.

% required, but can just return Config. this is a suite level tear down function.
end_per_suite(Config) ->
        Config.

% optional, can do function level setup for all functions,
% or for individual functions by matching on TestCase.
init_per_testcase(_TestCase, Config) ->
        Config.

% optional, can do function level tear down for all functions,
% or for individual functions by matching on TestCase.
end_per_testcase(_TestCase, Config) ->
        Config.

kolab_guam_rule_audit_test(_TestConfig) ->
    %% Data to be fed into the test, one tuple per iteration
    %% Tuple format: { client_data, server_data, LoginAttemptSucceeded }
    Data = [
        {
            [<<"a001 LOGIN test1@kolab.org SESAME\r\n">>],
            <<"a001 OK LOGIN completed">>,
            true
        },
        {
            [<<"a001 LOGIN test1@kolab.org SESAME\r\n">>],
            <<"a001 NO LOGIN completed">>,
            false
        },
        {
            [<<"a001 LOGIN test1@kolab.org SESAME\r\n">>],
            <<"a001 BAD LOGIN completed">>,
            false
        },
        {
            [<<"a001 AUTHENTICATE LOGIN\r\n">>,
            <<"dGVzdDFAa29sYWIub3Jn\r\n">>,
            <<"V2VsY29tZTJLb2xhYlN5c3RlbXM=\r\n">>],
            <<"a001 BAD LOGIN completed">>,
            false
        },
        {
            [<<"a001 AUTHENTICATE LOGIN\r\n">>,
            <<"dGVzdDFAa29sYWIub3Jn\r\n">>,
            <<"V2VsY29tZTJLb2xhYlN5c3RlbXM=\r\n">>],
            <<"a001 OK LOGIN completed">>,
            true
        },
        % Thunderbird with the authenticate plain mechanism
        {
            [<<"1 authenticate PLAIN\r\n">>,
            <<"AHRlc3QxQGtvbGFiLm9yZwBXZWxjb21lMktvbGFiU3lzdGVtcw==\r\n">>],
            <<"1 OK LOGIN completed">>,
            true
        }
    ],

    lager:start(),
    lager:set_loglevel(lager_console_backend, debug),

    %% setup boilerplate
    Config = {},
    State = kolab_guam_rule_audit:new(Config),
    ServerConfig = kolab_guam_sup:default_imap_server_config(),
    { ok, ImapSession } = eimap:start_link(ServerConfig),

    %% run the dataset through the rule
    lists:foreach(
        fun({ ClientDataList, ServerData, LoginAttemptSucceeded }) ->
            ReadyState = lists:foldl(fun(ClientData, State) ->
                Split = eimap_utils:split_command_into_components(ClientData),
                { _, ReadyState } = kolab_guam_rule_audit:apply_to_client_message(ImapSession, ClientData, Split, State),
                ReadyState
            end, State, ClientDataList),
            { _Filtered, NewState } = kolab_guam_rule_audit:apply_to_server_message(ImapSession, ServerData, ReadyState),
            lager:info("Result ~p", [NewState]),
            #state{ username = <<"test1@kolab.org">> } = NewState
            % true = false
        end,
    Data).
