// File: /workspace/github_c_makefile_star2_O3/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, %ebx
movq %rsi, %r14
movl %edi, %ebp
cmpl $0x1, %edi
jne 0x894c
movq %rcx, %r15
movq %rdx, %r12
leaq 0x6011(%rip), %rdi      # 0xe925
callq 0x56e9
leaq 0x6026(%rip), %rsi      # 0xe946
movq %rax, %rdi
callq 0x5ff1
movq %rax, %rdi
movq %r14, %rsi
callq 0x5ff1
leaq 0x601f(%rip), %rsi      # 0xe959
movq %rax, %rdi
movq %r12, %rdx
movq %r15, %rcx
xorl %eax, %eax
callq 0x6382
jmp 0x898f
testl $0xfffffffd, %ebp       # imm = 0xFFFFFFFD
jne 0x8cd7
leaq 0x5fc6(%rip), %rdi      # 0xe925
callq 0x56e9
leaq 0x5fdb(%rip), %rsi      # 0xe946
movq %rax, %rdi
callq 0x5ff1
movq %rax, %rdi
movq %r14, %rsi
callq 0x5ff1
leaq 0x5fff(%rip), %rsi      # 0xe984
movq %rax, %rdi
xorl %eax, %eax
callq 0x6382
movq %rax, %r14
movl $0x0, 0xc(%rsp)
testl %ebx, %ebx
je 0x89db
cmpl $0x0, 0xc92b(%rip)      # 0x152d0
je 0x89db
movq %r14, %rdi
callq 0x8ceb
testq %rax, %rax
je 0x89db
movq %rax, %r15
cmpl $0x0, 0xc8f2(%rip)      # 0x152b0
je 0x89d1
leaq 0x5fca(%rip), %rdi      # 0xe991
movq %r14, %rsi
xorl %eax, %eax
callq 0x2030
movl $0x1, 0xc(%rsp)
jmp 0x8a44
xorl %r13d, %r13d
leaq 0xc(%rsp), %r12
xorl %r15d, %r15d
testl %r13d, %r13d
je 0x89f5
movl $0x186a0, %edi          # imm = 0x186A0
callq 0x2380
movq %r15, %rdi
callq 0x5775
movq %r14, %rdi
movq %r12, %rsi
callq 0x8580
movq %rax, %r15
cmpl $0x3, %r13d
ja 0x8a1b
incl %r13d
cmpl $0x0, 0xc(%rsp)
je 0x89e6
testl %ebx, %ebx
je 0x8a44
cmpl $0x0, 0xc8aa(%rip)      # 0x152d0
je 0x8a44
movslq %ebx, %rbx
movq %r15, %rdi
callq 0x2100
movq %r14, %rdi
movq %r15, %rsi
movq %rax, %rdx
movq %rbx, %rcx
callq 0x9048
movq %r14, %rdi
callq 0x5775
cmpl $0x1, 0xc(%rsp)
jne 0x8b9e
movl $0x1, %edi
movl $0xf8, %esi
callq 0x2190
movq %rax, %rbx
movl %ebp, (%rax)
movq %r15, %rdi
callq 0x3163
movq %rax, %r14
movq %r15, %rdi
callq 0x5775
leaq 0x5f28(%rip), %rsi      # 0xe9ad
movq %r14, %rdi
xorl %eax, %eax
callq 0x7a6f
movq %rax, %r15
testl $0xfffffffd, %ebp       # imm = 0xFFFFFFFD
je 0x8bab
testq %r15, %r15
je 0x8cc7
leaq 0x5f15(%rip), %rsi      # 0xe9c3
movq %r15, %rdi
xorl %eax, %eax
callq 0x7a6f
testq %rax, %rax
je 0x8aca
movq 0x20(%rax), %rdi
callq 0x56e9
movq %rax, 0x8(%rbx)
leaq 0x5f4c(%rip), %rsi      # 0xea1d
movq %r14, %rdi
xorl %eax, %eax
callq 0x7a6f
testq %rax, %rax
je 0x8cc7
movq %rax, %r12
addq $0x10, %r12
movq $-0x4, %rdi
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movq %r12, %rcx
movq (%rcx), %rcx
addq $0x4, %rdi
incl %eax
testq %rcx, %rcx
jne 0x8afa
movl %eax, 0x78(%rbx)
callq 0x2480
movq %rax, 0x80(%rbx)
movq (%r12), %r12
testq %r12, %r12
je 0x8cbd
movq %rax, %r15
xorl %r13d, %r13d
xorps %xmm0, %xmm0
cvtsd2ss 0x30(%r12), %xmm0
movss %xmm0, 0x10(%rsp)
movq %r12, %rdi
callq 0x29f2
movss 0x10(%rsp), %xmm1
xorps %xmm0, %xmm0
testl %eax, %eax
je 0x8b52
movaps %xmm1, %xmm0
movss %xmm0, (%r15,%r13,4)
testq %r13, %r13
je 0x8b7d
movss 0x88(%rbx), %xmm0
ucomiss %xmm1, %xmm0
jbe 0x8b72
movss %xmm1, 0x88(%rbx)
ucomiss 0x8c(%rbx), %xmm1
ja 0x8b85
jmp 0x8b8d
movss %xmm1, 0x88(%rbx)
movss %xmm1, 0x8c(%rbx)
incq %r13
movq (%r12), %r12
testq %r12, %r12
jne 0x8b2a
jmp 0x8cbd
movq %r15, %rdi
callq 0x5775
jmp 0x8cd7
testq %r15, %r15
je 0x8cc7
leaq 0x5e08(%rip), %rsi      # 0xe9c3
movq %r15, %rdi
xorl %eax, %eax
callq 0x7a6f
testq %rax, %rax
je 0x8bd7
movq 0x20(%rax), %rdi
callq 0x56e9
movq %rax, 0x8(%rbx)
leaq 0x5def(%rip), %rsi      # 0xe9cd
movq %r15, %rdi
xorl %eax, %eax
callq 0x7a6f
testq %rax, %rax
je 0x8bf7
cvtsd2ss 0x30(%rax), %xmm0
movss %xmm0, 0x20(%rbx)
leaq 0x5de5(%rip), %rsi      # 0xe9e3
movq %r15, %rdi
xorl %eax, %eax
callq 0x7a6f
testq %rax, %rax
je 0x8c4d
movsd 0x30(%rax), %xmm0
cvtss2sd 0x20(%rbx), %xmm1
subsd %xmm0, %xmm1
divsd %xmm0, %xmm1
mulsd 0x5a89(%rip), %xmm1     # 0xe6b0
movsd %xmm1, 0x10(%rsp)
callq 0x56c6
leaq 0x5dc0(%rip), %rsi      # 0xe9f9
movq %rax, %rdi
movsd 0x10(%rsp), %xmm0
movb $0x1, %al
callq 0x6382
movq %rax, 0x58(%rbx)
leaq 0x5d6f(%rip), %rsi      # 0xe9c3
movq %r15, %rdi
xorl %eax, %eax
callq 0x7a6f
testq %rax, %rax
je 0x8c70
movq 0x20(%rax), %rdi
callq 0x56e9
movq %rax, 0x10(%rbx)
leaq 0x5d8a(%rip), %rsi      # 0xea01
movq %r15, %rdi
xorl %eax, %eax
callq 0x7a6f
testq %rax, %rax
je 0x8c93
movq 0x20(%rax), %rdi
callq 0x56e9
movq %rax, 0x60(%rbx)
leaq 0x5d77(%rip), %rsi      # 0xea11
movq %r15, %rdi
xorl %eax, %eax
callq 0x7a6f
testq %rax, %rax
je 0x8cb6
movq 0x20(%rax), %rdi
callq 0x56e9
movq %rax, 0x70(%rbx)
cmpq $0x0, 0x58(%rbx)
je 0x8cc7
movq %r14, %rdi
callq 0x2aa8
jmp 0x8cd9
movq %r14, %rdi
callq 0x2aa8
movq %rbx, %rdi
callq 0x885a
xorl %ebx, %ebx
movq %rbx, %rax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq