#include <chrono>
#include <fstream>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>

#include "sqlite3.h"

static int callback(void *NotUsed, int argc, char **argv, char **azColName){
    int i;
    for(i=0; i<argc; i++){
        printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
    }
    printf("\n");
    return 0;
}

int main(int argc, char **argv){
    sqlite3 *db;
    char *zErrMsg = 0;
    int rc;


    bool run = true;
	bool movies_loaded = false;
	bool fill_loaded = false;
	bool mixed_loaded = false;

    rc = sqlite3_open(argv[1], &db);
    if( rc ){
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        return(1);
    }

    while(run)
    {
        std::string input;
        std::cout << "Insert command please" << std::endl;
        std::getline(std::cin,input);

        //std::cout << input << std::endl;

        
        if(input == "exit" || input == "quit")
        {
            run = false;
        }
        else if(input == "load movies" && !movies_loaded)
        {
            std::cout << "Loading movies" << std::endl;
            std::ifstream moviesfile;
            moviesfile.open("movies.txt");
            std::string instruction;

            while (std::getline(moviesfile, instruction))
            {
                //std::cout << instruction << std::endl;
                char *instructionchars = new char[instruction.length() + 1];
                strcpy(instructionchars, instruction.c_str());



                rc = sqlite3_exec(db, instructionchars, callback, 0, &zErrMsg);
                if( rc!=SQLITE_OK ){
                    fprintf(stderr, "SQL error: %s\n", zErrMsg);
                    sqlite3_free(zErrMsg);
                }
                delete[](instructionchars);
            }
            movies_loaded = true;
            std::cout << "Done" << std::endl;
        }
        else if( input == "load fill" && !fill_loaded ) {
            std::ifstream is("fill.txt");
            std::string line;
            std::vector<char*> instructions;
            while (getline(is,line)) {
                char *linechars = new char[line.length() + 1];
                strcpy(linechars, line.c_str());
                instructions.emplace_back(linechars);
                //delete[](linechars);
            }
            std::cout << "Loading fill file..." << std::endl;
            std::chrono::time_point<std::chrono::high_resolution_clock> start;
            start = std::chrono::high_resolution_clock::now();
            for( char* instr : instructions) {
                rc = sqlite3_exec(db, instr, callback, 0, &zErrMsg);
                if( rc!=SQLITE_OK ){
                    fprintf(stderr, "SQL error: %s\n", zErrMsg);
                    sqlite3_free(zErrMsg);
                }
            }
            fill_loaded = true;
            auto end = std::chrono::high_resolution_clock::now();
            std::chrono::duration<double> diff = end - start;
            std::cout << "done, fill file loaded in " << diff.count() * 1000 << "ms" << std::endl;
        }
        // lädt anderes einkompiliertes File zeilenweise
        else if( input == "load mixed" && !mixed_loaded ) {
            std::ifstream is("mixed.txt");
            std::string line;
            std::vector<char*> instructions;
            while (getline(is,line)) {
                char *linechars = new char[line.length() + 1];
                strcpy(linechars, line.c_str());
                instructions.emplace_back(linechars);
            }
            std::cout << "Loading mixed file..." << std::endl;
            std::chrono::time_point<std::chrono::high_resolution_clock> start;
            start = std::chrono::high_resolution_clock::now();
            for( char* instr : instructions) {
                rc = sqlite3_exec(db, instr, callback, 0, &zErrMsg);
                if( rc!=SQLITE_OK ){
                    fprintf(stderr, "SQL error: %s\n", zErrMsg);
                    sqlite3_free(zErrMsg);
                }
            }
            mixed_loaded = true;
            auto end = std::chrono::high_resolution_clock::now();
            std::chrono::duration<double> diff = end - start;
            std::cout << "done, mixed file loaded in " << diff.count() * 1000 << "ms" << std::endl;
        }

        else
        {
            std::cout << "Executing input" << std::endl;
            char *inputchars = new char[input.length() + 1];
            strcpy(inputchars, input.c_str());
            rc = sqlite3_exec(db, inputchars, callback, 0, &zErrMsg);
            if( rc!=SQLITE_OK ){
                fprintf(stderr, "SQL error: %s\n", zErrMsg);
                sqlite3_free(zErrMsg);
            }
            delete[](inputchars);
        }
    }
    sqlite3_close(db);
    return 0;
}
