// File: 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
subq $0xa00, %rsp            # imm = 0xA00
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
cmpl $0x3, -0x8(%rbp)
jge 0x267d
movq 0x8982(%rip), %rdi      # 0xafd8
leaq 0x59a7(%rip), %rsi      # 0x8004
callq 0x2200
movq %rax, %rdi
movq 0x8954(%rip), %rsi      # 0xafc0
callq 0x2250
movl $0x1, -0x4(%rbp)
jmp 0x2dec
leaq -0x210(%rbp), %rdi
callq 0x23c0
movl $0x10, %edi
movl $0x4, %esi
callq 0x2e70
movl %eax, -0x954(%rbp)
jmp 0x26a0
movl -0x954(%rbp), %edx
leaq 0x597a(%rip), %rsi      # 0x8027
leaq -0x210(%rbp), %rdi
callq 0x2050
jmp 0x26bb
leaq -0x420(%rbp), %rdi
callq 0x23c0
jmp 0x26c9
movl $0x10, %edi
movl $0x4, %esi
callq 0x2e70
movl %eax, -0x958(%rbp)
jmp 0x26e0
movl -0x958(%rbp), %edx
leaq 0x594a(%rip), %rsi      # 0x8037
leaq -0x420(%rbp), %rdi
callq 0x2050
jmp 0x26fb
leaq -0x420(%rbp), %rdi
callq 0x21c0
movq %rdx, -0x968(%rbp)
movq %rax, -0x960(%rbp)
jmp 0x2717
movq -0x968(%rbp), %rax
movq -0x960(%rbp), %rcx
movq %rcx, -0x438(%rbp)
movq %rax, -0x430(%rbp)
leaq -0x438(%rbp), %rdi
callq 0x2e90
movq %rax, -0x970(%rbp)
jmp 0x2748
movq -0x970(%rbp), %rax
movq %rax, -0x428(%rbp)
leaq -0x638(%rbp), %rdi
callq 0x23c0
jmp 0x2764
movl $0x10, %edi
movl $0x4, %esi
callq 0x2e70
movl %eax, -0x974(%rbp)
jmp 0x277b
movl -0x974(%rbp), %edx
leaq 0x58c5(%rip), %rsi      # 0x804d
leaq -0x638(%rbp), %rdi
callq 0x2050
jmp 0x2796
leaq -0x638(%rbp), %rdi
callq 0x21c0
movq %rdx, -0x988(%rbp)
movq %rax, -0x980(%rbp)
jmp 0x27b2
movq -0x988(%rbp), %rax
movq -0x980(%rbp), %rcx
movq %rcx, -0x650(%rbp)
movq %rax, -0x648(%rbp)
leaq -0x650(%rbp), %rdi
callq 0x2e90
movq %rax, -0x990(%rbp)
jmp 0x27e3
movq -0x990(%rbp), %rax
movq %rax, -0x640(%rbp)
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0x2390
movl %eax, -0x654(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x660(%rbp)
leaq -0x868(%rbp), %rdi
callq 0x2280
jmp 0x2821
movq -0x660(%rbp), %rsi
leaq -0x868(%rbp), %rdi
movl $0x8, %edx
callq 0x2170
jmp 0x283b
leaq -0x868(%rbp), %rdi
leaq -0x86c(%rbp), %rsi
callq 0x4b00
movq %rax, -0x998(%rbp)
jmp 0x2857
movq -0x998(%rbp), %rax
movq %rax, -0x878(%rbp)
movq $0x0, -0x880(%rbp)
movq -0x878(%rbp), %rax
movl -0x86c(%rbp), %ecx
decl %ecx
movb (%rax,%rcx), %al
movb %al, -0x881(%rbp)
movzbl -0x881(%rbp), %ecx
movl %ecx, %eax
shrl %eax
andl $0x1, %ecx
addl %ecx, %eax
movl %eax, -0x888(%rbp)
movl -0x888(%rbp), %eax
movq %rsp, %rcx
movq %rcx, -0x890(%rbp)
movq %rax, %rdx
addq $0xf, %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x9a0(%rbp)
movq %rcx, %rsp
movq %rax, -0x898(%rbp)
movl $0x0, -0x89c(%rbp)
movl $0x0, -0x8a0(%rbp)
movl $0x0, -0x8a4(%rbp)
movl -0x8a4(%rbp), %eax
cmpl -0x888(%rbp), %eax
jae 0x2a9e
movl -0x89c(%rbp), %eax
movq -0x878(%rbp), %rcx
movslq -0x8a0(%rbp), %rdx
movzbl (%rcx,%rdx), %ecx
cmpl %ecx, %eax
jl 0x29ad
jmp 0x2922
movl -0x89c(%rbp), %eax
movq -0x878(%rbp), %rcx
movslq -0x8a0(%rbp), %rdx
movzbl (%rcx,%rdx), %ecx
cmpl %ecx, %eax
jl 0x29ab
movl -0x8a0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8a0(%rbp)
jmp 0x2922
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x218(%rbp)
movl %eax, -0x21c(%rbp)
jmp 0x2e56
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x218(%rbp)
movl %eax, -0x21c(%rbp)
jmp 0x2e4a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x218(%rbp)
movl %eax, -0x21c(%rbp)
jmp 0x2e3e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x218(%rbp)
movl %eax, -0x21c(%rbp)
jmp 0x2e32
jmp 0x29ad
movq -0x9a0(%rbp), %rax
movl -0x89c(%rbp), %ecx
addl $0x2, %ecx
movzbl -0x881(%rbp), %edx
subl %edx, %ecx
setle %cl
movzbl %cl, %ecx
incl %ecx
movl %ecx, -0x8a8(%rbp)
movb -0x8a8(%rbp), %dl
movslq -0x8a4(%rbp), %rcx
movb %dl, (%rax,%rcx)
movl -0x8a8(%rbp), %esi
movl $0x2, %edi
callq 0x2ea0
vmovsd %xmm0, -0x9a8(%rbp)
jmp 0x29fe
vmovsd -0x9a8(%rbp), %xmm0
vaddsd %xmm0, %xmm0, %xmm0
vcvttsd2si %xmm0, %eax
movb %al, -0x8a9(%rbp)
movl -0x654(%rbp), %edx
movl -0x86c(%rbp), %eax
movl -0x8a0(%rbp), %ecx
subl %ecx, %eax
imull %eax, %edx
movzbl -0x8a9(%rbp), %ecx
leaq -0x420(%rbp), %rdi
leaq -0x638(%rbp), %rsi
movl $0x4, %r8d
movl $0x1, %r9d
callq 0x41c0
jmp 0x2a53
movl -0x654(%rbp), %eax
movl -0x86c(%rbp), %ecx
subl -0x8a0(%rbp), %ecx
imull %ecx, %eax
movl %eax, %eax
addq -0x880(%rbp), %rax
movq %rax, -0x880(%rbp)
movl -0x8a8(%rbp), %eax
addl -0x89c(%rbp), %eax
movl %eax, -0x89c(%rbp)
movl -0x8a4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8a4(%rbp)
jmp 0x28ee
movl -0x86c(%rbp), %ecx
movl %ecx, %eax
shrl %eax
andl $0x1, %ecx
addl %ecx, %eax
movl %eax, -0x8b0(%rbp)
movl -0x8b0(%rbp), %eax
movq %rax, %rdx
addq $0xf, %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x9b0(%rbp)
movq %rcx, %rsp
movq %rax, -0x8b8(%rbp)
movb $0x0, -0x8b9(%rbp)
movl $0x0, -0x8c0(%rbp)
movl -0x8c0(%rbp), %eax
cmpl -0x8b0(%rbp), %eax
jae 0x2bd4
movq -0x9b0(%rbp), %rax
movzbl -0x8b9(%rbp), %edx
addl $0x2, %edx
movl -0x86c(%rbp), %ecx
subl %edx, %ecx
movl $0x1, %ecx
sbbl $-0x1, %ecx
movl %ecx, -0x8c4(%rbp)
movb -0x8c4(%rbp), %dl
movslq -0x8c0(%rbp), %rcx
movb %dl, (%rax,%rcx)
movl -0x8c4(%rbp), %esi
movl $0x2, %edi
callq 0x2ea0
vmovsd %xmm0, -0x9b8(%rbp)
jmp 0x2b4f
vmovsd -0x9b8(%rbp), %xmm0
vcvttsd2si %xmm0, %eax
movb %al, -0x8c5(%rbp)
movl -0x654(%rbp), %edx
movzbl -0x8c5(%rbp), %ecx
movl %ecx, %eax
leal (%rax,%rax,2), %eax
movzbl %al, %ecx
leaq -0x420(%rbp), %rdi
leaq -0x638(%rbp), %rsi
movl $0x6, %r8d
movl $0x2, %r9d
callq 0x41c0
jmp 0x2b97
movl -0x654(%rbp), %eax
addq -0x880(%rbp), %rax
movq %rax, -0x880(%rbp)
movl -0x8c4(%rbp), %ecx
movzbl -0x8b9(%rbp), %eax
addl %ecx, %eax
movb %al, -0x8b9(%rbp)
movl -0x8c0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8c0(%rbp)
jmp 0x2aec
movq -0x9b0(%rbp), %r8
movq -0x9a0(%rbp), %rcx
movl -0x654(%rbp), %esi
movl -0x86c(%rbp), %edx
movl -0x888(%rbp), %r9d
movl -0x8b0(%rbp), %edi
movq -0x878(%rbp), %r10
subq $0x10, %rsp
movq %rsp, %rax
movq %r10, 0x8(%rax)
movl %edi, (%rax)
leaq -0x8f8(%rbp), %rdi
callq 0x2ec0
addq $0x10, %rsp
jmp 0x2c21
vmovdqu -0x8f8(%rbp), %ymm0
vmovdqu -0x8e8(%rbp), %ymm1
vmovdqu %ymm1, -0x920(%rbp)
vmovdqu %ymm0, -0x930(%rbp)
leaq -0x210(%rbp), %rdi
leaq -0x930(%rbp), %rsi
vzeroupper
callq 0x4830
jmp 0x2c59
leaq -0x930(%rbp), %rdi
callq 0x4af0
leaq -0x420(%rbp), %rdi
callq 0x21c0
movq %rdx, -0x9c8(%rbp)
movq %rax, -0x9c0(%rbp)
jmp 0x2c81
movq -0x9c8(%rbp), %rax
movq -0x9c0(%rbp), %rcx
movq %rcx, -0x940(%rbp)
movq %rax, -0x938(%rbp)
leaq -0x940(%rbp), %rdi
callq 0x2e90
movq %rax, -0x9d0(%rbp)
jmp 0x2cb2
movq -0x9d0(%rbp), %rax
movq -0x428(%rbp), %rcx
subq %rcx, %rax
movq %rax, -0x428(%rbp)
leaq -0x638(%rbp), %rdi
callq 0x21c0
movq %rdx, -0x9e0(%rbp)
movq %rax, -0x9d8(%rbp)
jmp 0x2ce6
movq -0x9e0(%rbp), %rax
movq -0x9d8(%rbp), %rcx
movq %rcx, -0x950(%rbp)
movq %rax, -0x948(%rbp)
leaq -0x950(%rbp), %rdi
callq 0x2e90
movq %rax, -0x9e8(%rbp)
jmp 0x2d17
movq -0x9e8(%rbp), %rax
movq -0x640(%rbp), %rcx
subq %rcx, %rax
movq %rax, -0x640(%rbp)
movq 0x82a2(%rip), %rdi      # 0xafd8
leaq 0x5326(%rip), %rsi      # 0x8063
callq 0x2200
movq %rax, -0x9f0(%rbp)
jmp 0x2d4b
movq -0x9f0(%rbp), %rdi
movq -0x880(%rbp), %rsi
callq 0x2090
movq %rax, -0x9f8(%rbp)
jmp 0x2d67
movq -0x9f8(%rbp), %rdi
movq 0x824b(%rip), %rsi      # 0xafc0
callq 0x2250
jmp 0x2d7c
leaq -0x638(%rbp), %rdi
callq 0x2340
jmp 0x2d8a
leaq -0x420(%rbp), %rdi
callq 0x2340
jmp 0x2d98
leaq -0x210(%rbp), %rdi
callq 0x2340
jmp 0x2da6
leaq -0x8f8(%rbp), %rdi
callq 0x4af0
movq -0x890(%rbp), %rax
movq %rax, %rsp
leaq -0x868(%rbp), %rdi
callq 0x20b0
leaq -0x638(%rbp), %rdi
callq 0x2350
leaq -0x420(%rbp), %rdi
callq 0x2350
leaq -0x210(%rbp), %rdi
callq 0x2350
movl -0x4(%rbp), %eax
movq %rbp, %rsp
popq %rbp
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x218(%rbp)
movl %eax, -0x21c(%rbp)
leaq -0x930(%rbp), %rdi
callq 0x4af0
jmp 0x2e26
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x218(%rbp)
movl %eax, -0x21c(%rbp)
leaq -0x8f8(%rbp), %rdi
callq 0x4af0
leaq -0x868(%rbp), %rdi
callq 0x20b0
leaq -0x638(%rbp), %rdi
callq 0x2350
leaq -0x420(%rbp), %rdi
callq 0x2350
leaq -0x210(%rbp), %rdi
callq 0x2350
movq -0x218(%rbp), %rdi
callq 0x2400
nop