// File: /workspace/github_c_makefile_star2_O2/MAGI003769[P]EE450-Socket-Project/serverC.c
// Function: main
int main(void) {
    int sockfd;
    struct addrinfo hints, *servinfo, *p;
    int rv;
    int numbytes;
    struct sockaddr_storage their_addr;
    socklen_t addr_len;
    char s[INET6_ADDRSTRLEN];

    char data[MAXBUFLEN]; // 
    char buf[MAXBUFLEN];  // 
    char edges[MAXBUFLEN] = "";
    char *args[6];  // {<source ID>, <tarrget ID>, <file size>, <MAP ID>, <Prop speed>, <Trans speed>}

    int vtx_set[MAXNUMVERTICES];
    // set all vertex initialed as -1 to prevent the 0-initialization have crash for vertex id 0
    int vtx_num = 0;
    int src_idx, target_idx;
    char ans_path[100] = "";
    float shortest_dist = FLT_MAX;
    float trans_delay = 0.0;
    float prop_delay = 0.0;
    float total_delay = 0.0;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_DGRAM;
    hints.ai_flags = AI_PASSIVE;

    // get information of the backend server itself with MYPORT
    if((rv = getaddrinfo(IPADDRESS, MYPORT, &hints, &servinfo)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        return 1;
    }

    // loop through all the results and make a socket
    for(p = servinfo; p != NULL; p = p->ai_next) {
        if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
            perror("server: socket");
            continue;
        }

        if(bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
            close(sockfd);
            perror("server: bind");
            continue;
        }
        break;
    }

    if(p == NULL) {
        fprintf(stderr, "talker: failed to bind socket\n");
        return 2;
    }

    freeaddrinfo(servinfo);

    addr_len = sizeof their_addr;
    
    printf("The Server C is up and running using UDP on port %s\n", MYPORT);
    fflush(stdout);

    while(1) {
        if((numbytes = recvfrom(sockfd, data, MAXBUFLEN-1, 0,
            (struct sockaddr *)&their_addr, &addr_len)) == -1) {
            perror("recvfrom");
            exit(1);
        }
        data[numbytes] = '\0';
        // printf("debug: server-C received %d bytes from AWS\n", numbytes);
        // printf("debug: server-C received %s bytes from AWS\n", data);

        // read file and search the map_id
        //memset(&buf, 0, sizeof buf);
        memset(&edges, 0, sizeof edges);   // REMEBER to flush the edges buffer !!!
        for(int i = 0; i < MAXNUMVERTICES; i++) { // REMEBER to reset the vtx_set for new query
            vtx_set[i] = -1;
        }
        vtx_num = parse_data2(args, data, edges, vtx_set);
        // printf("debug: the number of vertices in map is %d\n", vtx_num);
        // for(int i = 0; i < MAXNUMVERTICES; i++) {
        //     printf("%d\t", vtx_set[i]);
        // }
        // printf("\n");
        // printf("debug: the length of edges in map is %lu\n", strlen(edges));
        // printf("debug: Edges:\n %s\n", edges);

        printf("The Server C has received data for calculation:\n");
        printf("* Propagation speed: %s km/s;\n", args[4]);
        printf("* Transmission speed %s KB/s;\n", args[5]);
        printf("* map ID: %s;\n", args[3]);
        printf("* Source ID: %s    Destination ID: %s;\n", args[0], args[1]);

        // printf("debug: vtx_set\n");
        // for(int i = 0; i < vtx_num; i++) {
        //     printf("%d\t", vtx_set[i]);
        // }
        // printf("\n");

        // Construct graph represents by a matrix initialized 0
        float G[vtx_num][vtx_num];
        memset(G, 0, vtx_num * vtx_num * sizeof(float));
        add_edges(vtx_num, G, vtx_set, edges);

        // Convert vertex IDs to index in graph matrix and find the shortest path
        src_idx = get_index(vtx_set, vtx_num, atoi(args[0]));
        target_idx = get_index(vtx_set, vtx_num, atoi(args[1]));
        shortest_dist = dijkstra(vtx_num, G, src_idx, target_idx, ans_path, vtx_set);

        // calculate delays
        trans_delay = atof(args[2]) / atof(args[5]);
        prop_delay = shortest_dist / atof(args[4]);
        total_delay = trans_delay + prop_delay;

        // printf("debug: The vertex set: \n");
        // for(int i = 0; i < MAXNUMVERTICES; i++) {
        //     printf("%d\t", get_index(vtx_set, vtx_num, vtx_set[i]));
        // }
        // printf("\n");
        // for(int i = 0; i < MAXNUMVERTICES; i++) {
        //     printf("%d\t", vtx_set[i]);
        // }
        // printf("\n");

        printf("The Server C has finished the calculation: \n");
        printf("Shortest path: %s\n", ans_path);
        printf("Shortest distance: %.4f\n", shortest_dist);
        printf("Transmission delay: %.4f\n", trans_delay);
        printf("Propagation delay: %.4f\n", prop_delay);

        // printing adjacency matrix for debug
        // for(int i = 0; i < vtx_num; i++) {
        //     for(int j = 0; j < vtx_num; j++) {
        //         printf("%.2f\t", G[i][j]);
        //     }
        //     printf("\n");
        // }

        // write answers to buf[] to send back to
        sprintf(buf, "%.4f\n%.4f\n%.4f\n%.4f\n%s", shortest_dist, trans_delay, prop_delay, total_delay, ans_path);

        numbytes = sendto(sockfd, buf, strlen(buf), 0,
            (struct sockaddr *)&their_addr, addr_len);
        
        if(numbytes == -1) {
            perror("listener: sendto");
            exit(1);
        }

        printf("The Server C finished sening the output to AWS\n");
        
        //close(sockfd);
    }

    return 0;

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x30b8, %rsp           # imm = 0x30B8
leaq -0x11a0(%rbp), %rdi
movl $0xfa0, %edx            # imm = 0xFA0
xorl %esi, %esi
callq 0x1080
xorpd %xmm0, %xmm0
movapd %xmm0, -0xc0(%rbp)
movapd %xmm0, -0xd0(%rbp)
movapd %xmm0, -0xe0(%rbp)
movapd %xmm0, -0xf0(%rbp)
andl $0x0, -0xb0(%rbp)
movapd %xmm0, -0x100(%rbp)
movapd %xmm0, -0x110(%rbp)
leaq -0x180(%rbp), %rdx
movapd %xmm0, (%rdx)
movapd %xmm0, 0x10(%rdx)
movapd %xmm0, 0x20(%rdx)
movl $0x2, 0x8(%rdx)
movl $0x1, (%rdx)
leaq 0x747(%rip), %rdi       # 0x203b
leaq 0x74a(%rip), %rsi       # 0x2045
leaq -0x68(%rbp), %r14
movq %r14, %rcx
callq 0x1170
testl %eax, %eax
jne 0x1967
leaq 0x74a(%rip), %rbx       # 0x205c
leaq 0x752(%rip), %r15       # 0x206b
movq (%r14), %r14
testq %r14, %r14
je 0x1990
movl 0x4(%r14), %edi
movl 0x8(%r14), %esi
movl 0xc(%r14), %edx
callq 0x1190
movq %rbx, %rdi
cmpl $-0x1, %eax
je 0x195c
movl %eax, %r12d
movq 0x18(%r14), %rsi
movl 0x10(%r14), %edx
movl %eax, %edi
callq 0x10f0
cmpl $-0x1, %eax
jne 0x19be
movl %r12d, %edi
callq 0x10a0
movq %r15, %rdi
callq 0x1100
addq $0x28, %r14
jmp 0x1919
movq 0x268a(%rip), %rcx      # 0x3ff8
movq (%rcx), %rbx
movl %eax, %edi
callq 0x1070
leaq 0x6cc(%rip), %rsi       # 0x204b
movq %rbx, %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x10c0
pushq $0x1
jmp 0x19ae
movq 0x2661(%rip), %rax      # 0x3ff8
movq (%rax), %rcx
leaq 0x6d7(%rip), %rdi       # 0x2078
pushq $0x1e
popq %rsi
pushq $0x1
popq %rdx
callq 0x1160
pushq $0x2
popq %rax
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq -0x68(%rbp), %rdi
callq 0x1180
leaq -0x44(%rbp), %rax
movl $0x80, (%rax)
leaq 0x6bf(%rip), %rdi       # 0x2097
leaq 0x666(%rip), %rsi       # 0x2045
xorl %eax, %eax
callq 0x1060
movq 0x25eb(%rip), %rax      # 0x3fd8
movq (%rax), %rdi
callq 0x10d0
leaq -0x2140(%rbp), %rbx
leaq -0x200(%rbp), %r14
movl %r12d, -0x54(%rbp)
movl $0xf9f, %edx            # imm = 0xF9F
movl %r12d, %edi
movq %rbx, %rsi
xorl %ecx, %ecx
movq %r14, %r8
leaq -0x44(%rbp), %r9
callq 0x10e0
cmpl $-0x1, %eax
je 0x1cbe
cltq
movb $0x0, -0x2140(%rbp,%rax)
movl $0xfa0, %edx            # imm = 0xFA0
leaq -0x11a0(%rbp), %rdi
xorl %esi, %esi
callq 0x1080
xorl %eax, %eax
cmpq $0xf, %rax
je 0x1a5b
orl $-0x1, -0x150(%rbp,%rax,4)
incq %rax
jmp 0x1a48
leaq -0xa0(%rbp), %rdi
movq %rbx, %rsi
leaq -0x11a0(%rbp), %rdx
leaq -0x150(%rbp), %r15
movq %r15, %rcx
callq 0x12e4
movl %eax, %r12d
leaq 0x74c(%rip), %rdi       # 0x21d1
callq 0x1030
movq -0x80(%rbp), %rsi
movq %rsi, -0x50(%rbp)
leaq 0x63c(%rip), %rdi       # 0x20d5
xorl %eax, %eax
callq 0x1060
movq -0x78(%rbp), %rsi
movq %rsi, -0x40(%rbp)
leaq 0x645(%rip), %rdi       # 0x20f4
xorl %eax, %eax
callq 0x1060
movq -0x88(%rbp), %rsi
leaq 0x64f(%rip), %rdi       # 0x2113
xorl %eax, %eax
callq 0x1060
movq -0xa0(%rbp), %r13
movq -0x98(%rbp), %rbx
leaq 0x642(%rip), %rdi       # 0x2122
movq %r13, %rsi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x1060
movq %rsp, -0x60(%rbp)
movl %r12d, %eax
imulq %rax, %rax
leaq 0xf(,%rax,4), %rax
andq $-0x10, %rax
movq %rsp, %r14
subq %rax, %r14
movq %r14, %rsp
movl %r12d, %edx
imull %edx, %edx
shlq $0x2, %rdx
movq %r14, %rdi
xorl %esi, %esi
callq 0x1080
movl %r12d, %edi
movq %r14, %rsi
movq %r15, %rdx
leaq -0x11a0(%rbp), %rcx
callq 0x1435
movq %r13, %rdi
callq 0x1120
movq %r15, %rdi
movl %r12d, %esi
movl %eax, %edx
callq 0x1412
movl %eax, %r13d
movq %rbx, %rdi
callq 0x1120
movq %r15, %rdi
movl %r12d, %esi
movl %eax, %edx
callq 0x1412
movl %r12d, %edi
movl -0x54(%rbp), %r12d
movq %r14, %rsi
leaq -0x200(%rbp), %r14
movl %r13d, %edx
movl %eax, %ecx
leaq -0x110(%rbp), %rbx
movq %rbx, %r8
movq %r15, %r9
callq 0x1727
movss %xmm0, -0x38(%rbp)
movq -0x90(%rbp), %rdi
callq 0x1040
movsd %xmm0, -0x30(%rbp)
movq -0x40(%rbp), %rdi
callq 0x1040
movsd -0x30(%rbp), %xmm1
divsd %xmm0, %xmm1
cvtsd2ss %xmm1, %xmm0
movss %xmm0, -0x30(%rbp)
cvtss2sd -0x38(%rbp), %xmm0
movsd %xmm0, -0x40(%rbp)
movq -0x50(%rbp), %rdi
callq 0x1040
movsd -0x40(%rbp), %xmm1
divsd %xmm0, %xmm1
cvtsd2ss %xmm1, %xmm1
movss %xmm1, -0x38(%rbp)
movss -0x30(%rbp), %xmm0
addss %xmm1, %xmm0
movss %xmm0, -0x50(%rbp)
leaq 0x60b(%rip), %rdi       # 0x2201
callq 0x1030
leaq 0x548(%rip), %rdi       # 0x214a
movq %rbx, %rsi
xorl %eax, %eax
callq 0x1060
leaq 0x54a(%rip), %rdi       # 0x215d
movsd -0x40(%rbp), %xmm0
movb $0x1, %al
callq 0x1060
cvtss2sd -0x30(%rbp), %xmm0
movsd %xmm0, -0x30(%rbp)
leaq 0x546(%rip), %rdi       # 0x2176
movb $0x1, %al
callq 0x1060
cvtss2sd -0x38(%rbp), %xmm0
movsd %xmm0, -0x38(%rbp)
leaq 0x548(%rip), %rdi       # 0x2190
movb $0x1, %al
callq 0x1060
cvtss2sd -0x50(%rbp), %xmm3
leaq -0x30e0(%rbp), %r15
movq %r15, %rdi
leaq 0x544(%rip), %rsi       # 0x21a9
movsd -0x40(%rbp), %xmm0
movsd -0x30(%rbp), %xmm1
movsd -0x38(%rbp), %xmm2
movq %rbx, %rdx
movb $0x4, %al
callq 0x1140
movq %r15, %rdi
callq 0x1050
movl -0x44(%rbp), %r9d
movl %r12d, %edi
movq %r15, %rsi
movq %rax, %rdx
xorl %ecx, %ecx
movq %r14, %r8
callq 0x1090
cmpl $-0x1, %eax
je 0x1cc7
leaq 0x584(%rip), %rdi       # 0x222d
callq 0x1030
movq -0x60(%rbp), %rsp
leaq -0x2140(%rbp), %rbx
jmp 0x1a07
leaq 0x407(%rip), %rdi       # 0x20cc
jmp 0x1cce
leaq 0x4f2(%rip), %rdi       # 0x21c0
callq 0x1100
pushq $0x1
popq %rdi
callq 0x1150