/******************************************************************************
 * Copyright © 2016 jl777                                                     *
 * ALL RIGHTS RESERVED                                                        *
 *                                                                            *
 * Removal or modification of this copyright notice is prohibited.            *
 *                                                                            *
 ******************************************************************************/

int32_t init_startheight(int32_t startheight)
{
    long filesize; int32_t height; char *heightstr;
    if ( (heightstr= OS_filestr(&filesize,TRADEBOT_NAME)) != 0 )
    {
        height = atoi(heightstr);
        free(heightstr);
        if ( height > 0 && height < startheight )
            startheight = height;
    }
    return(startheight);
}

void steemit_history_limitorder(int32_t ind,char *acount,cJSON *opitem)
{
    // hwm.12081 flag.1 limit_order_create ({"owner":"taker","orderid":1469136578,"amount_to_sell":"24.346 SBD","min_to_receive":"7.770 STEEM","fill_or_kill":false,"expiration":"2016-07-24T23:21:24"})
}

void steemit_update_inventory(double *SBD,double *SBDVOL,double *STEEMVOL,double *STEEM,double myvol,char *mycoin,char *other,double othervol,char *othercoin)
{
    if ( strcmp(mycoin,"SBD") == 0 && strcmp(othercoin,"STEEM") == 0 )
    {
        *SBD -= myvol;
        *SBDVOL += myvol;
        *STEEM += othervol;
        *STEEMVOL += othervol;
    }
    else if ( strcmp(mycoin,"STEEM") == 0 && strcmp(othercoin,"SBD") == 0 )
    {
        *STEEM -= myvol;
        *STEEMVOL += myvol;
        *SBD += othervol;
        *SBDVOL += othervol;
    } else printf("steemit_update_inventory: unexpected pair (%s) (%s)\n",mycoin,othercoin);
}

void steemit_history_fillorder(int32_t ind,char *account,cJSON *opitem)
{
    static double SBD,STEEM,SBDVOL,STEEMVOL;
    char *taker,*maker,*takercoin,*makercoin; uint64_t openorderid,fillorderid; double takervol,makervol;
    taker = jstr(opitem,"current_owner");
    fillorderid = j64bits(opitem,"current_orderid");
    takercoin = jstr(opitem,"current_pays");
    maker = jstr(opitem,"open_owner");
    openorderid = j64bits(opitem,"open_orderid");
    makercoin = jstr(opitem,"open_pays");
    if ( taker != 0 && maker != 0 && takercoin != 0 && makercoin != 0 && (strcmp(account,taker) == 0 || strcmp(maker,account) == 0) )
    {
        takervol = atof(takercoin);
        while ( *takercoin != 0 && *takercoin != ' ' )
            takercoin++;
        makervol = atof(makercoin);
        while ( *makercoin != 0 && *makercoin != ' ' )
            makercoin++;
        if ( strcmp(taker,account) == 0 )
        {
            steemit_update_inventory(&SBD,&SBDVOL,&STEEMVOL,&STEEM,takervol,takercoin+1,maker,makervol,makercoin+1);
            printf("%6d %s.(%.6f%s) <-> %s.(%.6f%s) SBD %.6f STEEM %.6f | VOL SBD %.6f STEEM %.6f-> %.6f\n",ind,taker,takervol,takercoin,maker,makervol,makercoin,SBD,STEEM,SBDVOL,STEEMVOL,SBD/STEEM);
        }
        else
        {
            steemit_update_inventory(&SBD,&SBDVOL,&STEEMVOL,&STEEM,takervol,takercoin+1,maker,makervol,makercoin+1);
            printf("%6d %s.(%.6f%s) <-> %s.(%.6f%s) SBD %.6f STEEM %.6f | VOL SBD %.6f STEEM %.6f-> %.6f\n",ind,maker,makervol,makercoin,taker,takervol,takercoin,SBD,STEEM,SBDVOL,STEEMVOL,SBD/STEEM);
        }
    }
    //hwm.12077 flag.1 fill_order ({"current_owner":"enki","current_orderid":3402053187,"current_pays":"19.613 SBD","open_owner":"taker","open_orderid":1469136521,"open_pays":"5.792 STEEM"})
    
}

void steemit_tradehistory(char *account)
{
    int32_t j,n,m,ind,flag = 1,hwm = 0; cJSON *retjson,*result,*item,*oparray,*opitem; char *opstr,*retstr;
    while ( flag != 0 )
    {
        flag = 0;
        if ( (retstr= STEEM_gethistory(account,hwm+1,1)) != 0 )
        {
            if ( (retjson= cJSON_Parse(retstr)) != 0 )
            {
                if ( (result= jarray(&n,retjson,"result")) != 0 )
                {
                    for (j=0; j<n; j++)
                    {
                        item = jitem(result,j);
                        if ( is_cJSON_Array(item) != 0 && cJSON_GetArraySize(item) == 2 )
                        {
                            ind = jdouble(jitem(item,0),0);
                            //printf("ind.%d from %s\n",ind,jprint(jitem(item,0),0));
                            if ( ind == hwm )
                            {
                                if ( (oparray= jarray(&m,jitem(item,1),"op")) != 0 && m == 2 )
                                {
                                    opstr = jstr(jitem(oparray,0),0);
                                    opitem = jitem(oparray,1);
                                    if ( strcmp(opstr,"limit_order_create") == 0 )
                                        steemit_history_limitorder(hwm,account,opitem);
                                    else if ( strcmp(opstr,"fill_order") == 0 )
                                        steemit_history_fillorder(hwm,account,opitem);
                                    else printf("hwm.%d flag.%d %s (%s)\n",hwm,flag,opstr,jprint(opitem,0));
                                } else printf("unexpected oparray item.%d j.%d (%s)\n",hwm,j,jprint(jitem(item,1),0));
                                hwm++;
                                flag++;
                            } else printf("skip ind.%d when hwm.%d\n",ind,hwm);
                        } else printf("unexpected item.%d j.%d (%s)\n",hwm,j,jprint(item,0));
                    }
                } else printf("no result in (%s)\n",retstr);
                free(retjson);
            } else printf("error.(%s)\n",retstr);
            free(retstr);
        } else printf("null return for hwm.%d\n",hwm);
    }
}

void steemit_pow(int32_t height,int32_t ind,int32_t j,cJSON *json)
{
    // 3417584.1: limit_order_create.({"owner":"taker","orderid":1469129923,"amount_to_sell":"7.770 STEEM","min_to_receive":"25.367 SBD","fill_or_kill":false,"expiration":"2016-07-23T14:20:23"})
}

void steemit_transfer(int32_t height,int32_t ind,int32_t j,cJSON *json)
{
    // 3417584.0: transfer.({"from":"lukestokes","to":"benslayton","amount":"100.000 SBD","memo":"Dude, you're awesome. No need to give back as your rewards are all you. You worked hard on your post and it was perfectly timed. You deserve every bit of the reward you got! :)"})
}

void steemit_limitorder(int32_t height,int32_t ind,int32_t j,cJSON *json)
{
    // 3417584.1: limit_order_create.({"owner":"taker","orderid":1469129923,"amount_to_sell":"7.770 STEEM","min_to_receive":"25.367 SBD","fill_or_kill":false,"expiration":"2016-07-23T14:20:23"})
}

void steemit_cancelorder(int32_t height,int32_t ind,int32_t j,cJSON *json)
{
    // 3418230.1.0: limit_order_cancel.({"owner":"kujira","orderid":1469194992})
}

void steemit_accountupdate(int32_t height,int32_t ind,int32_t j,cJSON *json)
{
    // 3417791.3: account_update.({"account":"hello","owner":{"weight_threshold":2,"account_auths":[["xeroc", 1]],"key_auths":[["STM8GkRiob5ErhxZgaVv7a3tCGUy14Kp2D3zL69LcpHpgnLxDoTTi", 1]]},"active":{"weight_threshold":1,"account_auths":[["xeroc", 1]],"key_auths":[["STM7WkgYMEfMrteCD1e5VyPGu6VbgYa95Q9xRjdQs8M8PgJ1QdQie", 1]]},"posting":{"weight_threshold":1,"account_auths":[["xeroc", 1]],"key_auths":[["STM6YMtZfg7AsiXdxHjZu7CpYBveLjSKQKgw9bcSUsePuWSMk1xTb", 1]]},"memo_key":"STM8MhWjF83aovRRyMVmFeSbiSXfWEyqMhxocvDoSri8MxAdTojWZ","json_metadata":""})
}

void steemit_convert(int32_t height,int32_t ind,int32_t j,cJSON *json)
{
    // 3418042.8.0: convert.({"owner":"oliverb","requestid":1469194981,"amount":"1.090 SBD"})
}

void steemit_powerup(int32_t height,int32_t ind,int32_t j,cJSON *json)
{
    // 3418105.2.0: transfer_to_vesting.({"from":"jed78","to":"jed78","amount":"2.600 STEEM"})
}

void steemit_deletecomment(int32_t height,int32_t ind,int32_t j,cJSON *json)
{
    // 3417632.0: delete_comment.({"author":"cass","permlink":"re-isteemit-re-summon-re-isteemit-and-hours-later-the-steemit-theme-music-is-finally-here-20160722t132137767z"})
}

void steemit_customjson(int32_t height,int32_t ind,int32_t j,cJSON *json)
{
    // 3418087.5.0: custom_json.({"required_auths":[],"required_posting_auths":["sictransitgloria"],"id":"follow","json":"{\"follower\":\"sictransitgloria\",\"following\":\"johnsmith\",\"what\":[\"blog\"]}"})
}

void steemit_powerdown(int32_t height,int32_t ind,int32_t j,cJSON *json)
{
}

void steemit_feedpublish(int32_t height,int32_t ind,int32_t j,cJSON *json)
{
}

void steemit_accountwitness(int32_t height,int32_t ind,int32_t j,cJSON *json)
{
}

void iguana_accounts(char *keytype)
{
    long filesize; cJSON *json,*array,*item,*posting,*auths,*json2; int32_t i,n,m; char *str,*str2,*postingkey,*name,*key,fname[128],cmd[512]; FILE *postingkeys;
    if ( (str= OS_filestr(&filesize,"accounts.txt")) != 0 )
    {
        if ( (json= cJSON_Parse(str)) != 0 )
        {
            if ( (array= jarray(&n,json,"result")) != 0 && (postingkeys= fopen("keys.c","wb")) != 0 )
            {
                fprintf(postingkeys,"char *%skeys[][2] = {\n",keytype);
                for (i=0; i<n; i++)
                {
                    item = jitem(array,i);
                    if ( (name= jstr(item,"name")) != 0 && (posting= jobj(item,keytype)) != 0 )
                    {
                        if ( (auths= jarray(&m,posting,"key_auths")) != 0 )
                        {
                            item = jitem(auths,0);
                            if ( is_cJSON_Array(item) != 0 && (key= jstri(item,0)) != 0 )
                            {
                                sprintf(fname,"/tmp/%s",name);
                                sprintf(cmd,"curl --url \"http://127.0.0.1:8091\" --data \"{\\\"id\\\":444,\\\"method\\\":\\\"get_private_key\\\",\\\"params\\\":[\\\"%s\\\"]}\" > %s",key,fname);
                                system(cmd);
                                if ( (str2= OS_filestr(&filesize,fname)) != 0 )
                                {
                                    if ( (json2= cJSON_Parse(str2)) != 0 )
                                    {
                                        if ( (postingkey= jstr(json2,"result")) != 0 )
                                        {
                                            //miner = ["supernet", "5J4gTpk4CMBdPzgaRj7yNXDZTzBBQ41bNyJTqHbBi7Ku6v75bXa"]
                                            //fprintf(postingkeys,"miner = [\"%s\", \"%s\"]\n",name,postingkey);
                                            fprintf(postingkeys,"witness = \"%s\"\n",name);
                                            //fprintf(postingkeys,"{ \"%s\", \"%s\" },",name,postingkey);
                                        }
                                        else printf("no result in (%s)\n",jprint(json2,0));
                                        free_json(json2);
                                    } else printf("couldnt parse (%s)\n",str2);
                                    free(str2);
                                } else printf("couldnt load (%s)\n",fname);
                            }
                        }
                    }
                }
                fprintf(postingkeys,"\n};\n");
                fclose(postingkeys);
            }
            free_json(json);
        }
        free(str);
    }
}

void tradebots_LP(char *configjsonstr,char *arg)
{
    char *retstr,*cmdstr; int32_t i,tallymode=0,repeat,lastheight=0,j,n,one,height = -1; cJSON *obj,*json,*operations,*item,*retjson,*result,*props,*transactions;
    if ( configjsonstr != 0 && (json= cJSON_Parse(configjsonstr)) != 0 )
    {
        // process config
        free_json(json);
    }
    strcpy(Articles.name,"Articles");
    strcpy(Comments.name,"Comments");
    strcpy(Votes.name,"Votes");
    if ( (retstr= STEEM_getstate(0)) == 0 )
        return;
    for (i=0; i<sizeof(Whales)/sizeof(*Whales); i++)
        whale_search(1,Whales[i]);
    if ( arg != 0 )
    {
        if ( strcmp(arg,"taker") == 0 )
        {
            steemit_tradehistory("taker");
            return;
        }
        else if ( strcmp(arg,"active") == 0 )
        {
            iguana_accounts("active");
            return;
        }
        if ( strcmp(arg,"tally") == 0 )
            tallymode = 1;
    }
    if ( (retjson= cJSON_Parse(retstr)) != 0 )
    {
        if ( (result= jobj(retjson,"result")) != 0 )
        {
            if ( (props= jobj(result,"props")) != 0 )
            {
                if ( jobj(props,"head_block_number") != 0 )
                    height = juint(props,"head_block_number");
            }
        }
        free_json(retjson);
    }
    //printf("ht.%d retstr.(%s)\n",height,retstr);
    free(retstr);
    printf("Start %s from %d instead, tallymode.%d\n",TRADEBOT_NAME,height,tallymode);
    Startheight = init_startheight(height);
    if ( tallymode != 0 )
        height = (Startheight - 24*30*3600/3);
    while ( height >= 0 )
    {
        if ( tallymode != 0 && height == Startheight )
        {
            printf("reached Startheight.%d, getchar()\n",Startheight);
            steemit_summary(Startheight);
            getchar();
            exit(0);
        }
        if ( (retstr= STEEM_getblock(height)) != 0 )
        {
            if ( (retjson= cJSON_Parse(retstr)) != 0 )
            {
                if ( (result= jobj(retjson,"result")) != 0 )
                {
                    if ( (transactions= jarray(&n,result,"transactions")) != 0 )
                    {
                        if ( tallymode == 0 )
                            printf("lag.%d ht.%d n.%d\n",height-Startheight,height,n);
                        for (i=0; i<n; i++)
                        {
                            item = jitem(transactions,i);
                            if ( (operations= jarray(&one,item,"operations")) != 0 )
                            {
                                if ( 0 && tallymode == 0 )
                                    printf("one.%d: ",one);
                                for (j=0; j<one; j++)
                                {
                                    item = jitem(operations,j);
                                    if ( is_cJSON_Array(item) != 0 && cJSON_GetArraySize(item) == 2 )
                                    {
                                        cmdstr = jstr(jitem(item,0),0);
                                        obj = jitem(item,1);
                                        if ( cmdstr != 0 && obj != 0 )
                                        {
                                            //printf("%s ",jprint(item,0));
                                            if ( 0 && tallymode == 0 )
                                                printf("%d %s\n",j,cmdstr);
                                            if ( strcmp("vote",cmdstr) == 0 )
                                                steemit_vote(height,i,j,obj);
                                            else if ( (tallymode != 0 || height >= Startheight) && strcmp("comment",cmdstr) == 0 )
                                                steemit_comment(height,i,j,obj,height >= Startheight);
                                            else if ( height >= Startheight )
                                            {
                                                if ( strcmp("limit_order_create",cmdstr) == 0 )
                                                    steemit_limitorder(height,i,j,obj);
                                                else if ( strcmp("convert",cmdstr) == 0 )
                                                    steemit_convert(height,i,j,obj);
                                                else if ( strcmp("custom_json",cmdstr) == 0 )
                                                    steemit_customjson(height,i,j,obj);
                                                else if ( strcmp("transfer_to_vesting",cmdstr) == 0 )
                                                    steemit_powerup(height,i,j,obj);
                                                else if ( strcmp("account_update",cmdstr) == 0 )
                                                    steemit_accountupdate(height,i,j,obj);
                                                else if ( strcmp("transfer",cmdstr) == 0 )
                                                    steemit_transfer(height,i,j,obj);
                                                else if ( strcmp("limit_order_cancel",cmdstr) == 0 )
                                                    steemit_cancelorder(height,i,j,obj);
                                                else if ( strcmp("delete_comment",cmdstr) == 0 )
                                                    steemit_deletecomment(height,i,j,obj);
                                                else if ( strcmp("pow",cmdstr) == 0 )
                                                    steemit_pow(height,i,j,obj);
                                                else if ( strcmp("feed_publish",cmdstr) == 0 )
                                                    steemit_feedpublish(height,i,j,obj);
                                                else if ( strcmp("withdraw_vesting",cmdstr) == 0 )
                                                    steemit_powerdown(height,i,j,obj);
                                                else if ( strcmp("account_witness_vote",cmdstr) == 0 )
                                                    steemit_accountwitness(height,i,j,obj);
                                                else printf("%d.%d.%d: %s.(%s)\n",height,i,j,cmdstr,jprint(obj,0));
                                            }
                                        } else printf("%d.%d: unexpected paired item.(%s)\n",height,i,jprint(item,0));
                                    } else printf("%d.%d: unexpected unpaired item.(%s)\n",height,i,jprint(item,0));
                                }
                            }
                        }
                    } else if ( is_cJSON_Null(result) == 0 && jstr(result,"previous") == 0 )
                        printf("ht.%d no transactions in result.(%s)\n",height,jprint(result,0));
                    if ( is_cJSON_Null(result) == 0 )
                    {
                        FILE *fp;
                        if ( (fp= fopen(TRADEBOT_NAME,"wb")) != 0 )
                        {
                            // printf("startheight.%d for %s\n",height,TRADEBOT_NAME);
                            fprintf(fp,"%d\n",height);
                            fclose(fp);
                        } else printf("error saving startheight.%d for %s\n",height,TRADEBOT_NAME);
                        height++, repeat = 0;
                        if ( 0 && tallymode != 0 && (height % 1000) == 0 )
                            disp_vote_totals(height);
                    }
                } else printf("ht.%d no result in (%s)\n",height,jprint(retjson,0));
                //printf("ht.%d blockstr.(%s)\n",height,retstr);
                free_json(retjson);
            } else printf("ht.%d couldnt parse.(%s)\n",height,retstr);
            free(retstr);
        } else printf("error getting ht.%d\n",height);
        if ( height >= Startheight )
            sleep(1);
        if ( height == lastheight && ++repeat > 3 )
            height++, repeat = 0, lastheight = height;
#ifdef __APPLE__
        continue;
#endif
    }
    printf("done whale watching, hope you enjoyed the show\n");
}