// File: /workspace/github_cpp_makefile_star2_O2/linuxnoodle[P]typer/main.cpp
// Function: main
int main(){
    // Clears screen when first ran.
    #ifdef _WIN32
        system("cls");
    #else
        cout << "\x1B[2J"; 
        cout << "\x1B[0;0H";
    #endif

    cout << "Enter the amount of words you want to type: (type \"quotes\" for quotes)\n";
    string s = "bruh";
    
    // Makes sure user input is valid.
    while (s != "quotes" && (!(s.find_first_not_of("0123456789") == string::npos) || s == "0")){
        #ifdef _WIN32
            cout << "Please enter a positive non-zero integer.\n";
        #else
            cout << "\033[0;32mPlease enter a positive non-zero integer.\033[0m\n";
        #endif
        getline(cin, s, '\n');
    }

    ifstream wordsFile;
    
    #ifdef _WIN32
        char *path = getenv("appdata");
        if (s == "quotes"){
            strcat(path, "\\quotes.txt"); 
        } else {
            strcat(getenv("appdata"), "\\words.txt"); 
        }   
    #else
        struct passwd *pw = getpwuid(getuid());
        char *path = pw->pw_dir;
        if (s == "quotes"){
            strcat(path, "/.local/share/quotes.txt");
        } else {
            strcat(path, "/.local/share/words.txt");
        } 
    #endif

    // Reads file into the vector "words".
    wordsFile = ifstream(path);

    if (!wordsFile){
        if (s == "quotes"){
            wordsFile = ifstream("quotes.txt");
        } else {
            wordsFile = ifstream("words.txt");
        }
        if (!wordsFile){
            #ifdef _WIN32
                cerr << "Error: quotes and/or words file is missing. Put \"words.txt\" and \"quotes.txt\" in \%appdata\%\\Roaming\\\n";
            #else
                cerr << "Error: quotes and/or words file is missing. Put \"words.txt\" and \"quotes.txt\" in ~/.local/share/\n";
            #endif
            return -1;
        } else {
            #ifdef _WIN32
                // Moving the files in windows doesn't appear to work, but at the very least, 
                // there is no reason to move them in windows
                if (s == "quotes"){
                    MoveFile("quotes.txt", path);
                } else {
                    MoveFile("words.txt", path);
                }
            #else
                if (s == "quotes"){
                    filesystem::rename("quotes.txt", path);
                } else {
                    filesystem::rename("words.txt", path);
                }
            #endif
        }
    }
    if (wordsFile.is_open()){
        string line;
        while (getline(wordsFile, line)){
            words.push_back(line);
        }
    }
    // Initializes random distribution, as before this the bounds are not decided.
    distribution = uniform_int_distribution<mt19937::result_type>(0, words.size() - 1);

    while (true){
        // Grabs the next phrase, and loads it.
        string phrase;
        if (s == "quotes"){
            phrase = words[distribution(generator)];
        } else {
            phrase = generateString(stoi(s));
        }

        // Clears screen, then displays text in green. 
        // (\033 is the escape character, 0;32 means green.)
        #ifdef _WIN32
            system("cls");
            cout << phrase << "\n";
        #else
            cout << "\x1B[2J";
            cout << "\x1B[0;0H";
            cout << "\033[0;32m" << phrase << "\033[0m\n";
        #endif
        // Splits phrase delimited by space, and finds wordcount. (Will be used to rework new typing system)
        vector<string> splitPhrase;
        istringstream iss(phrase);
        
        string word;
        while (getline(iss, word, ' ')){
            splitPhrase.push_back(word);
        }
        
        int wordCount = splitPhrase.size();
        
        // Starts timer to calculate WPM.
        auto startTime = chrono::system_clock::now();
        
        string userInput;
        getline(cin, userInput, '\n');
        
        float timeTaken = (chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now() - startTime).count());
        
        cout << "Time taken: " << timeTaken/1000 << "s\n";
        cout << "Raw WPM: " << wordCount/(timeTaken/60000) << "wpm\n";
        
        // Calculates the amount of mistyped characters.
        // First, it checks if the size of the phrase typed and the actual phrase are the same, as if they aren't,
        // checking each character would segfault due to an out of bounds exception.
        // If it is, it adds the difference to the error count, and only check for differences up to the shorter length.
        // If it isn't, it just checks each character with the same indicies.
        
        int errors = 0;
        if (userInput.size() != phrase.size()){
            errors += abs((int)userInput.size() - (int)phrase.size());
            for (int i = 0; i <= abs((int)userInput.size() - (int)phrase.size()); ++i){
                if (phrase[i] != userInput[i]){
                    ++errors;
                }
            }
        } else {
            for (int i = 0; i < (int)phrase.size(); ++i){
                if (phrase[i] != userInput[i]){
                    ++errors;
                }
            }
        }
        
        cout << "Mistyped characters: " << errors << "\n";
        errors = 0;
        
        // Waits for one second so that the user can actually read the output.
        #ifdef _WIN32
            Sleep(1000);
        #else
            usleep(1000000);
        #endif
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x4c8, %rsp            # imm = 0x4C8
movq 0x3a2c(%rip), %rbx      # 0x5fc0
leaq 0x1a85(%rip), %rsi      # 0x4020
movq %rbx, %rdi
callq 0x21f0
leaq 0x1a7b(%rip), %rsi      # 0x4025
movq %rbx, %rdi
callq 0x21f0
leaq 0x1a73(%rip), %rsi      # 0x402c
movq %rbx, %rdi
callq 0x21f0
leaq 0x1aac(%rip), %rsi      # 0x4074
leaq 0x78(%rsp), %r14
leaq 0x2c0(%rsp), %rdx
movq %r14, %rdi
callq 0x2d20
leaq 0x1a95(%rip), %r15      # 0x4079
leaq 0x1a95(%rip), %r12      # 0x4080
leaq 0x1a9b(%rip), %rbp      # 0x408d
movq 0x39df(%rip), %r13      # 0x5fd8
pushq $0xa
popq %rbx
movq %r14, %rdi
movq %r15, %rsi
callq 0x2d5b
testb %al, %al
je 0x264f
movq %r14, %rdi
movq %r12, %rsi
xorl %edx, %edx
callq 0x2140
cmpq $-0x1, %rax
jne 0x2631
movq %r14, %rdi
leaq 0x1a63(%rip), %rsi      # 0x408b
callq 0x2d65
testb %al, %al
je 0x264f
movq 0x3988(%rip), %rdi      # 0x5fc0
movq %rbp, %rsi
callq 0x21f0
movq %r13, %rdi
movq %r14, %rsi
movl %ebx, %edx
callq 0x2320
jmp 0x25fc
leaq 0x2c0(%rsp), %rdi
callq 0x2220
callq 0x2110
movl %eax, %edi
callq 0x2230
movq 0x20(%rax), %rax
movq %rax, 0x30(%rsp)
leaq 0x1a01(%rip), %rsi      # 0x4079
leaq 0x78(%rsp), %rdi
callq 0x2d65
movl %eax, %ebp
movq 0x30(%rsp), %rbx
movq %rbx, %rdi
callq 0x20e0
addq %rbx, %rax
testb %bpl, %bpl
je 0x26b0
movups 0x1a2c(%rip), %xmm0     # 0x40cc
movups %xmm0, 0x9(%rax)
movups 0x1a18(%rip), %xmm0     # 0x40c3
movups %xmm0, (%rax)
jmp 0x26c8
movups 0x1a25(%rip), %xmm0     # 0x40dc
movups %xmm0, (%rax)
movabsq $0x7478742e736472, %rcx # imm = 0x7478742E736472
movq %rcx, 0x10(%rax)
leaq 0xb8(%rsp), %rdi
pushq $0x8
popq %rdx
movq %rbx, %rsi
callq 0x2310
leaq 0x2c0(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0x22b0
leaq 0xb8(%rsp), %rdi
callq 0x2070
movq 0x2c0(%rsp), %rax
movq -0x18(%rax), %rax
testb $0x5, 0x2e0(%rsp,%rax)
je 0x288c
leaq 0x195b(%rip), %rsi      # 0x4079
leaq 0x78(%rsp), %rdi
callq 0x2d65
testb %al, %al
je 0x275a
leaq 0x199e(%rip), %rsi      # 0x40d1
leaq 0xb8(%rsp), %rdi
pushq $0x8
popq %rdx
callq 0x2310
leaq 0x2c0(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0x22b0
jmp 0x2786
leaq 0x1989(%rip), %rsi      # 0x40ea
leaq 0xb8(%rsp), %rdi
pushq $0x8
popq %rdx
callq 0x2310
leaq 0x2c0(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0x22b0
leaq 0xb8(%rsp), %rdi
callq 0x2070
movq 0x2c0(%rsp), %rax
movq -0x18(%rax), %rax
testb $0x5, 0x2e0(%rsp,%rax)
je 0x27e8
movq 0x3840(%rip), %rdi      # 0x5ff0
leaq 0x193d(%rip), %rsi      # 0x40f4
callq 0x21f0
leaq 0x2c0(%rsp), %rdi
callq 0x2070
leaq 0x78(%rsp), %rdi
callq 0x20f0
pushq $-0x1
popq %rax
addq $0x4c8, %rsp            # imm = 0x4C8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x188a(%rip), %rsi      # 0x4079
leaq 0x78(%rsp), %rdi
callq 0x2d65
testb %al, %al
je 0x283a
leaq 0x18cd(%rip), %rsi      # 0x40d1
leaq 0xb8(%rsp), %rdi
pushq $0x2
popq %rdx
callq 0x2d72
leaq 0x8(%rsp), %rdi
leaq 0x30(%rsp), %rsi
pushq $0x2
popq %rdx
callq 0x2dde
leaq 0xb8(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x2160
jmp 0x2875
leaq 0x18a9(%rip), %rsi      # 0x40ea
leaq 0xb8(%rsp), %rdi
pushq $0x2
popq %rdx
callq 0x2e60
leaq 0x8(%rsp), %rdi
leaq 0x30(%rsp), %rsi
pushq $0x2
popq %rdx
callq 0x2dde
leaq 0xb8(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x2160
leaq 0x8(%rsp), %rdi
callq 0x2e4a
leaq 0xb8(%rsp), %rdi
callq 0x2e4a
leaq 0x338(%rsp), %rdi
callq 0x2060
testb %al, %al
je 0x28fb
leaq 0xc8(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb $0x0, (%rax)
leaq 0x2c0(%rsp), %rbx
leaq 0xb8(%rsp), %r14
leaq 0x3908(%rip), %r15      # 0x61d0
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2050
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
testb $0x5, 0x20(%rax,%rcx)
jne 0x28ee
movq %r15, %rdi
movq %r14, %rsi
callq 0x2ecc
jmp 0x28c8
leaq 0xb8(%rsp), %rdi
callq 0x20f0
movq 0x38d6(%rip), %rax      # 0x61d8
subq 0x38c7(%rip), %rax      # 0x61d0
sarq $0x5, %rax
decq %rax
andq $0x0, 0x4c58(%rip)      # 0x7570
movq %rax, 0x4c59(%rip)      # 0x7578
movq 0x369a(%rip), %rbp      # 0x5fc0
leaq 0xb8(%rsp), %r12
leaq 0x98(%rsp), %r15
pushq $0x20
popq %rbx
leaq 0x60(%rsp), %r14
leaq 0x18(%rsp), %rax
movq %rax, 0x8(%rsp)
andq $0x0, 0x10(%rsp)
movb $0x0, 0x18(%rsp)
leaq 0x78(%rsp), %r13
movq %r13, %rdi
leaq 0x1717(%rip), %rsi      # 0x4079
callq 0x2d65
testb %al, %al
je 0x2998
leaq 0x4bfe(%rip), %rdi      # 0x7570
leaq 0x386f(%rip), %rsi      # 0x61e8
callq 0x2d18
shlq $0x5, %rax
addq 0x3847(%rip), %rax      # 0x61d0
leaq 0x8(%rsp), %rdi
movq %rax, %rsi
callq 0x2130
jmp 0x29c4
movq %r13, %rdi
xorl %esi, %esi
pushq $0xa
popq %rdx
callq 0x2ef8
movq %r12, %rdi
movl %eax, %esi
callq 0x24dc
leaq 0x8(%rsp), %rdi
movq %r12, %rsi
callq 0x2240
movq %r12, %rdi
callq 0x20f0
movq %rbp, %rdi
leaq 0x1652(%rip), %rsi      # 0x4020
callq 0x21f0
movq %rbp, %rdi
leaq 0x1648(%rip), %rsi      # 0x4025
callq 0x21f0
movq %rbp, %rdi
leaq 0x1769(%rip), %rsi      # 0x4155
callq 0x21f0
movq %rax, %rdi
leaq 0x8(%rsp), %rsi
callq 0x21d0
movq %rax, %rdi
leaq 0x16b5(%rip), %rsi      # 0x40bd
callq 0x21f0
xorps %xmm0, %xmm0
movaps %xmm0, 0x60(%rsp)
andq $0x0, 0x70(%rsp)
movq %r12, %rdi
leaq 0x8(%rsp), %rsi
pushq $0x8
popq %rdx
callq 0x22d0
leaq 0xa8(%rsp), %rax
movq %rax, 0x98(%rsp)
andq $0x0, 0xa0(%rsp)
movb $0x0, 0xa8(%rsp)
movq %r12, %rdi
movq %r15, %rsi
movl %ebx, %edx
callq 0x2320
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
testb $0x5, 0x20(%rax,%rcx)
jne 0x2a74
movq %r14, %rdi
movq %r15, %rsi
callq 0x2ecc
jmp 0x2a4c
movq %rbp, %rbx
movq 0x68(%rsp), %rbp
subq 0x60(%rsp), %rbp
callq 0x2040
movq %rax, %r13
leaq 0x50(%rsp), %rax
movq %rax, 0x40(%rsp)
andq $0x0, 0x48(%rsp)
movb $0x0, 0x50(%rsp)
movq 0x3533(%rip), %rdi      # 0x5fd8
leaq 0x40(%rsp), %rsi
pushq $0xa
popq %rdx
callq 0x2320
callq 0x2040
subq %r13, %rax
cqto
movl $0xf4240, %ecx          # imm = 0xF4240
idivq %rcx
movq %rax, %r13
movq %rbx, %rdi
leaq 0x168c(%rip), %rsi      # 0x415d
callq 0x21f0
cvtsi2ss %r13, %xmm0
movss %xmm0, 0x3c(%rsp)
divss 0x151b(%rip), %xmm0     # 0x4004
movq %rax, %rdi
callq 0x2180
movq %rax, %rdi
leaq 0x166f(%rip), %rsi      # 0x416a
callq 0x21f0
movq %rbx, %rdi
leaq 0x1663(%rip), %rsi      # 0x416d
callq 0x21f0
shrq $0x5, %rbp
cvtsi2ss %ebp, %xmm0
movss 0x3c(%rsp), %xmm1
divss 0x14e3(%rip), %xmm1     # 0x4008
divss %xmm1, %xmm0
movq %rax, %rdi
callq 0x2180
movq %rax, %rdi
leaq 0x163c(%rip), %rsi      # 0x4177
callq 0x21f0
movq 0x48(%rsp), %rax
movq 0x10(%rsp), %rcx
cmpq %rcx, %rax
jne 0x2b85
movq 0x8(%rsp), %rcx
movq 0x40(%rsp), %rdx
xorl %esi, %esi
testl %eax, %eax
cmovlel %esi, %eax
xorl %r13d, %r13d
movq %rbx, %rbp
pushq $0x20
popq %rbx
cmpq %rsi, %rax
je 0x2bc3
movb (%rcx,%rsi), %dil
xorl %r8d, %r8d
cmpb (%rdx,%rsi), %dil
setne %r8b
addl %r8d, %r13d
incq %rsi
jmp 0x2b69
subl %ecx, %eax
movl %eax, %r13d
negl %r13d
cmovsl %eax, %r13d
movq 0x8(%rsp), %rax
movq 0x40(%rsp), %rcx
leal 0x1(%r13), %edx
xorl %esi, %esi
movq %rbx, %rbp
pushq $0x20
popq %rbx
cmpq %rsi, %rdx
je 0x2bc3
movb (%rax,%rsi), %dil
xorl %r8d, %r8d
cmpb (%rcx,%rsi), %dil
setne %r8b
addl %r8d, %r13d
incq %rsi
jmp 0x2ba7
movq %rbp, %rdi
leaq 0x15af(%rip), %rsi      # 0x417c
callq 0x21f0
movq %rax, %rdi
movl %r13d, %esi
callq 0x22e0
movq %rax, %rdi
leaq 0x148b(%rip), %rsi      # 0x4072
callq 0x21f0
movl $0xf4240, %edi          # imm = 0xF4240
callq 0x2270
leaq 0x40(%rsp), %rdi
callq 0x20f0
movq %r15, %rdi
callq 0x20f0
movq %r12, %rdi
callq 0x2100
movq %r14, %rdi
callq 0x2cf6
leaq 0x8(%rsp), %rdi
callq 0x20f0
jmp 0x293e
jmp 0x2c32
movq %rax, %rbx
jmp 0x2ca1
jmp 0x2c41
jmp 0x2c32
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x20f0
jmp 0x2c87
movq %rax, %rbx
jmp 0x2cab
jmp 0x2c48
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
callq 0x2e4a
jmp 0x2c5c
jmp 0x2c59
movq %rax, %rbx
leaq 0xb8(%rsp), %rdi
callq 0x2e4a
jmp 0x2cd0
jmp 0x2ccd
jmp 0x2ccd
movq %rax, %rbx
leaq 0xb8(%rsp), %rdi
jmp 0x2cb0
jmp 0x2cb9
jmp 0x2cb9
jmp 0x2ccd
jmp 0x2ccd
movq %rax, %rbx
leaq 0x98(%rsp), %rdi
callq 0x20f0
leaq 0xb8(%rsp), %rdi
callq 0x2100
leaq 0x60(%rsp), %rdi
callq 0x2cf6
leaq 0x8(%rsp), %rdi
callq 0x20f0
jmp 0x2cd0
jmp 0x2ccd
movq %rax, %rbx
leaq 0xb8(%rsp), %rdi
callq 0x2070
jmp 0x2cd0
jmp 0x2ccd
movq %rax, %rbx
leaq 0x2c0(%rsp), %rdi
callq 0x2070
jmp 0x2ce4
jmp 0x2ce1
movq %rax, %rbx
leaq 0x78(%rsp), %rdi
callq 0x20f0
movq %rbx, %rdi
callq 0x22f0