// File: bowenfan96[P]icl-mcs-enigma/enigma.cpp
// Function: Enigma::Enigma(int, char**)
Enigma::Enigma(int argc, char** argv) 
{    
    // Minimum 3 parameters: 0 rotors, 1 plugboard, 1 reflector, 1 position
    // Check if there are 3 or more parameters supplied: argc >= 4
    if(argc < 4) {
        std::cerr << "usage: enigma plugboard-file reflector-file (<rotor-file>)* rotor-positions" << "\n";
        throw INSUFFICIENT_NUMBER_OF_PARAMETERS;
    }
    
    std::string pb_filename;
    std::string rf_filename;
    std::vector<std::string> rot_filenames;
    std::string pos_filename;
        
    pb_filename = argv[1];
    rf_filename = argv[2];
    
    // check if there are rotor(s), then load them
    num_rotors = 0;
    if(argc > 4) {
        for(int i=3; i < (argc - 1); i++) {
            rot_filenames.push_back(argv[i]);
            num_rotors++;
        }
    }
    
    pos_filename = argv[argc - 1];
    
    // load Plugboard
    pb = new Plugboard(pb_filename.c_str());
    
    // load rotor positions
    std::ifstream pos_file;
    pos_file.open(pos_filename);
    
    if(pos_file.is_open()) {
        
        std::string index;
        int pos_num;
        int num_pos = 0;
        size_t sz;
        
        while(std::getline(pos_file, index, ' ')) {
            
            index.erase(std::remove_if(index.begin(), index.end(), ::isspace), index.end());
            
            if(!index.empty()) {
                if(is_numeric(index)) {
                    if(is_valid(index)) {
                        pos_num = std::stoi(index, &sz);
                        vec_rot_posn.push_back(pos_num);
                        num_pos++;
                    }
                    else {
                        std::cerr << "Index in rotor positions file " << pos_filename << " does not correspond to an alphabet letter" << "\n";
                        throw INVALID_INDEX;
                    }
                }
                else {
                    std::cerr << "Non-numeric character in rotor positions file " << pos_filename << "\n";
                    throw NON_NUMERIC_CHARACTER;
                }
            }
        }
        
        // check every rotor has a starting position defined
        // excessive positions are ignored
        if(num_pos < num_rotors) {
            std::cerr << "No starting position for rotor " << num_pos << " in rotor position file: " << pos_filename << "\n";
            throw NO_ROTOR_STARTING_POSITION;
        }
    }
    
    // check if position file open failed
    else {
        std::cerr << "Rotor positions file " << pos_filename << " supplied cannot be opened" << "\n";
        throw ERROR_OPENING_CONFIGURATION_FILE;
    }
    
    // load rotors
    if(num_rotors > 0) {
        for(int i=0; i<num_rotors; i++) {
            vec_rotors.push_back(Rotor(rot_filenames.at(i).c_str()));
            vec_rotors.at(i).position = vec_rot_posn.at(i);
        }
    }
    
    // load Reflector
    rf = new Reflector(rf_filename.c_str());
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x550, %rsp            # imm = 0x550
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0x440(%rbp)
addq $0x8, %rdi
movq %rdi, -0x450(%rbp)
callq 0x5970
movq -0x440(%rbp), %rdi
addq $0x20, %rdi
movq %rdi, -0x448(%rbp)
callq 0x5240
movq -0x440(%rbp), %rax
movq $0x0, 0x38(%rax)
movq $0x0, 0x40(%rax)
cmpl $0x4, -0xc(%rbp)
jge 0x467f
movq 0xd9d4(%rip), %rdi      # 0x11ff0
leaq 0x7cfb(%rip), %rsi      # 0xc31e
callq 0x21d0
movq %rax, -0x458(%rbp)
jmp 0x4631
movq -0x458(%rbp), %rdi
leaq 0x7a3d(%rip), %rsi      # 0xc07c
callq 0x21d0
jmp 0x4646
movl $0x4, %edi
callq 0x20b0
movq %rax, %rdi
movl $0x1, (%rdi)
movq 0xd930(%rip), %rsi      # 0x11f90
xorl %eax, %eax
movl %eax, %edx
callq 0x2310
jmp 0x4f45
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
jmp 0x4f24
leaq -0x48(%rbp), %rdi
movq %rdi, -0x460(%rbp)
callq 0x2280
leaq -0x68(%rbp), %rdi
callq 0x2280
leaq -0x80(%rbp), %rdi
callq 0x5990
leaq -0xa0(%rbp), %rdi
callq 0x2280
movq -0x460(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rsi
callq 0x2260
jmp 0x46c3
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rsi
leaq -0x68(%rbp), %rdi
callq 0x2260
jmp 0x46d6
movq -0x440(%rbp), %rax
movl $0x0, (%rax)
cmpl $0x4, -0xc(%rbp)
jle 0x47e6
movl $0x3, -0xa4(%rbp)
movl -0xa4(%rbp), %eax
movl -0xc(%rbp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jge 0x47e4
movq -0x18(%rbp), %rax
movslq -0xa4(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x470(%rbp)
leaq -0xc9(%rbp), %rdi
movq %rdi, -0x468(%rbp)
callq 0x2340
movq -0x470(%rbp), %rsi
movq -0x468(%rbp), %rdx
leaq -0xc8(%rbp), %rdi
callq 0x2270
jmp 0x4750
leaq -0x80(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
callq 0x59b0
jmp 0x4762
leaq -0xc8(%rbp), %rdi
callq 0x2110
leaq -0xc9(%rbp), %rdi
callq 0x2200
movq -0x440(%rbp), %rax
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
movl -0xa4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa4(%rbp)
jmp 0x46f7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
jmp 0x4efd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
jmp 0x47d3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
leaq -0xc8(%rbp), %rdi
callq 0x2110
leaq -0xc9(%rbp), %rdi
callq 0x2200
jmp 0x4efd
jmp 0x47e6
movq -0x18(%rbp), %rax
movl -0xc(%rbp), %ecx
decl %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rsi
leaq -0xa0(%rbp), %rdi
callq 0x2260
jmp 0x4804
movl $0x30, %edi
callq 0x21e0
movq %rax, -0x478(%rbp)
jmp 0x4817
leaq -0x48(%rbp), %rdi
callq 0x20a0
movq -0x478(%rbp), %rdi
movq %rax, %rsi
callq 0x2640
jmp 0x4831
movq -0x440(%rbp), %rax
movq -0x478(%rbp), %rcx
movq %rcx, 0x38(%rax)
leaq -0x2d8(%rbp), %rdi
callq 0x2210
jmp 0x4851
leaq -0x2d8(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
movl $0x8, %edx
callq 0x2160
jmp 0x486b
leaq -0x2d8(%rbp), %rdi
callq 0x22d0
movb %al, -0x479(%rbp)
jmp 0x487f
movb -0x479(%rbp), %al
testb $0x1, %al
jne 0x488e
jmp 0x4ca0
leaq -0x2f8(%rbp), %rdi
callq 0x2280
movl $0x0, -0x300(%rbp)
leaq -0x2d8(%rbp), %rdi
leaq -0x2f8(%rbp), %rsi
movl $0x20, %edx
callq 0x2360
movq %rax, -0x488(%rbp)
jmp 0x48c5
movq -0x488(%rbp), %rdi
movq (%rdi), %rax
movq -0x18(%rax), %rax
addq %rax, %rdi
callq 0x2230
movb %al, -0x489(%rbp)
jmp 0x48e3
movb -0x489(%rbp), %al
testb $0x1, %al
jne 0x48f2
jmp 0x4bce
leaq -0x2f8(%rbp), %rdi
movq %rdi, -0x4a0(%rbp)
callq 0x2170
movq -0x4a0(%rbp), %rdi
movq %rax, -0x320(%rbp)
callq 0x20e0
movq %rax, -0x328(%rbp)
movq -0x320(%rbp), %rdi
movq -0x328(%rbp), %rsi
movq 0xd664(%rip), %rdx      # 0x11f98
callq 0x5260
movq %rax, -0x498(%rbp)
jmp 0x4942
movq -0x498(%rbp), %rax
movq %rax, -0x318(%rbp)
leaq -0x310(%rbp), %rdi
leaq -0x318(%rbp), %rsi
callq 0x52b0
leaq -0x2f8(%rbp), %rdi
movq %rdi, -0x4b0(%rbp)
callq 0x20e0
movq %rax, -0x338(%rbp)
leaq -0x330(%rbp), %rdi
leaq -0x338(%rbp), %rsi
callq 0x52b0
movq -0x4b0(%rbp), %rdi
movq -0x310(%rbp), %rsi
movq -0x330(%rbp), %rdx
callq 0x2040
movq %rax, -0x4a8(%rbp)
jmp 0x49b3
movq -0x4a8(%rbp), %rax
movq %rax, -0x340(%rbp)
leaq -0x2f8(%rbp), %rdi
callq 0x2300
testb $0x1, %al
jne 0x4bc9
leaq -0x2f8(%rbp), %rdi
callq 0x2e80
movb %al, -0x4b1(%rbp)
jmp 0x49e9
movb -0x4b1(%rbp), %al
testb $0x1, %al
jne 0x49f8
jmp 0x4b52
leaq -0x2f8(%rbp), %rdi
callq 0x2f00
movb %al, -0x4b2(%rbp)
jmp 0x4a0c
movb -0x4b2(%rbp), %al
testb $0x1, %al
jne 0x4a1b
jmp 0x4abf
leaq -0x2f8(%rbp), %rdi
leaq -0x308(%rbp), %rsi
movl $0xa, %edx
callq 0x52f0
movl %eax, -0x4b8(%rbp)
jmp 0x4a3b
movq -0x440(%rbp), %rdi
movl -0x4b8(%rbp), %eax
movl %eax, -0x2fc(%rbp)
addq $0x20, %rdi
leaq -0x2fc(%rbp), %rsi
callq 0x5330
jmp 0x4a60
movl -0x300(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x300(%rbp)
jmp 0x4b50
movq -0x478(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
callq 0x21b0
jmp 0x4efd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
jmp 0x4ef1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
leaq -0x2f8(%rbp), %rdi
callq 0x2110
jmp 0x4ef1
movq 0xd52a(%rip), %rdi      # 0x11ff0
leaq 0x789d(%rip), %rsi      # 0xc36a
callq 0x21d0
movq %rax, -0x4c0(%rbp)
jmp 0x4adb
movq -0x4c0(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x2190
movq %rax, -0x4c8(%rbp)
jmp 0x4af7
movq -0x4c8(%rbp), %rdi
leaq 0x754c(%rip), %rsi      # 0xc051
callq 0x21d0
movq %rax, -0x4d0(%rbp)
jmp 0x4b13
movq -0x4d0(%rbp), %rdi
leaq 0x755b(%rip), %rsi      # 0xc07c
callq 0x21d0
jmp 0x4b28
movl $0x4, %edi
callq 0x20b0
movq %rax, %rdi
movl $0x3, (%rdi)
movq 0xd44e(%rip), %rsi      # 0x11f90
xorl %eax, %eax
movl %eax, %edx
callq 0x2310
jmp 0x4f45
jmp 0x4bc7
movq 0xd497(%rip), %rdi      # 0x11ff0
leaq 0x7829(%rip), %rsi      # 0xc389
callq 0x21d0
movq %rax, -0x4d8(%rbp)
jmp 0x4b6e
movq -0x4d8(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x2190
movq %rax, -0x4e0(%rbp)
jmp 0x4b8a
movq -0x4e0(%rbp), %rdi
leaq 0x74e4(%rip), %rsi      # 0xc07c
callq 0x21d0
jmp 0x4b9f
movl $0x4, %edi
callq 0x20b0
movq %rax, %rdi
movl $0x4, (%rdi)
movq 0xd3d7(%rip), %rsi      # 0x11f90
xorl %eax, %eax
movl %eax, %edx
callq 0x2310
jmp 0x4f45
jmp 0x4bc9
jmp 0x48a4
movq -0x440(%rbp), %rcx
movl -0x300(%rbp), %eax
cmpl (%rcx), %eax
jge 0x4c8f
movq 0xd406(%rip), %rdi      # 0x11ff0
leaq 0x77c7(%rip), %rsi      # 0xc3b8
callq 0x21d0
movq %rax, -0x4e8(%rbp)
jmp 0x4bff
movq -0x4e8(%rbp), %rdi
movl -0x300(%rbp), %esi
callq 0x2320
movq %rax, -0x4f0(%rbp)
jmp 0x4c1a
movq -0x4f0(%rbp), %rdi
leaq 0x77b0(%rip), %rsi      # 0xc3d8
callq 0x21d0
movq %rax, -0x4f8(%rbp)
jmp 0x4c36
movq -0x4f8(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x2190
movq %rax, -0x500(%rbp)
jmp 0x4c52
movq -0x500(%rbp), %rdi
leaq 0x741c(%rip), %rsi      # 0xc07c
callq 0x21d0
jmp 0x4c67
movl $0x4, %edi
callq 0x20b0
movq %rax, %rdi
movl $0x8, (%rdi)
movq 0xd30f(%rip), %rsi      # 0x11f90
xorl %eax, %eax
movl %eax, %edx
callq 0x2310
jmp 0x4f45
leaq -0x2f8(%rbp), %rdi
callq 0x2110
jmp 0x4d31
movq 0xd349(%rip), %rdi      # 0x11ff0
leaq 0x7744(%rip), %rsi      # 0xc3f2
callq 0x21d0
movq %rax, -0x508(%rbp)
jmp 0x4cbc
movq -0x508(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x2190
movq %rax, -0x510(%rbp)
jmp 0x4cd8
movq -0x510(%rbp), %rdi
leaq 0x7443(%rip), %rsi      # 0xc129
callq 0x21d0
movq %rax, -0x518(%rbp)
jmp 0x4cf4
movq -0x518(%rbp), %rdi
leaq 0x737a(%rip), %rsi      # 0xc07c
callq 0x21d0
jmp 0x4d09
movl $0x4, %edi
callq 0x20b0
movq %rax, %rdi
movl $0xb, (%rdi)
movq 0xd26d(%rip), %rsi      # 0x11f90
xorl %eax, %eax
movl %eax, %edx
callq 0x2310
jmp 0x4f45
movq -0x440(%rbp), %rax
cmpl $0x0, (%rax)
jle 0x4e5e
movl $0x0, -0x344(%rbp)
movq -0x440(%rbp), %rcx
movl -0x344(%rbp), %eax
cmpl (%rcx), %eax
jge 0x4e5c
movq -0x440(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x528(%rbp)
movslq -0x344(%rbp), %rsi
leaq -0x80(%rbp), %rdi
callq 0x5a10
movq %rax, -0x520(%rbp)
jmp 0x4d8b
movq -0x520(%rbp), %rdi
callq 0x20a0
movq %rax, %rsi
leaq -0x438(%rbp), %rdi
callq 0x3280
jmp 0x4da8
movq -0x528(%rbp), %rdi
leaq -0x438(%rbp), %rsi
callq 0x59e0
jmp 0x4dbd
leaq -0x438(%rbp), %rdi
callq 0x5a50
movq -0x440(%rbp), %rdi
addq $0x20, %rdi
movslq -0x344(%rbp), %rsi
callq 0x5790
movq %rax, -0x530(%rbp)
jmp 0x4de9
movq -0x440(%rbp), %rdi
movq -0x530(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x53c(%rbp)
addq $0x8, %rdi
movslq -0x344(%rbp), %rsi
callq 0x5a80
movq %rax, -0x538(%rbp)
jmp 0x4e18
movq -0x538(%rbp), %rax
movl -0x53c(%rbp), %ecx
movl %ecx, 0xe8(%rax)
movl -0x344(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x344(%rbp)
jmp 0x4d4b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
leaq -0x438(%rbp), %rdi
callq 0x5a50
jmp 0x4ef1
jmp 0x4e5e
movl $0x30, %edi
callq 0x21e0
movq %rax, -0x548(%rbp)
jmp 0x4e71
leaq -0x68(%rbp), %rdi
callq 0x20a0
movq -0x548(%rbp), %rdi
movq %rax, %rsi
callq 0x3c70
jmp 0x4e8b
movq -0x440(%rbp), %rax
movq -0x548(%rbp), %rcx
movq %rcx, 0x40(%rax)
leaq -0x2d8(%rbp), %rdi
callq 0x2050
leaq -0xa0(%rbp), %rdi
callq 0x2110
leaq -0x80(%rbp), %rdi
callq 0x5ac0
leaq -0x68(%rbp), %rdi
callq 0x2110
leaq -0x48(%rbp), %rdi
callq 0x2110
addq $0x550, %rsp            # imm = 0x550
popq %rbp
retq
movq -0x548(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
callq 0x21b0
leaq -0x2d8(%rbp), %rdi
callq 0x2050
leaq -0xa0(%rbp), %rdi
callq 0x2110
leaq -0x80(%rbp), %rdi
callq 0x5ac0
leaq -0x68(%rbp), %rdi
callq 0x2110
leaq -0x48(%rbp), %rdi
callq 0x2110
movq -0x448(%rbp), %rdi
callq 0x5600
movq -0x450(%rbp), %rdi
callq 0x5b20
movq -0x20(%rbp), %rdi
callq 0x2330
nopw %cs:(%rax,%rax)