// File: /workspace/github_c_makefile_star2_O2/antirez[P]stonky/stonky.c
// Function: getYahooData
ydata *getYahooData(int type, const char *symbol, const char *range, const char *interval, int ttl) {
    const char *apihost = "https://query2.finance.yahoo.com";
    sds url;

    /* Build the query according to the requested data. */
    if (type == YDATA_TS) {
        url = sdsnew(apihost);
        url = sdscat(url,"/v8/finance/chart/");
        url = sdscat(url,symbol);
        url = sdscatprintf(url,"?range=%s&interval=%s&includePrePost=false",
                           range,interval);
    } else if (type == YDATA_QUOTE || type == YDATA_INFO) {
        /* For pricing data we have to abuse the chart API, since Yahoo
         * in late 2023 stopped providing a real time API and the
         * quoteSummary API no logner works. Not everything is available
         * here, but we try to do our best. */
        url = sdsnew(apihost);
        url = sdscat(url,"/v8/finance/chart/");
        url = sdscat(url,symbol);
        url = sdscatprintf(url,"?interval=1d");
    } else {
        return NULL;
    }

    /* Get data via a blocking HTTP request. We try to perform more than
     * a single query since sometimes the Yahoo API will return a 500
     * error without any reason, but will work again immediately after. */
    int attempt = 0, maxattempts = 5;
    int res = C_ERR;

    /* Try using the cache if possible. */
    sds body = (ttl && CacheYahoo) ? kvGet(url) : NULL;
    int cached = body != NULL;

    if (body == NULL) {
        /* No caching or no cached version found? Fetch it from the
         * Yahoo servers. */
        while(attempt < maxattempts && res == C_ERR) {
            if (attempt > 0) usleep(100000);
            sdsfree(body);
            body = makeHttpCall(url,&res);
            attempt++;
        }
    } else {
        if (DebugMode) printf("Using cached version of %s\n", url);
        res = C_OK;
    }

    /* If we are using caching, and we just fetched a fresh version,
     * set it on the cache. */
    if (ttl && CacheYahoo && !cached) {
        kvSet(url,body,ttl);
    }

    sdsfree(url);
    if (res != C_OK) {
        sdsfree(body);
        return NULL;
    }

    /* Setup the empty object. */
    ydata *yd = malloc(sizeof(*yd));
    memset(yd,0,sizeof(*yd));
    yd->type = type;

    /* Extract the JSON fields and fills the data object. */
    cJSON *json = cJSON_Parse(body);
    sdsfree(body);

    if (type == YDATA_QUOTE || type == YDATA_INFO) {
        cJSON *meta = cJSON_Select(json,".chart.result[0].meta");
        cJSON *aux;
        if (meta == NULL) goto fmterr;
        if ((aux = cJSON_Select(meta,".symbol:s")) != NULL)
            yd->symbol = sdsnew(aux->valuestring);

        if ((aux = cJSON_Select(meta,".regularMarketPrice:n")) != NULL)
            yd->reg = aux->valuedouble;
        if ((aux = cJSON_Select(meta,".chartPreviousClose:n")) != NULL)
        {
            /* Compute the price change in percentage. */
            double prev_close = aux->valuedouble;
            double change = (yd->reg - prev_close) / prev_close * 100;
            yd->regchange = sdscatprintf(sdsempty(),"%02.g%%",change);
        }

        if ((aux = cJSON_Select(meta,".symbol:s")) != NULL)
            yd->name = sdsnew(aux->valuestring);
        if ((aux = cJSON_Select(meta,".exchangeName:s")) != NULL)
            yd->exchange = sdsnew(aux->valuestring);
        if ((aux = cJSON_Select(meta,".currency:s")) != NULL)
            yd->csym = sdsnew(aux->valuestring);

        /* Certain times tha Yahoo API is unable to return actual info
         * from a stock, even if it returns success. */
        if (yd->regchange == NULL) goto fmterr;
    } else {
        cJSON *meta = cJSON_Select(json,".chart.result[0].meta");
        cJSON *aux;
        if (meta == NULL) goto fmterr;
        if ((aux = cJSON_Select(meta,".symbol:s")) != NULL)
            yd->symbol = sdsnew(aux->valuestring);
        cJSON *data = cJSON_Select(json,
            ".chart.result[0].indicators.quote[0].close:a");
        if (data == NULL) goto fmterr;

        /* Count the items, so that we can size our timestamp array. */
        int len = 0;
        aux = data->child;
        while(aux != NULL) {
            len++;
            aux = aux->next;
        }
        yd->ts_len = len;
        yd->ts_data = malloc(sizeof(float)*len);

        /* Load data into array. */
        int idx = 0;
        aux = data->child;
        while(aux != NULL) {
            float v = aux->valuedouble;
            if (cJSON_IsNumber(aux))
                yd->ts_data[idx] = v;
            else
                yd->ts_data[idx] = 0;
            if (idx == 0 || v < yd->ts_min) yd->ts_min = v;
            if (idx == 0 || v > yd->ts_max) yd->ts_max = v;
            idx++;
            aux = aux->next;
        }
    }

    cJSON_Delete(json);
    return yd;

fmterr:
    cJSON_Delete(json);
    freeYahooData(yd);
    return NULL;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movl %r8d, %r13d
movq %rsi, %r14
movl %edi, %ebp
cmpl $0x1, %edi
jne 0x76d6
movq %rcx, %r15
movq %rdx, %r12
leaq 0x4eef(%rip), %rdi      # 0xc58d
callq 0x4ef7
leaq 0x4f04(%rip), %rsi      # 0xc5ae
movq %rax, %rdi
callq 0x5593
movq %rax, %rdi
movq %r14, %rsi
callq 0x5593
leaq 0x4efd(%rip), %rsi      # 0xc5c1
movq %rax, %rdi
movq %r12, %rdx
movq %r15, %rcx
xorl %eax, %eax
callq 0x5814
jmp 0x7719
testl $0xfffffffd, %ebp       # imm = 0xFFFFFFFD
jne 0x7a5c
leaq 0x4ea4(%rip), %rdi      # 0xc58d
callq 0x4ef7
leaq 0x4eb9(%rip), %rsi      # 0xc5ae
movq %rax, %rdi
callq 0x5593
movq %rax, %rdi
movq %r14, %rsi
callq 0x5593
leaq 0x4edd(%rip), %rsi      # 0xc5ec
movq %rax, %rdi
xorl %eax, %eax
callq 0x5814
movq %rax, %r14
andl $0x0, 0x4(%rsp)
xorl %ebx, %ebx
movl %r13d, 0x8(%rsp)
testl %r13d, %r13d
je 0x7774
cmpl $0x0, 0xbb9c(%rip)      # 0x132d0
movl $0x0, %r13d
je 0x7777
movq %r14, %rdi
callq 0x7a70
testq %rax, %rax
setne %r13b
je 0x7777
movq %rax, %r15
cmpl $0x0, 0xbb59(%rip)      # 0x132b0
je 0x776a
leaq 0x4e99(%rip), %rdi      # 0xc5f9
movq %r14, %rsi
xorl %eax, %eax
callq 0x2030
movl $0x1, 0x4(%rsp)
jmp 0x77be
xorl %r13d, %r13d
movl %ebp, 0x14(%rsp)
leaq 0x4(%rsp), %r12
xorl %r15d, %r15d
xorl %ebp, %ebp
cmpl $0x4, %ebp
ja 0x77ba
testl %ebx, %ebx
jne 0x77ba
testl %ebp, %ebp
je 0x779c
movl $0x186a0, %edi          # imm = 0x186A0
callq 0x2380
movq %r15, %rdi
callq 0x4f65
movq %r14, %rdi
movq %r12, %rsi
callq 0x732d
movq %rax, %r15
incl %ebp
movl 0x4(%rsp), %ebx
jmp 0x7785
movl 0x14(%rsp), %ebp
testb %r13b, %r13b
movl 0x8(%rsp), %eax
jne 0x77e2
testl %eax, %eax
je 0x77e2
cmpl $0x0, 0xbafe(%rip)      # 0x132d0
je 0x77e2
movslq %eax, %rdx
movq %r14, %rdi
movq %r15, %rsi
callq 0x7b09
movq %r14, %rdi
callq 0x4f65
cmpl $0x1, 0x4(%rsp)
jne 0x7923
pushq $0x1
popq %rdi
movl $0xf8, %esi
callq 0x2190
movq %rax, %rbx
movl %ebp, (%rax)
movq %r15, %rdi
callq 0x3185
movq %rax, %r14
movq %r15, %rdi
callq 0x4f65
leaq 0x4df4(%rip), %rsi      # 0xc615
movq %r14, %rdi
xorl %eax, %eax
callq 0x689e
movq %rax, %r15
testl $0xfffffffd, %ebp       # imm = 0xFFFFFFFD
je 0x7930
testq %r15, %r15
je 0x7a4c
leaq 0x4de1(%rip), %rsi      # 0xc62b
movq %r15, %rdi
xorl %eax, %eax
callq 0x689e
testq %rax, %rax
je 0x7866
movq 0x20(%rax), %rdi
callq 0x4ef7
movq %rax, 0x8(%rbx)
leaq 0x4e18(%rip), %rsi      # 0xc685
movq %r14, %rdi
xorl %eax, %eax
callq 0x689e
testq %rax, %rax
je 0x7a4c
movq %rax, %r15
addq $0x10, %r15
pushq $-0x4
popq %rdi
pushq $-0x1
popq %rax
movq %r15, %rcx
movq (%rcx), %rcx
addq $0x4, %rdi
incl %eax
testq %rcx, %rcx
jne 0x7890
movl %eax, 0x78(%rbx)
callq 0x2480
movq %rax, %r12
movq %rax, 0x80(%rbx)
xorl %r13d, %r13d
movq (%r15), %r15
testq %r15, %r15
je 0x7a42
cvtsd2ss 0x30(%r15), %xmm0
movss %xmm0, 0x8(%rsp)
movq %r15, %rdi
callq 0x2912
movss 0x8(%rsp), %xmm1
xorps %xmm0, %xmm0
testl %eax, %eax
je 0x78e3
movaps %xmm1, %xmm0
movss %xmm0, (%r12,%r13,4)
testq %r13, %r13
je 0x790e
movss 0x88(%rbx), %xmm0
ucomiss %xmm1, %xmm0
jbe 0x7903
movss %xmm1, 0x88(%rbx)
ucomiss 0x8c(%rbx), %xmm1
ja 0x7916
jmp 0x791e
movss %xmm1, 0x88(%rbx)
movss %xmm1, 0x8c(%rbx)
incq %r13
jmp 0x78b3
movq %r15, %rdi
callq 0x4f65
jmp 0x7a5c
testq %r15, %r15
je 0x7a4c
leaq 0x4ceb(%rip), %rsi      # 0xc62b
movq %r15, %rdi
xorl %eax, %eax
callq 0x689e
testq %rax, %rax
je 0x795c
movq 0x20(%rax), %rdi
callq 0x4ef7
movq %rax, 0x8(%rbx)
leaq 0x4cd2(%rip), %rsi      # 0xc635
movq %r15, %rdi
xorl %eax, %eax
callq 0x689e
testq %rax, %rax
je 0x797c
cvtsd2ss 0x30(%rax), %xmm0
movss %xmm0, 0x20(%rbx)
leaq 0x4cc8(%rip), %rsi      # 0xc64b
movq %r15, %rdi
xorl %eax, %eax
callq 0x689e
testq %rax, %rax
je 0x79d2
movsd 0x30(%rax), %xmm0
cvtss2sd 0x20(%rbx), %xmm1
subsd %xmm0, %xmm1
divsd %xmm0, %xmm1
mulsd 0x4a1c(%rip), %xmm1     # 0xc3c8
movsd %xmm1, 0x8(%rsp)
callq 0x4ee9
leaq 0x4ca3(%rip), %rsi      # 0xc661
movq %rax, %rdi
movsd 0x8(%rsp), %xmm0
movb $0x1, %al
callq 0x5814
movq %rax, 0x58(%rbx)
leaq 0x4c52(%rip), %rsi      # 0xc62b
movq %r15, %rdi
xorl %eax, %eax
callq 0x689e
testq %rax, %rax
je 0x79f5
movq 0x20(%rax), %rdi
callq 0x4ef7
movq %rax, 0x10(%rbx)
leaq 0x4c6d(%rip), %rsi      # 0xc669
movq %r15, %rdi
xorl %eax, %eax
callq 0x689e
testq %rax, %rax
je 0x7a18
movq 0x20(%rax), %rdi
callq 0x4ef7
movq %rax, 0x60(%rbx)
leaq 0x4c5a(%rip), %rsi      # 0xc679
movq %r15, %rdi
xorl %eax, %eax
callq 0x689e
testq %rax, %rax
je 0x7a3b
movq 0x20(%rax), %rdi
callq 0x4ef7
movq %rax, 0x70(%rbx)
cmpq $0x0, 0x58(%rbx)
je 0x7a4c
movq %r14, %rdi
callq 0x29c2
jmp 0x7a5e
movq %r14, %rdi
callq 0x29c2
movq %rbx, %rdi
callq 0x75e4
xorl %ebx, %ebx
movq %rbx, %rax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq