/**
 * @file mxs1073_binlog_enc.cpp Test binlog router setup with binlogs encryption
 * - configure binlog router with follwoing options
 @verbatim
 encrypt_binlog=1,encryption_key_file=/etc/mariadb_binlog_keys.txt,encryption_algorithm=aes_cbc
 @endverbatim
 * - put some date to Master
 * - check that all slave have the same data
 * - 'maxbinlogcheck' against Maxscale binlog file
 * - check 'maxbinlogcheck' output for lack of errors and presence of 'Decrypting binlog file with algorithm' message
 * - try remote access to Maxscale binlog with 'mysqlbinlog'
 * - copy Maxscale binlogs to Master and check output of 'show binary logs' before and after copying
 * (expect same file name and size, but different checksums)
 */


#include <iostream>
#include <stdio.h>
#include "testconnections.h"
#include "test_binlog_fnc.h"

/**
 * @brief get_first_binlog_file Get name, size and checksum of first binlog file from 'show binary logs' output list
 * @param Test TestConnections object
 * @param name string for file name
 * @param size variable for file size
 * @param checksum Pointer to checksum string
 * @return 0 in case of success
 */
int get_first_binlog_file(TestConnections * Test, char * name, long long unsigned *size, char ** checksum)
{
    char size_str[64];
    char cmd[256];
    int res = 0;
    int exit_code;
    res  = find_field(Test->repl->nodes[0], (char *) "SHOW BINARY LOGS", (char *) "Log_name", name);
    res += find_field(Test->repl->nodes[0], (char *) "SHOW BINARY LOGS", (char *) "File_size", size_str);

    sscanf(size_str, "%llu", size);
    sprintf(cmd, "sha1sum /var/lib/mysql/%s | cut -f 1 -d \" \"", name);

    *checksum = Test->repl->ssh_node_output(0, cmd, true, &exit_code);
    if (exit_code != 0)
    {
        res++;
    }

    Test->tprintf("First master binlog file:\nname: '%s'\nsize: %llu\nchecksum: %s\n",
                  name,
                  *size,
                  *checksum
                 );

    return res;
}

int main(int argc, char *argv[])
{

    printf("ERROR!ERROR!ERROR!ERROR!ERROR!ERROR!ERROR!ERROR!ERROR!ERROR!\n"
           "ERROR!                                                ERROR!\n"
           "ERROR!  This test require file key management plugin! ERROR!\n"
           "ERROR!                                                ERROR!\n"
           "ERROR!ERROR!ERROR!ERROR!ERROR!ERROR!ERROR!ERROR!ERROR!ERROR!\n");
    return 1;


    TestConnections * Test = new TestConnections(argc, argv);
    Test->set_timeout(1000);
    char str1[1024];
    char str2[1024];
    char * alg;
    char * alg1 = (char *) "aes_cbc";
    char * alg2 = (char *) "aes_ctr";

    Test->tprintf("%s %s\n", Test->test_name, argv[1]);

    if (strcmp(Test->test_name, "mxs1073_binlog_enc_aes_ctr") == 0)
    {
        alg = alg2;
    }
    else
    {
        alg = alg1;
    }

    int i;

    Test->repl->connect();
    Test->try_query(Test->repl->nodes[0], (char *) "DROP TABLE IF EXISTS t1");


    Test->tprintf("Coping encription config .cnf files to all nodes \n");
    sprintf(str1, "%s/binlog_enc_%s.cnf", Test->test_dir, alg);
    sprintf(str2, "%s/mariadb_binlog_keys.txt", Test->test_dir);
    for (i = 0; i < Test->repl->N; i++)
    {
        Test->repl->copy_to_node(str1, (char *) "~/", i);
        Test->repl->ssh_node(i, (char *) "cp ~/binlog_enc*.cnf /etc/my.cnf.d/", true);

        Test->repl->copy_to_node(str2, (char *) "~/", i);
        Test->repl->ssh_node(i, (char *) "cp ~/mariadb_binlog_keys.txt /etc/", true);
    }

    Test->maxscales->copy_to_node(str2, (char *) "~/", 0);
    Test->maxscales->ssh_node_f(0, true, "cp ~/mariadb_binlog_keys.txt /etc/");

    Test->start_binlog();

    Test->repl->connect();

    Test->tprintf("Put some data to DB\n");
    Test->set_timeout(100);
    create_t1(Test->repl->nodes[0]);
    Test->add_result(insert_into_t1(Test->repl->nodes[0], 4), "Data inserting to t1 failed\n");
    Test->stop_timeout();
    Test->tprintf("Sleeping to let replication happen\n");
    sleep(60);

    for (i = 0; i < Test->repl->N; i++)
    {
        Test->tprintf("Checking data from node %d (%s)\n", i, Test->repl->IP[i]);
        Test->set_timeout(100);
        Test->add_result(select_from_t1(Test->repl->nodes[i], 4), "Selecting from t1 failed\n");
        Test->stop_timeout();
    }

    Test->tprintf("Flush logs\n");
    execute_query(Test->repl->nodes[0], (char *) "FLUSH LOGS");

    Test->tprintf("Running 'maxbinlogcheck' against Maxscale binlog file\n");
    char * maxscale_binlogcheck_output = Test->maxscales->ssh_node_f(0, true,
                                         "maxbinlogcheck -M -K /etc/mariadb_binlog_keys.txt -H /var/lib/maxscale/Binlog_Service/mar-bin.000001 --aes_algo=%s 2> 1",
                                         alg);
    //puts(maxscale_binlogcheck_output);
    if (strstr(maxscale_binlogcheck_output, "error") != NULL)
    {
        Test->add_result(1, "Errors in the maxbinlogcheck output:\n%s\n", maxscale_binlogcheck_output);
    }

    sprintf(str1, "Decrypting binlog file with algorithm: %s", alg);
    if (strstr(maxscale_binlogcheck_output, str1) == NULL)
    {
        Test->add_result(1, "No '%s' in the maxbinlogcheck output:\n%s\n", str1, maxscale_binlogcheck_output);
    }

    sprintf(str1,
            "mysqlbinlog -R -h %s -P %d -u%s -p%s mar-bin.000001 --stop-position=60000",
            Test->maxscales->IP[0], Test->maxscales->binlog_port[0], Test->maxscales->user_name, Test->maxscales->password);
    Test->tprintf("running mysqlbinlog on node_000 to connecto Maxscale: %s\n", str1);
    int exit_code;
    char * mysql_binlog_connect_output = Test->repl->ssh_node_output(0, str1, false, &exit_code);
    Test->add_result(exit_code, "Remote access to Maxscale binlog failed");
    sprintf(str1, "LOGS/%s/mysql_binlog_connect_output", Test->test_name);
    FILE *f = fopen(str1, "wt");
    fprintf(f, "%s", mysql_binlog_connect_output);
    fclose(f);

    Test->tprintf("Checking binlog files on master\n");
    long long unsigned size_before;
    long long unsigned size_after;
    long long unsigned size_after_restart;
    char * checksum_before;
    char * checksum_after;
    char * checksum_after_restart;
    char name_before[256];
    char name_after[256];
    char name_after_restart[256];

    Test->add_result(get_first_binlog_file(Test, name_before, &size_before, &checksum_before),
                     "Error getting binlog name and size\n");

    Test->tprintf("Copying binlogs from Maxscale to Master\n");
    system("rm -rf binlogs");
    system("mkdir binlogs");
    Test->maxscales->copy_from_node((char *) "/var/lib/maxscale/Binlog_Service/*", (char *) "binlogs/", 0);
    Test->repl->ssh_node(0, "rm -rf binlogs", true);
    Test->repl->copy_to_node("-r binlogs", "./", 0);
    Test->repl->ssh_node(0, "chown mysql:mysql binlogs/*", true);


    //Test->repl->ssh_node(0, "rm /var/lib/mysql/mar-bin*", true);
    Test->repl->ssh_node(0, "cp binlogs/* /var/lib/mysql/", true);
    sleep(5);
    Test->tprintf("Checking binlog files on master after copying binlogs from Maxscale\n");
    Test->add_result(get_first_binlog_file(Test, name_after, &size_after, &checksum_after),
                     "Error getting binlog name and size\n");

    Test->repl->close_connections();

    if (size_before != size_after)
    {
        Test->add_result(1, "Master binlog file size after copying Maxscale binlogs to Master is different\n");
    }
    if (strcmp(name_before, name_after) != 0)
    {
        Test->add_result(1, "Master binlog file name after copying Maxscale binlogs to Master is different\n");
    }
    if (strcmp(checksum_before, checksum_after) == 0)
    {
        Test->add_result(1,
                         "Master binlog file checksum after copying Maxscale binlogs to Master is the same. Probably binlog copying error different\n");
    }

    Test->repl->stop_node(0);
    Test->repl->start_node(0, (char *) "");
    sleep(5);

    Test->tprintf("Checking binlog files on master after copying binlogs from Maxscale and Master restart\n");
    Test->repl->connect();
    Test->add_result(get_first_binlog_file(Test, name_after_restart, &size_after_restart,
                                           &checksum_after_restart),
                     "Error getting binlog name and size\n");
    Test->repl->close_connections();

    if (size_before != size_after_restart)
    {
        Test->add_result(1,
                         "Master binlog file size after copying Maxscale binlogs to Master and restart is different\n");
    }
    if (strcmp(name_before, name_after_restart) != 0)
    {
        Test->add_result(1,
                         "Master binlog file name after copying Maxscale binlogs to Master and restart is different\n");
    }
    if (strcmp(checksum_after_restart, checksum_after) != 0)
    {
        Test->add_result(1, "Master binlog file checksum after Master restart is different\n");
    }


    // clean up
    Test->tprintf("Cleaning up nodes and restart replication\n");
    Test->repl->stop_nodes();
    for (i = 0; i < Test->repl->N; i++)
    {
        Test->repl->ssh_node(i, (char *) "rm  /etc/my.cnf.d/binlog_enc*.cnf", true);
        Test->repl->ssh_node(i, (char *) "rm  /etc/mariadb_binlog_keys.txt", true);
    }
    Test->repl->start_replication();



    int rval = Test->global_result;
    delete Test;
    return rval;
}
