// File: isabellab3[P]OS-Simulation/main.cpp
// Function: main
int main() {

    unsigned int RAM = 0;
    unsigned int page_size = 0;
    int number_of_hard_disks = 0;

    std::cout << "How much RAM is there?" << std::endl;
    std::cin >> RAM;

    std::cout << "What is the size of a page/frame?" << std::endl;
    std::cin >> page_size;

    std::cout << "How many hard disks does the simulated computer have?" << std::endl;
    std::cin >> number_of_hard_disks;


    OperatingSystem OS(number_of_hard_disks, RAM, page_size);

    std::string input;
    std::getline(std::cin, input);

    while (1) {
         //Shows which process is currently using the CPU and which processes are waiting in the ready-queue.
        if (input == "S r") {
            OS.Snapshot();
        }
        //Shows which processes are currently using the hard disks and which processes are waiting to use them
        else if (input == "S i") {
            OS.IOSnapshot();
        }
        //Shows the state of memory.
        else if (input == "S m") {
            OS.MemorySnapshot();
        }
        // Creates a new pcb and places it at end of ready queue, or in the CPU if the ready queue is empty.
        else if (input == "A") {
            OS.CreateProcess();
        }
        //The currently running process has spent a time quantum using the CPU. 
        else if (input == "Q") {
            OS.CPUToReadyQueue();
        }
        //The process using the CPU forks a child.The child is placed in the end of the ready - queue.
        else if (input == "fork") {
            OS.Fork();
        }
        //The process that is currently using the CPU terminates.
        else if (input == "exit") {
            OS.Exit();
        }
        //The process wants to pause and wait for any of its child processes to terminate.
        else if (input == "wait") {
            OS.Wait();
        }
        
        // For other commands, parse input
        std::stringstream in_stream(input);
        string first_word;
        in_stream >> first_word;

        if (first_word == "d" || first_word == "D" || first_word == "m") {
            int second_word;
            in_stream >> second_word;
            //The process that currently uses the CPU requests the hard disk #number. 
            //It wants to read or write file file _name.
            if (first_word == "d") {
                string third_word;
                in_stream >> third_word;
                OS.RequestDisk(second_word, third_word);
            }
            else if (first_word == "D") { // "D number") {
                // The hard disk #number has finished the work for one process.
                OS.RemoveProcessFromDisk(second_word);
            }
            //The process that is currently using the CPU requests a memory operation for the logical address.
            else if (first_word == "m") { // == "m address") {
                OS.RequestMemoryOperation(second_word);
            }
        }       
        // Get next line of input from user
        std::cout << endl;
        std::getline(std::cin, input);
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x310, %rsp            # imm = 0x310
movl $0x0, -0x4(%rbp)
movl $0x0, -0x8(%rbp)
movl $0x0, -0xc(%rbp)
movl $0x0, -0x10(%rbp)
movq 0x10af2(%rip), %rdi     # 0x12fd0
movq %rdi, -0x2e0(%rbp)
leaq 0x9b18(%rip), %rsi      # 0xc004
callq 0x21d0
movq %rax, %rdi
movq 0x10ac5(%rip), %rsi     # 0x12fc0
movq %rsi, -0x2d8(%rbp)
callq 0x2210
movq 0x10ad2(%rip), %rdi     # 0x12fe0
movq %rdi, -0x2b8(%rbp)
leaq -0x8(%rbp), %rsi
movq %rsi, -0x2c8(%rbp)
callq 0x2050
movq -0x2e0(%rbp), %rdi
leaq 0x9ae8(%rip), %rsi      # 0xc01b
callq 0x21d0
movq -0x2d8(%rbp), %rsi
movq %rax, %rdi
callq 0x2210
movq -0x2b8(%rbp), %rdi
leaq -0xc(%rbp), %rsi
movq %rsi, -0x2c0(%rbp)
callq 0x2050
movq -0x2e0(%rbp), %rdi
leaq 0x9ad1(%rip), %rsi      # 0xc03d
callq 0x21d0
movq -0x2d8(%rbp), %rsi
movq %rax, %rdi
callq 0x2210
movq -0x2b8(%rbp), %rdi
leaq -0x10(%rbp), %rsi
movq %rsi, -0x2d0(%rbp)
callq 0x2120
movq -0x2d0(%rbp), %rsi
movq -0x2c8(%rbp), %rdx
movq -0x2c0(%rbp), %rcx
leaq -0xa8(%rbp), %rdi
callq 0x2a80
leaq -0xc8(%rbp), %rdi
movq %rdi, -0x2b0(%rbp)
callq 0x22b0
movq -0x2b8(%rbp), %rdi
movq -0x2b0(%rbp), %rsi
callq 0x2080
jmp 0x25e0
jmp 0x25e2
jmp 0x25e4
leaq 0x9a88(%rip), %rsi      # 0xc073
leaq -0xc8(%rbp), %rdi
callq 0x2d90
movb %al, -0x2e1(%rbp)
jmp 0x25ff
movb -0x2e1(%rbp), %al
testb $0x1, %al
jne 0x260b
jmp 0x2635
leaq -0xa8(%rbp), %rdi
callq 0x2dc0
jmp 0x2619
jmp 0x27d0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
jmp 0x2a51
leaq 0x9a3b(%rip), %rsi      # 0xc077
leaq -0xc8(%rbp), %rdi
callq 0x2d90
movb %al, -0x2e2(%rbp)
jmp 0x2650
movb -0x2e2(%rbp), %al
testb $0x1, %al
jne 0x265c
jmp 0x266f
leaq -0xa8(%rbp), %rdi
callq 0x2ea0
jmp 0x266a
jmp 0x27ce
leaq 0x9a05(%rip), %rsi      # 0xc07b
leaq -0xc8(%rbp), %rdi
callq 0x2d90
movb %al, -0x2e3(%rbp)
jmp 0x268a
movb -0x2e3(%rbp), %al
testb $0x1, %al
jne 0x2696
jmp 0x26a9
leaq -0xa8(%rbp), %rdi
callq 0x3080
jmp 0x26a4
jmp 0x27cc
leaq 0x99cf(%rip), %rsi      # 0xc07f
leaq -0xc8(%rbp), %rdi
callq 0x2d90
movb %al, -0x2e4(%rbp)
jmp 0x26c4
movb -0x2e4(%rbp), %al
testb $0x1, %al
jne 0x26d0
jmp 0x26e3
leaq -0xa8(%rbp), %rdi
callq 0x3230
jmp 0x26de
jmp 0x27ca
leaq 0x9997(%rip), %rsi      # 0xc081
leaq -0xc8(%rbp), %rdi
callq 0x2d90
movb %al, -0x2e5(%rbp)
jmp 0x26fe
movb -0x2e5(%rbp), %al
testb $0x1, %al
jne 0x270a
jmp 0x271d
leaq -0xa8(%rbp), %rdi
callq 0x3310
jmp 0x2718
jmp 0x27c8
leaq 0x9a82(%rip), %rsi      # 0xc1a6
leaq -0xc8(%rbp), %rdi
callq 0x2d90
movb %al, -0x2e6(%rbp)
jmp 0x2738
movb -0x2e6(%rbp), %al
testb $0x1, %al
jne 0x2744
jmp 0x2754
leaq -0xa8(%rbp), %rdi
callq 0x3360
jmp 0x2752
jmp 0x27c6
leaq 0x9928(%rip), %rsi      # 0xc083
leaq -0xc8(%rbp), %rdi
callq 0x2d90
movb %al, -0x2e7(%rbp)
jmp 0x276f
movb -0x2e7(%rbp), %al
testb $0x1, %al
jne 0x277b
jmp 0x278b
leaq -0xa8(%rbp), %rdi
callq 0x3460
jmp 0x2789
jmp 0x27c4
leaq 0x98f6(%rip), %rsi      # 0xc088
leaq -0xc8(%rbp), %rdi
callq 0x2d90
movb %al, -0x2e8(%rbp)
jmp 0x27a6
movb -0x2e8(%rbp), %al
testb $0x1, %al
jne 0x27b2
jmp 0x27c2
leaq -0xa8(%rbp), %rdi
callq 0x3620
jmp 0x27c0
jmp 0x27c2
jmp 0x27c4
jmp 0x27c6
jmp 0x27c8
jmp 0x27ca
jmp 0x27cc
jmp 0x27ce
jmp 0x27d0
movl $0x10, %edi
movl $0x8, %esi
callq 0x3760
movl %eax, -0x2ec(%rbp)
jmp 0x27e7
movl -0x2ec(%rbp), %edx
leaq -0x260(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
callq 0x22e0
jmp 0x2802
leaq -0x280(%rbp), %rdi
movq %rdi, -0x2f8(%rbp)
callq 0x22b0
movq -0x2f8(%rbp), %rsi
leaq -0x260(%rbp), %rdi
callq 0x2280
jmp 0x282a
leaq 0x98b7(%rip), %rsi      # 0xc0e8
leaq -0x280(%rbp), %rdi
callq 0x2d90
movb %al, -0x2f9(%rbp)
jmp 0x2845
movb -0x2f9(%rbp), %al
testb $0x1, %al
jne 0x28a2
jmp 0x2851
leaq 0x9835(%rip), %rsi      # 0xc08d
leaq -0x280(%rbp), %rdi
callq 0x2d90
movb %al, -0x2fa(%rbp)
jmp 0x286c
movb -0x2fa(%rbp), %al
testb $0x1, %al
jne 0x28a2
jmp 0x2878
leaq 0x97fe(%rip), %rsi      # 0xc07d
leaq -0x280(%rbp), %rdi
callq 0x2d90
movb %al, -0x2fb(%rbp)
jmp 0x2893
movb -0x2fb(%rbp), %al
testb $0x1, %al
jne 0x28a2
jmp 0x29f2
leaq -0x260(%rbp), %rdi
leaq -0x284(%rbp), %rsi
callq 0x2120
jmp 0x28b7
leaq 0x982a(%rip), %rsi      # 0xc0e8
leaq -0x280(%rbp), %rdi
callq 0x2d90
movb %al, -0x2fc(%rbp)
jmp 0x28d2
movb -0x2fc(%rbp), %al
testb $0x1, %al
jne 0x28e1
jmp 0x2970
leaq -0x2a8(%rbp), %rdi
movq %rdi, -0x308(%rbp)
callq 0x22b0
movq -0x308(%rbp), %rsi
leaq -0x260(%rbp), %rdi
callq 0x2280
jmp 0x2909
leaq -0xa8(%rbp), %rdi
leaq -0x284(%rbp), %rsi
leaq -0x2a8(%rbp), %rdx
callq 0x3780
jmp 0x2925
leaq -0x2a8(%rbp), %rdi
callq 0x2130
jmp 0x29f0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
jmp 0x2a39
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
leaq -0x2a8(%rbp), %rdi
callq 0x2130
jmp 0x2a39
leaq 0x9716(%rip), %rsi      # 0xc08d
leaq -0x280(%rbp), %rdi
callq 0x2d90
movb %al, -0x309(%rbp)
jmp 0x298b
movb -0x309(%rbp), %al
testb $0x1, %al
jne 0x2997
jmp 0x29ae
leaq -0xa8(%rbp), %rdi
leaq -0x284(%rbp), %rsi
callq 0x3820
jmp 0x29ac
jmp 0x29ee
leaq 0x96c8(%rip), %rsi      # 0xc07d
leaq -0x280(%rbp), %rdi
callq 0x2d90
movb %al, -0x30a(%rbp)
jmp 0x29c9
movb -0x30a(%rbp), %al
testb $0x1, %al
jne 0x29d5
jmp 0x29ec
leaq -0xa8(%rbp), %rdi
leaq -0x284(%rbp), %rsi
callq 0x38b0
jmp 0x29ea
jmp 0x29ec
jmp 0x29ee
jmp 0x29f0
jmp 0x29f2
movq 0x105d7(%rip), %rdi     # 0x12fd0
movq 0x105c0(%rip), %rsi     # 0x12fc0
callq 0x2210
jmp 0x2a07
movq 0x105d2(%rip), %rdi     # 0x12fe0
leaq -0xc8(%rbp), %rsi
callq 0x2080
jmp 0x2a1c
leaq -0x280(%rbp), %rdi
callq 0x2130
leaq -0x260(%rbp), %rdi
callq 0x2170
jmp 0x25e2
leaq -0x280(%rbp), %rdi
callq 0x2130
leaq -0x260(%rbp), %rdi
callq 0x2170
leaq -0xc8(%rbp), %rdi
callq 0x2130
leaq -0xa8(%rbp), %rdi
callq 0x3b40
movq -0xd0(%rbp), %rdi
callq 0x2330
nopw %cs:(%rax,%rax)
nop