// File: /workspace/github_c_makefile_star2_O1/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
cmpl $0x1, %edi
jne 0x8bb2
movq %rcx, %r15
movq %rdx, %r12
movl %edi, 0x10(%rsp)
leaq 0x5dcb(%rip), %rdi      # 0xe945
callq 0x58ac
leaq 0x5de0(%rip), %rsi      # 0xe966
movq %rax, %rdi
callq 0x61f0
movq %rax, %rdi
movq %r14, %rsi
callq 0x61f0
leaq 0x5dd9(%rip), %rsi      # 0xe979
movq %rax, %rdi
movq %r12, %rdx
movq %r15, %rcx
xorl %eax, %eax
callq 0x6581
jmp 0x8bf9
testl $0xfffffffd, %edi       # imm = 0xFFFFFFFD
jne 0x8f5f
movl %edi, 0x10(%rsp)
leaq 0x5d7c(%rip), %rdi      # 0xe945
callq 0x58ac
leaq 0x5d91(%rip), %rsi      # 0xe966
movq %rax, %rdi
callq 0x61f0
movq %rax, %rdi
movq %r14, %rsi
callq 0x61f0
leaq 0x5db5(%rip), %rsi      # 0xe9a4
movq %rax, %rdi
xorl %eax, %eax
callq 0x6581
movq %rax, %r14
movl $0x0, 0xc(%rsp)
xorl %r12d, %r12d
testl %ebx, %ebx
je 0x8c1f
cmpl $0x0, 0xc6be(%rip)      # 0x152d0
je 0x8c1f
movq %r14, %rdi
callq 0x8f73
movq %rax, %r12
testq %r12, %r12
je 0x8c4b
cmpl $0x0, 0xc685(%rip)      # 0x152b0
je 0x8c3e
leaq 0x5d7d(%rip), %rdi      # 0xe9b1
movq %r14, %rsi
xorl %eax, %eax
callq 0x2030
movl $0x1, 0xc(%rsp)
movq %r12, %r15
jmp 0x8c93
xorl %ebp, %ebp
cmpl $0x0, 0xc(%rsp)
je 0x8c59
xorl %r15d, %r15d
jmp 0x8c93
leaq 0xc(%rsp), %r13
xorl %r15d, %r15d
testl %ebp, %ebp
je 0x8c6f
movl $0x186a0, %edi          # imm = 0x186A0
callq 0x2370
movq %r15, %rdi
callq 0x591d
movq %r14, %rdi
movq %r13, %rsi
callq 0x8808
movq %rax, %r15
cmpl $0x3, %ebp
ja 0x8c93
incl %ebp
cmpl $0x0, 0xc(%rsp)
je 0x8c61
testq %r12, %r12
jne 0x8cc1
testl %ebx, %ebx
je 0x8cc1
cmpl $0x0, 0xc62d(%rip)      # 0x152d0
je 0x8cc1
movslq %ebx, %rbx
movq %r15, %rdi
callq 0x2100
movq %r14, %rdi
movq %r15, %rsi
movq %rax, %rdx
movq %rbx, %rcx
callq 0x92e3
movq %r14, %rdi
callq 0x591d
cmpl $0x1, 0xc(%rsp)
jne 0x8e26
movl $0xf8, %edi
callq 0x2470
movq %rax, %rbx
movl $0xf8, %edx
movq %rax, %rdi
xorl %esi, %esi
callq 0x2140
movl 0x10(%rsp), %ebp
movl %ebp, (%rbx)
movq %r15, %rdi
callq 0x31ce
movq %rax, %r14
movq %r15, %rdi
callq 0x591d
leaq 0x5cbd(%rip), %rsi      # 0xe9cd
movq %r14, %rdi
xorl %eax, %eax
callq 0x7cc5
movq %rax, %r15
testl $0xfffffffd, %ebp       # imm = 0xFFFFFFFD
je 0x8e33
testq %r15, %r15
je 0x8f4f
leaq 0x5caa(%rip), %rsi      # 0xe9e3
movq %r15, %rdi
xorl %eax, %eax
callq 0x7cc5
testq %rax, %rax
je 0x8d55
movq 0x20(%rax), %rdi
callq 0x58ac
movq %rax, 0x8(%rbx)
leaq 0x5ce1(%rip), %rsi      # 0xea3d
movq %r14, %rdi
xorl %eax, %eax
callq 0x7cc5
testq %rax, %rax
je 0x8f4f
movq %rax, %r15
addq $0x10, %r15
movq $-0x4, %rdi
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movq %r15, %rcx
movq (%rcx), %rcx
addq $0x4, %rdi
incl %eax
testq %rcx, %rcx
jne 0x8d85
movl %eax, 0x78(%rbx)
callq 0x2470
movq %rax, 0x80(%rbx)
movq (%r15), %r15
testq %r15, %r15
je 0x8f45
xorl %r12d, %r12d
xorps %xmm0, %xmm0
cvtsd2ss 0x30(%r15), %xmm0
movss %xmm0, 0x10(%rsp)
movq %r15, %rdi
callq 0x2a1e
movss 0x10(%rsp), %xmm1
xorps %xmm0, %xmm0
testl %eax, %eax
je 0x8dd8
movaps %xmm1, %xmm0
movq 0x80(%rbx), %rax
movss %xmm0, (%rax,%r12)
testq %r12, %r12
je 0x8df7
movss 0x88(%rbx), %xmm0
ucomiss %xmm1, %xmm0
jbe 0x8dff
movss %xmm1, 0x88(%rbx)
testq %r12, %r12
je 0x8e0d
ucomiss 0x8c(%rbx), %xmm1
jbe 0x8e15
movss %xmm1, 0x8c(%rbx)
movq (%r15), %r15
addq $0x4, %r12
testq %r15, %r15
jne 0x8db1
jmp 0x8f45
movq %r15, %rdi
callq 0x591d
jmp 0x8f5f
testq %r15, %r15
je 0x8f4f
leaq 0x5ba0(%rip), %rsi      # 0xe9e3
movq %r15, %rdi
xorl %eax, %eax
callq 0x7cc5
testq %rax, %rax
je 0x8e5f
movq 0x20(%rax), %rdi
callq 0x58ac
movq %rax, 0x8(%rbx)
leaq 0x5b87(%rip), %rsi      # 0xe9ed
movq %r15, %rdi
xorl %eax, %eax
callq 0x7cc5
testq %rax, %rax
je 0x8e7f
cvtsd2ss 0x30(%rax), %xmm0
movss %xmm0, 0x20(%rbx)
leaq 0x5b7d(%rip), %rsi      # 0xea03
movq %r15, %rdi
xorl %eax, %eax
callq 0x7cc5
testq %rax, %rax
je 0x8ed5
movsd 0x30(%rax), %xmm0
cvtss2sd 0x20(%rbx), %xmm1
subsd %xmm0, %xmm1
divsd %xmm0, %xmm1
mulsd 0x5811(%rip), %xmm1     # 0xe6c0
movsd %xmm1, 0x10(%rsp)
callq 0x5889
leaq 0x5b58(%rip), %rsi      # 0xea19
movq %rax, %rdi
movsd 0x10(%rsp), %xmm0
movb $0x1, %al
callq 0x6581
movq %rax, 0x58(%rbx)
leaq 0x5b07(%rip), %rsi      # 0xe9e3
movq %r15, %rdi
xorl %eax, %eax
callq 0x7cc5
testq %rax, %rax
je 0x8ef8
movq 0x20(%rax), %rdi
callq 0x58ac
movq %rax, 0x10(%rbx)
leaq 0x5b22(%rip), %rsi      # 0xea21
movq %r15, %rdi
xorl %eax, %eax
callq 0x7cc5
testq %rax, %rax
je 0x8f1b
movq 0x20(%rax), %rdi
callq 0x58ac
movq %rax, 0x60(%rbx)
leaq 0x5b0f(%rip), %rsi      # 0xea31
movq %r15, %rdi
xorl %eax, %eax
callq 0x7cc5
testq %rax, %rax
je 0x8f3e
movq 0x20(%rax), %rdi
callq 0x58ac
movq %rax, 0x70(%rbx)
cmpq $0x0, 0x58(%rbx)
je 0x8f4f
movq %r14, %rdi
callq 0x2ad2
jmp 0x8f61
movq %r14, %rdi
callq 0x2ad2
movq %rbx, %rdi
callq 0x8abe
xorl %ebx, %ebx
movq %rbx, %rax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq