// File: AraKhachatryan[P]messenger/client.cpp
// Function: send_thread(void*)
void * send_thread( void * arg )
{
    int socket_desc = *(int*)arg;

    char client_name[50];
    std::vector<std::string> dest_names;
    std::string message_info;
    std::string message;

    char input[392];
    char input_encoded[512];

    bzero(client_name, sizeof(client_name));

    std::cout << "Write your name: " << terminal::TEXT_BOLD << terminal::TEXTCOLOR_CYAN;
    std::cin.getline(client_name, 50);
    std::cout << terminal::RESET_ALL;

	send(socket_desc, (char*)&client_name, sizeof(client_name), 0);

	std::cout << "Private message pattern: @<Destination name>: <message>" << std::endl;
	std::cout << "Public message typed as is: <message>" << std::endl;
	std::cout << "Write your first message !!!" << std::endl << std::endl;

    while(1)
    {
        // clear all data buffers
        bzero(input, sizeof(input));
        bzero(input_encoded, sizeof(input_encoded));
        dest_names.clear();
        message_info.clear();
        message.clear();

        std::cin.getline(input, sizeof(input));


        // Erase input from terminal   ////////////////////////////////////////
        int input_size = std::cin.gcount();
        struct winsize w;
        ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
        int erase_line_count = 0;
        if( (input_size % w.ws_col) != 0 )
        {
            erase_line_count = (int)(input_size / w.ws_col) + 1;
        } else {
            erase_line_count = (int)(input_size / w.ws_col);
        }
        while( erase_line_count-- != 0 )
        {
            std::cout << terminal::Cursor_Previous_Line() << terminal::Erase_Line();
        }
        ///////////////////////////////////////////////////////////////////////


        // If input is empty (Enter key is pressed) do nothing
        if ( input_size == 1 )
        {
            continue;
        }


        encode_message(input, input_encoded, sizeof(input_encoded));
        //print_encoded_message(input_encoded, sizeof(input_encoded));

        send(socket_desc,(char*)&input_encoded, sizeof(input_encoded), 0);

        // decoding for input formatting in terminal
        decode_message(input_encoded, sizeof(input_encoded), dest_names, message_info, message);


        // Formatting input (encoded -> decoded input message)   ////////////////////
        // Private message is send
        if ( !dest_names.empty() )
        {
            std::cout << terminal::TEXT_BOLD << terminal::TEXTCOLOR_BLUE;

            for( auto it = dest_names.begin(); it != dest_names.end(); ++it )
            {
                std::cout << *it;
                if ( *it != dest_names.back() )
                {
                    std::cout << ", ";
                }
            }

            std::cout << terminal::RESET_ALL << "<- " << terminal::TEXT_BOLD << terminal::TEXTCOLOR_YELLOW
                        << message << terminal::RESET_ALL << std::endl;

        // Public message is send (if no dest_names)
        } else {
            std::cout << terminal::TEXT_BOLD << terminal::TEXTCOLOR_YELLOW
                        << message << terminal::RESET_ALL << std::endl;

        }
        ///////////////////////////////////////////////////////////////////////



    } // End while()

    pthread_exit(NULL);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x550, %rsp            # imm = 0x550
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movl (%rax), %eax
movl %eax, -0xc(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x3320
leaq -0x78(%rbp), %rdi
callq 0x2330
leaq -0x98(%rbp), %rdi
callq 0x2330
xorps %xmm0, %xmm0
movaps %xmm0, -0x20(%rbp)
movaps %xmm0, -0x30(%rbp)
movaps %xmm0, -0x40(%rbp)
movw $0x0, -0x10(%rbp)
movq 0x6836(%rip), %rdi      # 0x8fc8
leaq 0x38dc(%rip), %rsi      # 0x6075
callq 0x2220
movq %rax, -0x498(%rbp)
jmp 0x27a7
movq -0x498(%rbp), %rdi
movl $0x1, %esi
callq 0x3340
movq %rax, -0x4a0(%rbp)
jmp 0x27c1
movq -0x4a0(%rbp), %rdi
movl $0x24, %esi
callq 0x3340
jmp 0x27d4
movq 0x67fd(%rip), %rdi      # 0x8fd8
leaq -0x40(%rbp), %rsi
movl $0x32, %edx
callq 0x20a0
jmp 0x27eb
movq 0x67d6(%rip), %rdi      # 0x8fc8
xorl %esi, %esi
callq 0x3340
jmp 0x27fb
movl -0xc(%rbp), %edi
leaq -0x40(%rbp), %rsi
movl $0x32, %edx
xorl %ecx, %ecx
callq 0x2110
jmp 0x2810
movq 0x67b1(%rip), %rdi      # 0x8fc8
leaq 0x3869(%rip), %rsi      # 0x6087
callq 0x2220
movq %rax, -0x4a8(%rbp)
jmp 0x282c
movq -0x4a8(%rbp), %rdi
movq 0x677e(%rip), %rsi      # 0x8fb8
callq 0x2270
jmp 0x2841
movq 0x6780(%rip), %rdi      # 0x8fc8
leaq 0x3870(%rip), %rsi      # 0x60bf
callq 0x2220
movq %rax, -0x4b0(%rbp)
jmp 0x285d
movq -0x4b0(%rbp), %rdi
movq 0x674d(%rip), %rsi      # 0x8fb8
callq 0x2270
jmp 0x2872
movq 0x674f(%rip), %rdi      # 0x8fc8
leaq 0x3865(%rip), %rsi      # 0x60e5
callq 0x2220
movq %rax, -0x4b8(%rbp)
jmp 0x288e
movq -0x4b8(%rbp), %rdi
movq 0x671c(%rip), %rsi      # 0x8fb8
callq 0x2270
movq %rax, -0x4c0(%rbp)
jmp 0x28aa
movq -0x4c0(%rbp), %rdi
movq 0x6700(%rip), %rsi      # 0x8fb8
callq 0x2270
jmp 0x28bf
jmp 0x28c1
jmp 0x28c3
leaq -0x220(%rbp), %rdi
movq %rdi, -0x4d0(%rbp)
xorl %esi, %esi
movl %esi, -0x4d4(%rbp)
movl $0x188, %edx            # imm = 0x188
movq %rdx, -0x4c8(%rbp)
callq 0x2130
movl -0x4d4(%rbp), %esi
leaq -0x420(%rbp), %rdi
movl $0x200, %edx            # imm = 0x200
callq 0x2130
leaq -0x58(%rbp), %rdi
callq 0x33a0
leaq -0x78(%rbp), %rdi
callq 0x2310
leaq -0x98(%rbp), %rdi
callq 0x2310
movq -0x4d0(%rbp), %rsi
movq -0x4c8(%rbp), %rdx
movq 0x66a4(%rip), %rdi      # 0x8fd8
callq 0x20a0
jmp 0x293b
movq 0x6696(%rip), %rdi      # 0x8fd8
callq 0x2410
movq %rax, -0x4e0(%rbp)
jmp 0x2950
movq -0x4e0(%rbp), %rax
movl %eax, -0x430(%rbp)
movl $0x1, %edi
movl $0x5413, %esi           # imm = 0x5413
leaq -0x438(%rbp), %rdx
movb $0x0, %al
callq 0x2340
movl $0x0, -0x43c(%rbp)
movl -0x430(%rbp), %eax
movzwl -0x436(%rbp), %ecx
cltd
idivl %ecx
cmpl $0x0, %edx
je 0x29c6
movl -0x430(%rbp), %eax
movzwl -0x436(%rbp), %ecx
cltd
idivl %ecx
addl $0x1, %eax
movl %eax, -0x43c(%rbp)
jmp 0x29dc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x428(%rbp)
movl %eax, -0x42c(%rbp)
jmp 0x2d34
movl -0x430(%rbp), %eax
movzwl -0x436(%rbp), %ecx
cltd
idivl %ecx
movl %eax, -0x43c(%rbp)
jmp 0x29de
movl -0x43c(%rbp), %eax
movl %eax, %ecx
addl $-0x1, %ecx
movl %ecx, -0x43c(%rbp)
cmpl $0x0, %eax
je 0x2aaf
leaq -0x460(%rbp), %rdi
movl $0x1, %esi
callq 0x33c0
jmp 0x2a0b
movq 0x65b6(%rip), %rdi      # 0x8fc8
leaq -0x460(%rbp), %rsi
callq 0x21f0
movq %rax, -0x4e8(%rbp)
jmp 0x2a27
leaq -0x480(%rbp), %rdi
movl $0x2, %esi
callq 0x3510
jmp 0x2a3a
movq -0x4e8(%rbp), %rdi
leaq -0x480(%rbp), %rsi
callq 0x21f0
jmp 0x2a4f
leaq -0x480(%rbp), %rdi
callq 0x2150
leaq -0x460(%rbp), %rdi
callq 0x2150
jmp 0x29de
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x428(%rbp)
movl %eax, -0x42c(%rbp)
jmp 0x2a9e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x428(%rbp)
movl %eax, -0x42c(%rbp)
leaq -0x480(%rbp), %rdi
callq 0x2150
leaq -0x460(%rbp), %rdi
callq 0x2150
jmp 0x2d34
cmpl $0x1, -0x430(%rbp)
jne 0x2abd
jmp 0x28c1
leaq -0x220(%rbp), %rdi
leaq -0x420(%rbp), %rsi
movl $0x200, %edx            # imm = 0x200
callq 0x4150
jmp 0x2ad7
movl -0xc(%rbp), %edi
leaq -0x420(%rbp), %rsi
movl $0x200, %edx            # imm = 0x200
xorl %ecx, %ecx
callq 0x2110
jmp 0x2aef
leaq -0x420(%rbp), %rdi
movl $0x200, %esi            # imm = 0x200
leaq -0x58(%rbp), %rdx
leaq -0x78(%rbp), %rcx
leaq -0x98(%rbp), %r8
callq 0x47a0
jmp 0x2b11
leaq -0x58(%rbp), %rdi
callq 0x3660
testb $0x1, %al
jne 0x2cb1
movq 0x649f(%rip), %rdi      # 0x8fc8
movl $0x1, %esi
callq 0x3340
movq %rax, -0x4f0(%rbp)
jmp 0x2b3c
movq -0x4f0(%rbp), %rdi
movl $0x22, %esi
callq 0x3340
jmp 0x2b4f
leaq -0x58(%rbp), %rdi
callq 0x36a0
movq %rax, -0x488(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x3710
movq %rax, -0x490(%rbp)
leaq -0x488(%rbp), %rdi
leaq -0x490(%rbp), %rsi
callq 0x36d0
testb $0x1, %al
jne 0x2b88
jmp 0x2c00
leaq -0x488(%rbp), %rdi
callq 0x3740
movq %rax, %rsi
movq 0x642a(%rip), %rdi      # 0x8fc8
callq 0x21f0
jmp 0x2ba5
leaq -0x488(%rbp), %rdi
callq 0x3740
movq %rax, -0x4f8(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x3790
movq -0x4f8(%rbp), %rdi
movq %rax, %rsi
callq 0x3760
testb $0x1, %al
jne 0x2bd6
jmp 0x2bed
movq 0x63eb(%rip), %rdi      # 0x8fc8
leaq 0x351e(%rip), %rsi      # 0x6102
callq 0x2220
jmp 0x2beb
jmp 0x2bed
jmp 0x2bef
leaq -0x488(%rbp), %rdi
callq 0x37d0
jmp 0x2b5f
movq 0x63c1(%rip), %rdi      # 0x8fc8
xorl %esi, %esi
callq 0x3340
movq %rax, -0x500(%rbp)
jmp 0x2c17
movq -0x500(%rbp), %rdi
leaq 0x34e0(%rip), %rsi      # 0x6105
callq 0x2220
movq %rax, -0x508(%rbp)
jmp 0x2c33
movq -0x508(%rbp), %rdi
movl $0x1, %esi
callq 0x3340
movq %rax, -0x510(%rbp)
jmp 0x2c4d
movq -0x510(%rbp), %rdi
movl $0x21, %esi
callq 0x3340
movq %rax, -0x518(%rbp)
jmp 0x2c67
movq -0x518(%rbp), %rdi
leaq -0x98(%rbp), %rsi
callq 0x21f0
movq %rax, -0x520(%rbp)
jmp 0x2c83
movq -0x520(%rbp), %rdi
xorl %esi, %esi
callq 0x3340
movq %rax, -0x528(%rbp)
jmp 0x2c9a
movq -0x528(%rbp), %rdi
movq 0x6310(%rip), %rsi      # 0x8fb8
callq 0x2270
jmp 0x2caf
jmp 0x2d2f
movq 0x6310(%rip), %rdi      # 0x8fc8
movl $0x1, %esi
callq 0x3340
movq %rax, -0x530(%rbp)
jmp 0x2ccb
movq -0x530(%rbp), %rdi
movl $0x21, %esi
callq 0x3340
movq %rax, -0x538(%rbp)
jmp 0x2ce5
movq -0x538(%rbp), %rdi
leaq -0x98(%rbp), %rsi
callq 0x21f0
movq %rax, -0x540(%rbp)
jmp 0x2d01
movq -0x540(%rbp), %rdi
xorl %esi, %esi
callq 0x3340
movq %rax, -0x548(%rbp)
jmp 0x2d18
movq -0x548(%rbp), %rdi
movq 0x6292(%rip), %rsi      # 0x8fb8
callq 0x2270
jmp 0x2d2d
jmp 0x2d2f
jmp 0x28c1
leaq -0x98(%rbp), %rdi
callq 0x2150
leaq -0x78(%rbp), %rdi
callq 0x2150
leaq -0x58(%rbp), %rdi
callq 0x37f0
movq -0x428(%rbp), %rdi
callq 0x2390
nop