#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "cJSON.h"
#include "com_api.h"
#include "kk_hal.h"
#include "kk_product.h"
#include "kcloud_config.h"
#include "infra_sha256.h"
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include "kk_log.h"
#include "../../common/curl/include/curl/curl.h"

int kk_check_config_file(char* path,char **config)
{
	FILE *fp;  
    int filesize = 0;
    char *buf = NULL; 
    INFO_PRINT("path:%s\n",path); 
    if((access(path,F_OK)) == 0){
        fp = fopen(path, "r");
        if(fp != NULL){
            fseek(fp, 0L, SEEK_END);
            filesize = ftell(fp);
            buf = malloc(filesize+1);
            if(buf == NULL){
                ERROR_PRINT("MALLOC FAIL!!!\n");
                fclose(fp);
                return -1;
            }
            memset(buf,0x0,filesize+1);
            fseek(fp, 0L, SEEK_SET);
            fread(buf, 1, filesize, fp); 
            INFO_PRINT("buf:%s\n",buf);
            *config = buf; 
             fclose(fp);
            return 0;
        }
    }else{
        return -1;
    }
}
static int _kk_parse_config_dl_host(cJSON *configInfo,char *url){
    char ccuid[32] = {0};
    if(configInfo == NULL ||url == NULL){
        return -1;
    }
    KK_Get_ccuid(ccuid);
    cJSON *host = cJSON_GetObjectItem(configInfo,"host");
    cJSON *proto = cJSON_GetObjectItem(configInfo,"proto");
    cJSON *port = cJSON_GetObjectItem(configInfo,"port");
    if(host != NULL && proto != NULL && port != NULL){
        sprintf(url,"%s://%s:%d/api/1.0/ccu/%s/cloud_entry",proto->valuestring,host->valuestring,port->valueint,&ccuid[4]);
        INFO_PRINT("%s\n",url); 
        return 0;
    }  
    return -1;  
}
static int _kk_get_config_dl_host(char *buf,char *url){
    cJSON *configInfo = NULL;
    if(buf == NULL || url == NULL){
        ERROR_PRINT("param error\n");
        return -1;
    }
    cJSON* configObj = cJSON_Parse(buf);
    if(configObj == NULL){
        ERROR_PRINT("cJSON_Parse error\n");
        return -2;
    }
    cJSON *data = cJSON_GetObjectItem(configObj,"data");
    if(data == NULL){
        configInfo = cJSON_GetObjectItem(configObj,"iot_ops_entry");
    }else{
        configInfo = cJSON_GetObjectItem(data,"iot_ops_entry");
    }
    _kk_parse_config_dl_host(configInfo,url);
    cJSON_Delete(configObj);
    return 0;
}
static int s_getSize = 0;
size_t receive_config_data(void *buffer, size_t size, size_t nmemb, FILE *file){
	INFO_PRINT("buffer:%s\n",buffer);
    size_t s_getSize = fwrite(buffer, size, nmemb, file);
    return s_getSize;
}
int kk_dl_config(){
    int ret = 0;
    char *configData = NULL;
    int defaultFlag = 0;
    char url[512] = {0};
    FILE *file;
    CURLcode res; 
    CURL* curl;     
    char ccuid[32] = {0};
    char sds[128] = {0};
    static int s_count = 0;
    KK_Get_ccuid(ccuid);

    ret = kk_check_config_file(KK_DEFAULT_CONFIG_FILE_PATH,&configData);   
    if(ret == 0){
        ret = _kk_get_config_dl_host(configData,url);
        if(ret == 0){       
again:            
            s_count++;
            curl = curl_easy_init();  
            if (NULL == curl){
                if(configData != NULL){
                    free(configData);
                    configData = NULL;
                }
                return -1;
            }	
            if(access(KK_CONFIG_FILE_PATH,F_OK) != 0){
                char cmd[128] = {0};
                sprintf(cmd,"touch %s",KK_CONFIG_FILE_PATH);
                system(cmd);
            }
            file = fopen(KK_CONFIG_FILE_PATH,"r+");
            curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
            curl_easy_setopt(curl, CURLOPT_URL, url);
            //curl_easy_setopt(curl, CURLOPT_POSTFIELDS, WEATHER_DATA);
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, receive_config_data); 
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)file);
            curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
            curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
            curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
            curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, 30000);
            curl_easy_setopt(curl, CURLOPT_TIMEOUT, 100);
            curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);  //支持服务器跳转
            curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);  // enable TCP keep-alive for this transfer 
            curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);	// keep-alive idle time to 120 seconds 
            curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L);	// interval time between keep-alive probes: 60 seconds   
            struct curl_slist* headers = NULL;	
            sprintf(sds,"sds_ccu_id:%s",&ccuid[4]);
            INFO_PRINT("sds:%s\n",sds);
            headers = curl_slist_append(headers, "Content-Type:application/json");
            headers = curl_slist_append(headers, sds);
            curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
            curl_easy_setopt(curl, CURLOPT_POST, 0);//设置为非0表示本次操作为POST	           
            res = curl_easy_perform(curl);
            if(res != CURLE_OK){
                curl_easy_cleanup(curl);
                fclose(file);
                ERROR_PRINT("WCHEN[%s][%d]res:%d\n",__FUNCTION__,__LINE__,res);
                if(configData != NULL){
                    free(configData);
                    configData = NULL;
                }
                if(s_count < 15){
                    sleep(3);
                    ERROR_PRINT("get config again\n");
                    goto again;    
                }else{
                    ERROR_PRINT("get config timeout\n");
                    return -1;
                }    
            } 
            curl_easy_cleanup(curl);
            fclose(file);    
        }     
    }
    if(configData != NULL){
        free(configData);
        configData = NULL;
    }
    return 0;
}