// File: /workspace/github_cpp_makefile_star2_O3/Dwijesh522[P]DBMS_assignment_3/linear_search.cpp
// Function: main
int main(int argc, char **argv) {
    updateFilePaths(argc, argv);
    int integers_per_page = PAGE_CONTENT_SIZE / sizeof(int);
    FileManager fm;
    FileHandler output_handler = fm.CreateFile(output_file_path);
    FileHandler input_handler = fm.OpenFile(input_file_path);
    // by default following page is pinned and marked dirty
    PageHandler output_page_handler = output_handler.NewPage();
    int integers_written_on_output_page = 0;
    // reading query files
    ifstream query_file (query_file_path);
    if (query_file.is_open()) {
        string line;
        int counter = 0; // even counter for backward traversal, odd counter for forward traversal
        int input_last_page_number = getLastPageNumber(input_handler, /*keep pinned*/true);
        while (getline(query_file, line)) {
            int target_number = getSearchValue(line); // value to search for

            // since the input file is sorted, once processed all target values,
            // we need not process the remaining values
            bool found_it = false, query_processed = false;

            // Looping from last page to first page
            try {
                PageHandler curr_page_handler;
                if (counter %2 == 0) curr_page_handler = getLastPageHandler(input_handler, /*keep_pinned*/true);
                else curr_page_handler = getFirstPageHandler(input_handler, /*keep_pinned*/true);
                while (true) {
                    char *data = curr_page_handler.GetData();
                    if (data == nullptr) throw "EmptyFileException: Input file no pages\n";
                    for (int i=sizeof(int)*(integers_per_page-1); i>= 0; i-= sizeof(int)) {
                        // traversing from the last entry of the page to first entry
                        int curr_number;
                        memcpy(&curr_number, &data[i], sizeof(int));
                        if (curr_number == target_number) {
                            found_it = true;
                            // store (page num, offset) into the output file page
                            int curr_page_number = curr_page_handler.GetPageNum();
                            int offset = i/sizeof(int);
                            if (integers_written_on_output_page >= integers_per_page) {
                                output_handler.UnpinPage(output_page_handler.GetPageNum());//so that it can be flushed
                                output_handler.FlushPage(output_page_handler.GetPageNum()); // write otuput page to disk and remove from buffer
                                output_page_handler = output_handler.NewPage();	// create new output page in buffer
                                integers_written_on_output_page = 0; // new page is empty
                            }
                            char *output_data = output_page_handler.GetData();
                            memcpy(&output_data[integers_written_on_output_page * sizeof(int)], &curr_page_number, sizeof(int));
                            ++integers_written_on_output_page;
                            memcpy(&output_data[integers_written_on_output_page * sizeof(int)], &offset, sizeof(int));
                            ++integers_written_on_output_page;
                        }
                    }
                    // since we are done using the current input page, we can unpin it
                    if (query_processed) break;
                    if (curr_page_handler.GetPageNum() == 0 and counter %2 == 0) break; // termination for backward traversal
                    if (curr_page_handler.GetPageNum() == input_last_page_number and counter %2 == 1) break; // termination for forward traversal
                    input_handler.UnpinPage(curr_page_handler.GetPageNum());
                    if (counter %2 == 0) curr_page_handler = input_handler.PrevPage(curr_page_handler.GetPageNum()); // pinned
                    else curr_page_handler = input_handler.NextPage(curr_page_handler.GetPageNum()); // pinned
                }
//                input_handler.UnpinPage(curr_page_handler.GetPageNum());// so that it can be replaced
            }
            catch (exception &e) { }//cout << e.what() << endl; }
            catch (const char *e) { }//cout << e << endl; }
            catch (...) {}// { cout << "Unknown exception occured\n"; }

            // Since we are done with one query, writing (-1, -1) pair in output page
            if (integers_written_on_output_page >= integers_per_page) {
                output_handler.UnpinPage(output_page_handler.GetPageNum());//so that it can be flushed
                output_handler.FlushPage(output_page_handler.GetPageNum()); // write otuput page to disk and remove from buffer
                output_page_handler = output_handler.NewPage();	// create new output page in buffer
                integers_written_on_output_page = 0; // new page is empty
            }
            char *output_data = output_page_handler.GetData();
            memcpy(&output_data[integers_written_on_output_page * sizeof(int)], &MINUS_ONE, sizeof(int));
            ++integers_written_on_output_page;
            memcpy(&output_data[integers_written_on_output_page * sizeof(int)], &MINUS_ONE, sizeof(int));
            ++integers_written_on_output_page;
            ++counter;
        }
        // fill the empty space with int_min
        for (int j=integers_written_on_output_page; j<= integers_per_page; ++j) {
            char *output_data = output_page_handler.GetData();
            memcpy(&output_data[integers_written_on_output_page * sizeof(int)], &int_min, sizeof(int));
            ++integers_written_on_output_page;
        }
    }
    //else cout << "Unable to open query file\n";
    output_handler.UnpinPage(output_page_handler.GetPageNum());//so that it can be flushed
    output_handler.FlushPages(); // flush output pages
    fm.CloseFile (output_handler);
    fm.CloseFile(input_handler);

    // #TODO: following lines are only for debugging. Remove it in final submission
    //char *my_output = "./output_search";
    //char *ta_output = "./TestCases/TC_search/output_search";
    //printAnswers(fm, my_output, "My output");
    //printAnswers(fm, ta_output, "TA output");
    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x2c8, %rsp            # imm = 0x2C8
cmpl $0x4, %edi
jne 0x46ba
movq 0x8(%rsi), %rax
movq %rax, 0x3f56(%rip)      # 0x81d0
movq 0x10(%rsi), %rax
movq %rax, 0x3f53(%rip)      # 0x81d8
movq 0x18(%rsi), %rax
movq %rax, 0x3f50(%rip)      # 0x81e0
leaq -0x50(%rbp), %rbx
movq %rbx, %rdi
callq 0x3af2
movq 0x3f3d(%rip), %rdx      # 0x81e0
leaq -0xa0(%rbp), %rdi
movq %rbx, %rsi
callq 0x3b9c
movq 0x3f17(%rip), %rdx      # 0x81d0
leaq -0xc0(%rbp), %rdi
leaq -0x50(%rbp), %rsi
callq 0x3c40
leaq -0x60(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x390e
movq 0x3ef8(%rip), %rsi      # 0x81d8
leaq -0x2e8(%rbp), %rdi
movl $0x8, %edx
callq 0x22d0
leaq -0x270(%rbp), %rdi
callq 0x2070
testb %al, %al
je 0x464e
leaq -0xd0(%rbp), %rax
movq %rax, -0x10(%rax)
movq $0x0, -0x8(%rax)
movb $0x0, (%rax)
leaq -0x40(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
callq 0x3798
leaq -0x40(%rbp), %rdi
callq 0x368e
movl %eax, -0x7c(%rbp)
movq $0x0, -0x78(%rbp)
xorl %r14d, %r14d
movq -0x2e8(%rbp), %rax
movq -0x18(%rax), %rdi
leaq -0x2e8(%rbp), %rbx
addq %rbx, %rdi
movl $0xa, %esi
callq 0x21c0
movsbl %al, %edx
movq %rbx, %rdi
leaq -0xe0(%rbp), %rsi
callq 0x22e0
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
testb $0x5, 0x20(%rax,%rcx)
jne 0x460b
leaq -0xe0(%rbp), %rdi
callq 0x3de0
movl %eax, %ebx
leaq -0x40(%rbp), %rdi
callq 0x3638
movq -0x78(%rbp), %rax
movl %eax, %ecx
andl $0x1, %ecx
movl %ecx, -0x44(%rbp)
testb $0x1, %al
jne 0x43c9
leaq -0x70(%rbp), %r15
movq %r15, %rdi
leaq -0xc0(%rbp), %rsi
callq 0x3798
movq %r15, %rdi
callq 0x368e
jmp 0x43e4
leaq -0x70(%rbp), %r15
movq %r15, %rdi
leaq -0xc0(%rbp), %rsi
callq 0x36ee
movq %r15, %rdi
callq 0x368e
movups -0x70(%rbp), %xmm0
movaps %xmm0, -0x40(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x3684
movq %rax, %r13
testq %rax, %rax
je 0x451d
movl $0x14, %r15d
cmpl %ebx, (%r13,%r15)
jne 0x4488
leaq -0x40(%rbp), %rdi
callq 0x368e
movl %eax, %r12d
cmpl $0x6, %r14d
jl 0x4469
leaq -0x60(%rbp), %rdi
callq 0x368e
leaq -0xa0(%rbp), %rdi
movl %eax, %esi
callq 0x38f4
leaq -0x60(%rbp), %rdi
callq 0x368e
leaq -0xa0(%rbp), %rdi
movl %eax, %esi
callq 0x3a96
leaq -0x70(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x390e
movups -0x70(%rbp), %xmm0
movaps %xmm0, -0x60(%rbp)
xorl %r14d, %r14d
leaq -0x60(%rbp), %rdi
callq 0x3684
movl %r15d, %ecx
shrl $0x2, %ecx
movslq %r14d, %r14
movl %r12d, (%rax,%r14,4)
movl %ecx, 0x4(%rax,%r14,4)
addl $0x2, %r14d
addq $-0x4, %r15
cmpq $-0x4, %r15
jne 0x4407
leaq -0x40(%rbp), %rdi
callq 0x368e
orl -0x44(%rbp), %eax
je 0x4588
leaq -0x40(%rbp), %rdi
callq 0x368e
cmpl $0x0, -0x44(%rbp)
je 0x44c0
cmpl -0x7c(%rbp), %eax
je 0x4588
leaq -0x40(%rbp), %rdi
callq 0x368e
leaq -0xc0(%rbp), %rdi
movl %eax, %esi
callq 0x38f4
cmpl $0x0, -0x44(%rbp)
jne 0x44fd
leaq -0x40(%rbp), %rdi
callq 0x368e
leaq -0x70(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
movl %eax, %edx
callq 0x37b4
jmp 0x43e4
leaq -0x40(%rbp), %rdi
callq 0x368e
leaq -0x70(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
movl %eax, %edx
callq 0x370c
jmp 0x43e4
movl $0x8, %edi
callq 0x20f0
leaq 0xe90(%rip), %rcx       # 0x53be
movq %rcx, (%rax)
movq %rax, %rdi
movq 0x3a85(%rip), %rsi      # 0x7fc0
xorl %edx, %edx
callq 0x2290
jmp 0x46c1
jmp 0x455b
jmp 0x455b
jmp 0x455b
jmp 0x455b
jmp 0x455b
jmp 0x455b
jmp 0x455b
jmp 0x455b
jmp 0x455b
jmp 0x455b
movq %rdx, %rbx
movq %rax, %rdi
cmpl $0x3, %ebx
jne 0x4572
callq 0x20c0
callq 0x2270
jmp 0x4588
callq 0x20c0
cmpl $0x2, %ebx
jne 0x4583
callq 0x2270
jmp 0x4588
callq 0x2270
cmpl $0x6, %r14d
jl 0x45d7
leaq -0x60(%rbp), %rdi
callq 0x368e
leaq -0xa0(%rbp), %rdi
movl %eax, %esi
callq 0x38f4
leaq -0x60(%rbp), %rdi
callq 0x368e
leaq -0xa0(%rbp), %rdi
movl %eax, %esi
callq 0x3a96
leaq -0x40(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x390e
movups -0x40(%rbp), %xmm0
movaps %xmm0, -0x60(%rbp)
xorl %r14d, %r14d
leaq -0x60(%rbp), %rdi
callq 0x3684
movslq %r14d, %r14
movl 0x3bb7(%rip), %ecx      # 0x81a0
movl %ecx, (%rax,%r14,4)
movl 0x3bad(%rip), %ecx      # 0x81a0
movl %ecx, 0x4(%rax,%r14,4)
addl $0x2, %r14d
movq -0x78(%rbp), %rax
incl %eax
movq %rax, -0x78(%rbp)
jmp 0x4342
cmpl $0x6, %r14d
jg 0x4636
movslq %r14d, %r14
leaq -0x60(%rbp), %rbx
movq %rbx, %rdi
callq 0x3684
movl 0x3b7e(%rip), %ecx      # 0x81a4
movl %ecx, (%rax,%r14,4)
incq %r14
leal -0x1(%r14), %eax
cmpl $0x6, %eax
jl 0x4618
movq -0xe0(%rbp), %rdi
leaq -0xd0(%rbp), %rax
cmpq %rax, %rdi
je 0x464e
callq 0x21b0
leaq -0x60(%rbp), %rdi
callq 0x368e
leaq -0xa0(%rbp), %rdi
movl %eax, %esi
callq 0x38f4
leaq -0xa0(%rbp), %rdi
callq 0x3a48
leaq -0x50(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x3d08
leaq -0x50(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
callq 0x3d08
leaq -0x2e8(%rbp), %rdi
callq 0x2080
leaq -0x50(%rbp), %rdi
callq 0x3b6e
xorl %eax, %eax
addq $0x2c8, %rsp            # imm = 0x2C8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
xorl %edi, %edi
callq 0x21f0
jmp 0x46df
jmp 0x46df
jmp 0x46cb
jmp 0x46cb
jmp 0x46cb
movq %rax, %rbx
jmp 0x4706
movq %rax, %rbx
jmp 0x46fa
jmp 0x46df
jmp 0x46df
jmp 0x46df
jmp 0x46df
jmp 0x46df
movq %rax, %rbx
movq -0xe0(%rbp), %rdi
leaq -0xd0(%rbp), %rax
cmpq %rax, %rdi
je 0x46fa
callq 0x21b0
leaq -0x2e8(%rbp), %rdi
callq 0x2080
leaq -0x50(%rbp), %rdi
callq 0x3b6e
movq %rbx, %rdi
callq 0x22b0
nop