// File: /workspace/github_cpp_makefile_star2_O2/jBlinden[P]private-codis/GenerateOTs.cpp
// Function: main
int main(int argc, char **argv)
{
    if (argc < 3)
    {
        cout << "usage: ./GenerateOTs N config-file" << endl;
        return 1;
    }

    ofstream protocolArgsFile;
    protocolArgsFile.open("./data/info.txt", ios::out | ios::binary);

    ofstream senderOTs1;
    senderOTs1.open("./data/server/sOT.txt", ios::out | ios::binary);

    size_t senderOTFileBytes = senderOTs1.tellp();

    ofstream recieverOTs1;
    recieverOTs1.open("./data/client/rOT.txt", ios::out | ios::binary);
    
    size_t recieverOTFileBytes = recieverOTs1.tellp();

    uint32_t N = atoi(argv[1]);
    char* configFile = argv[2];

    ifstream configReader;
    configReader.open(configFile, ios::in);
    
    uint32_t C;
    uint8_t* bits_per_component = ReadInConfigFile(configReader, C);
    

    uint64_t number_of_OT_correlations = 0;
    uint8_t highest_number_bits = bits_per_component[C - 1];
    uint32_t number_rounds_FSM1 = highest_number_bits / FSM1_StepSize + (highest_number_bits % FSM1_StepSize != 0);
    uint8_t iteration_count_arr_FSM1[number_rounds_FSM1];

    int l = 0;
    int smallest_number_of_bits = 0;
    for (int i = 0; i < number_rounds_FSM1; i++)
    {
        if (l >= bits_per_component[smallest_number_of_bits])
        {
            while(l >= bits_per_component[smallest_number_of_bits])
                smallest_number_of_bits ++;
        }

        int round_step = l + FSM1_StepSize <= highest_number_bits ? FSM1_StepSize : 1;
        iteration_count_arr_FSM1[i] = round_step;

        uint8_t num_states = 2 * pow(2, round_step);
        CreateAndExportOTCorrelation(senderOTs1, recieverOTs1, N * (C - smallest_number_of_bits), num_states, bits_FSM1, bits_FSM1_SOT);
        number_of_OT_correlations += N * (C - smallest_number_of_bits);
        l += round_step;
    }

    uint32_t number_rounds_FSM2 = C / FSM2_StepSize + (C % FSM2_StepSize != 0);

    uint8_t iteration_count_arr_FSM2[number_rounds_FSM2];

    uint8_t count = 0;
    for (int i = 0; i < number_rounds_FSM2; i++)
    {
        int round_step = count + FSM2_StepSize <= C ? FSM2_StepSize : 1;

        iteration_count_arr_FSM2[i] = round_step;
        uint8_t num_states = pow(2, round_step);

        CreateAndExportOTCorrelation(senderOTs1, recieverOTs1, N, 3 * num_states, bits_FSM2, bits_FSM2_SOT);
        number_of_OT_correlations += N;
        count += round_step;
    }

    struct ProtocolArgs pArgs(N, C, iteration_count_arr_FSM1, iteration_count_arr_FSM2, number_rounds_FSM1, number_rounds_FSM2, bits_per_component);

    WriteProtocolArgs(protocolArgsFile, pArgs);

    senderOTFileBytes = (size_t)senderOTs1.tellp() - senderOTFileBytes;
    recieverOTFileBytes = (size_t)recieverOTs1.tellp() - recieverOTFileBytes;
    
    cout << "Number of OT correlations: " << number_of_OT_correlations << endl;
    
    recieverOTs1.close();
    senderOTs1.close();
    protocolArgsFile.close();
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x8b8, %rsp            # imm = 0x8B8
cmpl $0x2, %edi
jg 0x2598
pushq $0x1
popq %rbx
movq 0x5a59(%rip), %rdi      # 0x7fd8
leaq 0x2a7e(%rip), %rsi      # 0x5004
callq 0x2200
movq %rax, %rdi
callq 0x2110
jmp 0x2942
leaq -0x6d0(%rbp), %rbx
movq %rsi, %r14
movq %rbx, %rdi
callq 0x2350
leaq 0x2a76(%rip), %rsi      # 0x5027
pushq $0x14
popq %rdx
movq %rbx, %rdi
callq 0x2050
leaq -0x4d0(%rbp), %rdi
callq 0x2350
leaq 0x2a68(%rip), %rsi      # 0x5037
leaq -0x4d0(%rbp), %rdi
pushq $0x14
popq %rdx
callq 0x2050
leaq -0x4d0(%rbp), %rdi
callq 0x21b0
leaq -0x2d0(%rbp), %rdi
callq 0x2350
leaq 0x2a50(%rip), %rsi      # 0x504d
leaq -0x2d0(%rbp), %rdi
pushq $0x14
popq %rdx
callq 0x2050
leaq -0x2d0(%rbp), %rdi
callq 0x21b0
movq 0x8(%r14), %rdi
callq 0x2320
movq 0x10(%r14), %r14
movl %eax, %ebx
leaq -0x8d8(%rbp), %rdi
callq 0x2260
leaq -0x8d8(%rbp), %rdi
pushq $0x8
popq %rdx
movq %r14, %rsi
callq 0x2160
leaq -0x8d8(%rbp), %rdi
leaq -0x2c(%rbp), %rsi
movl %ebx, -0x30(%rbp)
callq 0x397b
movl -0x2c(%rbp), %ecx
movq %rsp, -0x98(%rbp)
decl %ecx
movzbl (%rax,%rcx), %ecx
movl %ecx, %edx
movl %ecx, -0x38(%rbp)
shrl %edx
andl $0x1, %ecx
leal (%rdx,%rcx), %esi
leal 0xf(%rdx,%rcx), %ecx
movq %rsp, %rdx
movq %rsi, -0x88(%rbp)
andl $-0x10, %ecx
subq %rcx, %rdx
movq %rdx, -0x80(%rbp)
movq %rdx, %rsp
movl -0x30(%rbp), %r12d
xorl %r13d, %r13d
xorl %r15d, %r15d
xorl %r14d, %r14d
xorl %ecx, %ecx
movq %rax, -0x78(%rbp)
cmpq -0x88(%rbp), %r13
je 0x2746
movslq %r14d, %rdx
movq %rcx, -0x40(%rbp)
movzbl (%rax,%rdx), %ecx
cmpl %ecx, %r15d
jb 0x26d5
leal -0x1(%rdx), %r14d
addq %rax, %rdx
movzbl (%rdx), %ecx
incl %r14d
incq %rdx
cmpl %ecx, %r15d
jae 0x26c7
leal 0x2(%r15), %eax
cmpl %eax, -0x38(%rbp)
pushq $0x2
popq %rbx
sbbl $0x0, %ebx
movq -0x80(%rbp), %rax
vcvtsi2sd %ebx, %xmm1, %xmm0
movb %bl, (%rax,%r13)
callq 0x21d0
movl -0x2c(%rbp), %edx
vaddsd %xmm0, %xmm0, %xmm0
vcvttsd2si %xmm0, %eax
movzbl %al, %ecx
subl %r14d, %edx
imull %r12d, %edx
leaq -0x4d0(%rbp), %rdi
leaq -0x2d0(%rbp), %rsi
pushq $0x4
popq %r8
pushq $0x1
popq %r9
callq 0x346d
movl -0x2c(%rbp), %eax
movq -0x40(%rbp), %rcx
addl %r15d, %ebx
incq %r13
movl %ebx, %r15d
subl %r14d, %eax
imull %r12d, %eax
addq %rax, %rcx
movq -0x78(%rbp), %rax
jmp 0x26a3
movl -0x2c(%rbp), %edx
movq %rsp, %rsi
movl %edx, %eax
shrl %eax
andl $0x1, %edx
addl %eax, %edx
leaq 0xf(%rdx), %rax
andq $-0x10, %rax
subq %rax, %rsi
movq %rsi, -0x38(%rbp)
movq %rsi, %rsp
movl -0x30(%rbp), %eax
movl $0xff, %r14d
movq %rdx, -0x40(%rbp)
xorl %r12d, %r12d
xorl %ebx, %ebx
imulq %rdx, %rax
addq %rcx, %rax
movq %rax, -0x90(%rbp)
pushq $0x2
popq %r15
cmpq %r12, -0x40(%rbp)
je 0x27e5
andl %r14d, %ebx
movl %r15d, %r13d
leal 0x2(%rbx), %eax
cmpl %eax, -0x2c(%rbp)
movq -0x38(%rbp), %rax
sbbl $0x0, %r13d
vcvtsi2sd %r13d, %xmm1, %xmm0
movb %r13b, (%rax,%r12)
callq 0x21d0
vcvttsd2si %xmm0, %eax
leal (%rax,%rax,2), %ecx
andl %r14d, %ecx
movl -0x30(%rbp), %edx
leaq -0x4d0(%rbp), %rdi
leaq -0x2d0(%rbp), %rsi
pushq $0x6
popq %r8
movl %r15d, %r9d
callq 0x346d
addl %ebx, %r13d
incq %r12
movl %r13d, %ebx
jmp 0x278b
movl -0x30(%rbp), %ecx
movl -0x2c(%rbp), %eax
movq -0x80(%rbp), %r8
movq -0x38(%rbp), %rsi
movl %ecx, -0x70(%rbp)
movl %eax, -0x6c(%rbp)
movq -0x88(%rbp), %rax
movl %eax, -0x68(%rbp)
movq -0x40(%rbp), %rax
movl %eax, -0x64(%rbp)
movq -0x78(%rbp), %rax
movq %r8, -0x60(%rbp)
movq %rsi, -0x58(%rbp)
leaq -0xd0(%rbp), %rsi
movq %rax, -0x50(%rbp)
movb $0x0, -0x48(%rbp)
movl -0x6c(%rbp), %ecx
movl -0x68(%rbp), %edx
movq -0x60(%rbp), %r8
movq -0x58(%rbp), %r9
movq -0x60(%rbp), %r10
movl -0x70(%rbp), %eax
movl -0x64(%rbp), %edi
movq -0x58(%rbp), %r11
movq %r8, 0x10(%rsi)
movq %r9, 0x18(%rsi)
movl %ecx, 0x4(%rsi)
movl %edx, 0x8(%rsi)
movzwl -0x43(%rbp), %edx
movq %r10, 0x10(%rsi)
movq -0x50(%rbp), %r10
movb -0x48(%rbp), %r9b
movl -0x47(%rbp), %r8d
movb -0x41(%rbp), %cl
movl %eax, (%rsi)
movl %edi, 0xc(%rsi)
movq %r11, 0x18(%rsi)
movq %r10, 0x20(%rsi)
movb %r9b, 0x28(%rsi)
movl %r8d, 0x29(%rsi)
movw %dx, 0x2d(%rsi)
movb %cl, 0x2f(%rsi)
leaq -0x6d0(%rbp), %rdi
callq 0x3797
leaq -0xd0(%rbp), %rdi
callq 0x397a
leaq -0x4d0(%rbp), %rdi
callq 0x21b0
leaq -0x2d0(%rbp), %rdi
callq 0x21b0
movq 0x571f(%rip), %rdi      # 0x7fd8
leaq 0x27a3(%rip), %rsi      # 0x5063
callq 0x2200
movq -0x90(%rbp), %rsi
movq %rax, %rdi
callq 0x2170
movq %rax, %rdi
callq 0x2110
leaq -0x2d0(%rbp), %rdi
callq 0x22e0
leaq -0x4d0(%rbp), %rdi
callq 0x22e0
leaq -0x6d0(%rbp), %rdi
callq 0x22e0
leaq -0x70(%rbp), %rdi
callq 0x397a
movq -0x98(%rbp), %rsp
leaq -0x8d8(%rbp), %rdi
callq 0x2090
leaq -0x2d0(%rbp), %rdi
callq 0x22f0
leaq -0x4d0(%rbp), %rdi
callq 0x22f0
leaq -0x6d0(%rbp), %rdi
callq 0x22f0
xorl %ebx, %ebx
movl %ebx, %eax
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x2985
jmp 0x2985
leaq -0xd0(%rbp), %rdi
movq %rax, %rbx
callq 0x397a
jmp 0x2988
jmp 0x2995
jmp 0x2995
jmp 0x2970
jmp 0x2970
movq %rax, %rbx
jmp 0x29a4
jmp 0x2979
jmp 0x2979
movq %rax, %rbx
jmp 0x29b0
jmp 0x2980
movq %rax, %rbx
jmp 0x29bc
movq %rax, %rbx
leaq -0x70(%rbp), %rdi
callq 0x397a
jmp 0x2998
jmp 0x2995
movq %rax, %rbx
leaq -0x8d8(%rbp), %rdi
callq 0x2090
leaq -0x2d0(%rbp), %rdi
callq 0x22f0
leaq -0x4d0(%rbp), %rdi
callq 0x22f0
leaq -0x6d0(%rbp), %rdi
callq 0x22f0
movq %rbx, %rdi
callq 0x2380