// File: 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
subq $0x400, %rsp            # imm = 0x400
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl -0x8(%rbp), %edi
movq -0x10(%rbp), %rsi
callq 0x7740
movl $0x6, -0x14(%rbp)
leaq -0x20(%rbp), %rdi
movq %rdi, -0x380(%rbp)
callq 0x7080
movq -0x380(%rbp), %rsi
movq 0x66d6(%rip), %rdx      # 0xe220
leaq -0x40(%rbp), %rdi
callq 0x7180
jmp 0x7b55
movq 0x66b4(%rip), %rdx      # 0xe210
leaq -0x70(%rbp), %rdi
leaq -0x20(%rbp), %rsi
callq 0x7270
jmp 0x7b6b
leaq -0x80(%rbp), %rdi
leaq -0x40(%rbp), %rsi
callq 0x6d50
jmp 0x7b7a
movl $0x0, -0x84(%rbp)
movq 0x668d(%rip), %rsi      # 0xe218
leaq -0x290(%rbp), %rdi
movl $0x8, %edx
callq 0x2350
jmp 0x7b9e
leaq -0x290(%rbp), %rdi
callq 0x22d0
movb %al, -0x381(%rbp)
jmp 0x7bb2
movb -0x381(%rbp), %al
testb $0x1, %al
jne 0x7bc1
jmp 0x8285
leaq -0x2b0(%rbp), %rdi
callq 0x2270
movl $0x0, -0x2b4(%rbp)
leaq -0x70(%rbp), %rdi
movl $0x1, %esi
callq 0x7790
movl %eax, -0x388(%rbp)
jmp 0x7bed
movl -0x388(%rbp), %eax
movl %eax, -0x2b8(%rbp)
leaq -0x290(%rbp), %rdi
leaq -0x2b0(%rbp), %rsi
callq 0x2060
movq %rax, -0x390(%rbp)
jmp 0x7c15
movq -0x390(%rbp), %rdi
movq (%rdi), %rax
movq -0x18(%rax), %rax
addq %rax, %rdi
callq 0x2230
movb %al, -0x391(%rbp)
jmp 0x7c33
movb -0x391(%rbp), %al
testb $0x1, %al
jne 0x7c42
jmp 0x8207
leaq -0x2b0(%rbp), %rdi
callq 0x7660
movl %eax, -0x398(%rbp)
jmp 0x7c56
movl -0x398(%rbp), %eax
movl %eax, -0x2bc(%rbp)
movb $0x0, -0x2bd(%rbp)
movb $0x0, -0x2be(%rbp)
leaq -0x2d0(%rbp), %rdi
callq 0x6800
jmp 0x7c7e
movl -0x2b4(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
cmpl $0x0, %edx
jne 0x7e0f
leaq -0x2e0(%rbp), %rdi
leaq -0x70(%rbp), %rsi
movl $0x1, %edx
callq 0x77e0
jmp 0x7cac
movq -0x2e0(%rbp), %rax
movq %rax, -0x2d0(%rbp)
movq -0x2d8(%rbp), %rax
movq %rax, -0x2c8(%rbp)
jmp 0x7e42
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x8304
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x82f8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x2b0(%rbp), %rdi
callq 0x2140
jmp 0x82f8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
movl -0x4c(%rbp), %eax
movl %eax, -0x39c(%rbp)
movl $0x3, %ecx
cmpl %ecx, %eax
jne 0x7dd1
movq -0x48(%rbp), %rdi
callq 0x20b0
movq %rax, -0x350(%rbp)
callq 0x22f0
jmp 0x7d45
jmp 0x7d47
movl -0x84(%rbp), %eax
cmpl -0x14(%rbp), %eax
jl 0x817f
leaq -0x80(%rbp), %rdi
callq 0x68e0
movl %eax, -0x3a0(%rbp)
jmp 0x7d67
movl -0x3a0(%rbp), %esi
leaq -0x40(%rbp), %rdi
callq 0x6d10
jmp 0x7d78
leaq -0x80(%rbp), %rdi
callq 0x68e0
movl %eax, -0x3a4(%rbp)
jmp 0x7d89
movl -0x3a4(%rbp), %esi
leaq -0x40(%rbp), %rdi
callq 0x6fe0
jmp 0x7d9a
leaq -0x360(%rbp), %rdi
leaq -0x40(%rbp), %rsi
callq 0x6d50
jmp 0x7dac
movq -0x360(%rbp), %rax
movq %rax, -0x80(%rbp)
movq -0x358(%rbp), %rax
movq %rax, -0x78(%rbp)
movl $0x0, -0x84(%rbp)
jmp 0x817f
movl -0x39c(%rbp), %eax
movl $0x2, %ecx
cmpl %ecx, %eax
jne 0x7dfa
movq -0x48(%rbp), %rdi
callq 0x20b0
movq %rax, -0x348(%rbp)
callq 0x22f0
jmp 0x7d47
movq -0x48(%rbp), %rdi
callq 0x20b0
callq 0x22f0
jmp 0x7e0a
jmp 0x7d47
leaq -0x2f0(%rbp), %rdi
leaq -0x70(%rbp), %rsi
movl $0x1, %edx
callq 0x7840
jmp 0x7e26
movq -0x2f0(%rbp), %rax
movq %rax, -0x2d0(%rbp)
movq -0x2e8(%rbp), %rax
movq %rax, -0x2c8(%rbp)
jmp 0x7e44
jmp 0x7e46
leaq -0x2d0(%rbp), %rdi
callq 0x68c0
movq %rax, -0x3b0(%rbp)
jmp 0x7e5b
movq -0x3b0(%rbp), %rax
movq %rax, -0x2f8(%rbp)
cmpq $0x0, -0x2f8(%rbp)
jne 0x7e9f
movl $0x8, %edi
callq 0x20f0
movq %rax, %rdi
leaq 0x153b(%rip), %rax      # 0x93c2
movq %rax, (%rdi)
movq 0x6127(%rip), %rsi      # 0xdfb8
xorl %eax, %eax
movl %eax, %edx
callq 0x2300
jmp 0x8316
movl -0x14(%rbp), %eax
subl $0x1, %eax
cltq
shlq $0x2, %rax
movl %eax, -0x2fc(%rbp)
cmpl $0x0, -0x2fc(%rbp)
jl 0x802c
movq -0x2f8(%rbp), %rax
movslq -0x2fc(%rbp), %rcx
movl (%rax,%rcx), %eax
movl %eax, -0x300(%rbp)
movl -0x300(%rbp), %eax
cmpl -0x2bc(%rbp), %eax
jne 0x8014
movb $0x1, -0x2bd(%rbp)
leaq -0x2d0(%rbp), %rdi
callq 0x68e0
movl %eax, -0x3b4(%rbp)
jmp 0x7f02
movl -0x3b4(%rbp), %eax
movl %eax, -0x304(%rbp)
movslq -0x2fc(%rbp), %rax
shrq $0x2, %rax
movl %eax, -0x308(%rbp)
movl -0x84(%rbp), %eax
cmpl -0x14(%rbp), %eax
jl 0x7fa0
leaq -0x80(%rbp), %rdi
callq 0x68e0
movl %eax, -0x3b8(%rbp)
jmp 0x7f3b
movl -0x3b8(%rbp), %esi
leaq -0x40(%rbp), %rdi
callq 0x6d10
jmp 0x7f4c
leaq -0x80(%rbp), %rdi
callq 0x68e0
movl %eax, -0x3bc(%rbp)
jmp 0x7f5d
movl -0x3bc(%rbp), %esi
leaq -0x40(%rbp), %rdi
callq 0x6fe0
jmp 0x7f6e
leaq -0x318(%rbp), %rdi
leaq -0x40(%rbp), %rsi
callq 0x6d50
jmp 0x7f80
movq -0x318(%rbp), %rax
movq %rax, -0x80(%rbp)
movq -0x310(%rbp), %rax
movq %rax, -0x78(%rbp)
movl $0x0, -0x84(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x68c0
movq %rax, -0x3c8(%rbp)
jmp 0x7fb2
movq -0x3c8(%rbp), %rax
movq %rax, -0x320(%rbp)
movq -0x320(%rbp), %rax
movslq -0x84(%rbp), %rcx
shlq $0x2, %rcx
movl -0x304(%rbp), %edx
movl %edx, (%rax,%rcx)
movl -0x84(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x84(%rbp)
movq -0x320(%rbp), %rax
movslq -0x84(%rbp), %rcx
shlq $0x2, %rcx
movl -0x308(%rbp), %edx
movl %edx, (%rax,%rcx)
movl -0x84(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x84(%rbp)
jmp 0x8016
movslq -0x2fc(%rbp), %rax
subq $0x4, %rax
movl %eax, -0x2fc(%rbp)
jmp 0x7eb1
testb $0x1, -0x2be(%rbp)
je 0x803a
jmp 0x817a
leaq -0x2d0(%rbp), %rdi
callq 0x68e0
movl %eax, -0x3cc(%rbp)
jmp 0x804e
movl -0x3cc(%rbp), %eax
cmpl $0x0, %eax
jne 0x8071
movl -0x2b4(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
cmpl $0x0, %edx
jne 0x8071
jmp 0x817a
leaq -0x2d0(%rbp), %rdi
callq 0x68e0
movl %eax, -0x3d0(%rbp)
jmp 0x8085
movl -0x3d0(%rbp), %eax
cmpl -0x2b8(%rbp), %eax
jne 0x80ab
movl -0x2b4(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
cmpl $0x1, %edx
jne 0x80ab
jmp 0x817a
leaq -0x2d0(%rbp), %rdi
callq 0x68e0
movl %eax, -0x3d4(%rbp)
jmp 0x80bf
movl -0x3d4(%rbp), %esi
leaq -0x70(%rbp), %rdi
callq 0x6d10
jmp 0x80d0
movl -0x2b4(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
cmpl $0x0, %edx
jne 0x812d
leaq -0x2d0(%rbp), %rdi
callq 0x68e0
movl %eax, -0x3d8(%rbp)
jmp 0x80f7
movl -0x3d8(%rbp), %edx
leaq -0x330(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x6b00
jmp 0x810f
movq -0x330(%rbp), %rax
movq %rax, -0x2d0(%rbp)
movq -0x328(%rbp), %rax
movq %rax, -0x2c8(%rbp)
jmp 0x8175
leaq -0x2d0(%rbp), %rdi
callq 0x68e0
movl %eax, -0x3dc(%rbp)
jmp 0x8141
movl -0x3dc(%rbp), %edx
leaq -0x340(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x69e0
jmp 0x8159
movq -0x340(%rbp), %rax
movq %rax, -0x2d0(%rbp)
movq -0x338(%rbp), %rax
movq %rax, -0x2c8(%rbp)
jmp 0x7e44
jmp 0x7d47
leaq -0x80(%rbp), %rdi
callq 0x68c0
movq %rax, -0x3e8(%rbp)
jmp 0x8191
movq -0x3e8(%rbp), %rax
movq %rax, -0x368(%rbp)
movq -0x368(%rbp), %rax
movslq -0x84(%rbp), %rcx
shlq $0x2, %rcx
movl 0x6029(%rip), %edx      # 0xe1e0
movl %edx, (%rax,%rcx)
movl -0x84(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x84(%rbp)
movq -0x368(%rbp), %rax
movslq -0x84(%rbp), %rcx
shlq $0x2, %rcx
movl 0x5fff(%rip), %edx      # 0xe1e0
movl %edx, (%rax,%rcx)
movl -0x84(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x84(%rbp)
movl -0x2b4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2b4(%rbp)
jmp 0x7bf9
movl -0x84(%rbp), %eax
movl %eax, -0x36c(%rbp)
movl -0x36c(%rbp), %eax
cmpl -0x14(%rbp), %eax
jg 0x8279
leaq -0x80(%rbp), %rdi
callq 0x68c0
movq %rax, -0x3f0(%rbp)
jmp 0x8230
movq -0x3f0(%rbp), %rax
movq %rax, -0x378(%rbp)
movq -0x378(%rbp), %rax
movslq -0x84(%rbp), %rcx
shlq $0x2, %rcx
movl 0x5f8e(%rip), %edx      # 0xe1e4
movl %edx, (%rax,%rcx)
movl -0x84(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x84(%rbp)
movl -0x36c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x36c(%rbp)
jmp 0x8213
leaq -0x2b0(%rbp), %rdi
callq 0x2140
leaq -0x80(%rbp), %rdi
callq 0x68e0
movl %eax, -0x3f4(%rbp)
jmp 0x8296
movl -0x3f4(%rbp), %esi
leaq -0x40(%rbp), %rdi
callq 0x6d10
jmp 0x82a7
leaq -0x40(%rbp), %rdi
callq 0x6f60
jmp 0x82b2
leaq -0x20(%rbp), %rdi
leaq -0x40(%rbp), %rsi
callq 0x73a0
jmp 0x82c1
leaq -0x20(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x73a0
jmp 0x82d0
movl $0x0, -0x4(%rbp)
leaq -0x290(%rbp), %rdi
callq 0x2070
leaq -0x20(%rbp), %rdi
callq 0x7140
movl -0x4(%rbp), %eax
addq $0x400, %rsp            # imm = 0x400
popq %rbp
retq
leaq -0x290(%rbp), %rdi
callq 0x2070
leaq -0x20(%rbp), %rdi
callq 0x7140
movq -0x48(%rbp), %rdi
callq 0x2320
nopw %cs:(%rax,%rax)