#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#include "xieneng_car_common.h"

extern struct detail_info detail[MAX_LECU_CNT];

int store_vol_temp(xieneng_car_var_t *var, unsigned int nowtim)
{
    int i, j, k;
    node_cfg_t *node = NULL;
    time_t now = (time_t) nowtim;
    int ret = 0;
    static sqlite3_stmt * packdb = NULL;
    static sqlite3_stmt *stmt3 = NULL;
    static sqlite3_stmt *delete_stmt3 = NULL;
    static time_t last_delete = 0;

    if (var->db == NULL)
    {
        dy_syslog(LOG_ERR, "db file is NULL");
        return -1;
    }

    if (stmt3 == NULL)
    {
        ret = sqlite3_prepare_v2(var->db, XIENENG_CAR_INSERT_SQL, strlen(XIENENG_CAR_INSERT_SQL), &stmt3, 0);
        if (ret != SQLITE_OK)
        {
            dy_syslog(LOG_ERR, "prepare error %s\n", sqlite3_errmsg(var->db));
            sqlite3_finalize(stmt3);
            stmt3 = NULL;
            return ret;
        }
    }

    if (delete_stmt3 == NULL)
    {
        ret = sqlite3_prepare_v2(var->db, XIENENG_CAR_DELETE_DATA_SQL, strlen(XIENENG_CAR_DELETE_DATA_SQL), &delete_stmt3, 0);
        if (ret != SQLITE_OK)
        {
            dy_syslog(LOG_ERR, "prepare error %s\n", sqlite3_errmsg(var->db));
            sqlite3_finalize(delete_stmt3);
            delete_stmt3 = NULL;
        }
    }

    if (packdb == NULL) {
        ret = sqlite3_prepare_v2(var->db, XIENENG_CAR_PACK_DATABASE, strlen(XIENENG_CAR_PACK_DATABASE), &packdb, 0);
        if (ret != SQLITE_OK) {
            dy_syslog(LOG_ERR, "prepare error %s\n", sqlite3_errmsg(var->db));
            sqlite3_finalize(packdb);
            packdb = NULL;
        }
    }

    k = 0;
    for (j = 0; j < MAX_LECU_CNT; j++)
    {
        time_t timestamp;
        const int maxdelta = 10;
        const int anchor = (int) (now - 2);
        int dowrite = 0, uptim = 0, delta = 60;
        if (!dowrite) {
            timestamp = detail[j].update_time;
            uptim = (int) timestamp;
            delta = (int) (timestamp - now);
            if (delta < maxdelta)
                dowrite = -1;
        }
        if (!dowrite) {
            timestamp = detail[j].uplast[0];
            uptim = (int) timestamp;
            delta = (int) (timestamp - now);
            if (delta < maxdelta)
                dowrite = -1;
        }
        if (!dowrite) {
            timestamp = detail[j].uplast[1];
            uptim = (int) timestamp;
            delta = (int) (timestamp - now);
            if (delta < maxdelta)
                dowrite = -1;
        }
        if (!dowrite) {
            timestamp = detail[j].uplast[2];
            uptim = (int) timestamp;
            delta = (int) (timestamp - now);
            if (delta < maxdelta)
                dowrite = -1;
        }
        if (detail[j].id != 0 && dowrite)
        {
            delta = uptim - anchor;
            if (k == 0)
                uptim = anchor;
            else if (delta <= -3)
                uptim = anchor - 2;
            else if (delta >= 3)
                uptim = anchor + 2;
            k++;
            sqlite3_bind_int(stmt3, 1, detail[j].id);
            sqlite3_bind_int(stmt3, 2, uptim);
            sqlite3_bind_blob(stmt3, 3, detail[j].start, detail[j].end - detail[j].start + 1, SQLITE_TRANSIENT);
            sqlite3_bind_int(stmt3, 4, 0);
            ret = sqlite3_step(stmt3);
            if (ret != SQLITE_DONE)
            {
                dy_syslog(LOG_ERR, "Insert data error: %d", ret);
            }

            //重新初始化该sqlite3_stmt对象绑定的变量。
            sqlite3_reset(stmt3);
        }
    }

    if (now - last_delete > 3600 * 6)
    {
        time_t ts_threshold = now - 60 * 60 * 24 * 15;
        sqlite3_bind_int(delete_stmt3, 1, ts_threshold);

        ret = sqlite3_step(delete_stmt3);
        if (ret != SQLITE_DONE)
        {
            dy_syslog(LOG_ERR, "delete data error: %d", ret);
        }

        //重新初始化该sqlite3_stmt对象绑定的变量。
        sqlite3_reset(delete_stmt3);
        last_delete = now;

        /* pack database to save storage space */
        ret = (packdb != NULL) ? sqlite3_step(packdb) : -1;
        if (ret != SQLITE_DONE) {
            dy_syslog(LOG_ERR, "Pack database error: %d", ret);
        }
        sqlite3_reset(packdb);
    }

    return 0;
}

static int xieneng_car_db_create_table(sqlite3 *db, char *table_name, char *table_item)
{
    char sql[512] = {0};
    int ret, nRow, nCol;
    char **pResult;
    char *errMsg;

    if (db == NULL)
    {
        return -1;
    }

    snprintf(sql, sizeof(sql) - 1, "select count(*)  from sqlite_master where type='table' and name = '%s';", table_name);
    ret = sqlite3_get_table(db, sql, &pResult, &nRow, &nCol, &errMsg);
    if (ret != 0 || atoi(pResult[1]) == 0)
    {
        memset(sql, 0, sizeof(sql));
        snprintf(sql, sizeof(sql) - 1, "CREATE TABLE %s (%s);", table_name, table_item);
        ret = sqlite3_exec(db, sql, 0, 0, &errMsg);
        if (errMsg)
        {
            dy_syslog(LOG_INFO, "[ERR] CREATE TABLE %s errMsg %s ", table_name, errMsg);
        }
    }
    sqlite3_free_table(pResult);

    return ret;
}

int xieneng_car_db_init(xieneng_car_var_t *var)
{
    char set_max_page_count[64] = {0};

    var->db = db_open_db(XIENENG_CAR_DB_PATH);
    sqlite3_exec(var->db, "PRAGMA synchronous = NORMAL;", NULL, NULL, NULL);
    sqlite3_exec(var->db, "PRAGMA journal_mode = WAL;", NULL, NULL, NULL);
    sqlite3_exec(var->db, "PRAGMA journal_size_limit = 16384;", NULL, NULL, NULL);
    sprintf(set_max_page_count, "PRAGMA max_page_count = %d;", (3 * 1024 * 1024) / 4);
    sqlite3_exec(var->db, set_max_page_count, NULL, NULL, NULL);
    xieneng_car_db_create_table(var->db, DATA_TABLE_NAME, DATA_TABLE_CREATE);
}

int xieneng_car_history_data(xieneng_car_var_t *var, cJSON *msg)
{
    int mi;
    char *buff = NULL;
    char cmd[64] = {0};

    GET_JSON_VALUE_INT(msg, "mi", mi);
    sprintf(cmd, "sh /app/ftp_trans.sh %d", mi);

    system_reply(cmd, &buff);
    if (buff != NULL)
    {
        tag_table_t ptag = {0};
        time_t now = time(NULL);
        cJSON *ver_json = NULL;
        ptag.data_type = DATA_TYPE_SERVICE;
        strcpy(ptag.identifier, "downLoadHisData");
        ptag.report_period = 0;
        ptag.time = now;

        strcpy(ptag.sn, var->sn_str);
        ptag.mi = mi;

        ver_json = cJSON_CreateObject();

        if (ver_json != NULL)
        {
            char *data_tmp = NULL;
            int filesize;
            char *p = NULL;

            sscanf(buff, "%d", &filesize);
            p = strstr(buff, "ftp://");

            cJSON_AddNumberToObject(ver_json, "downLoadFileSize", filesize);
            if (p != NULL)
            {
                cJSON_AddNumberToObject(ver_json, "downLoadStatus", 1);
                cJSON_AddStringToObject(ver_json, "downLoadUrl", p);
            }
            else
            {
                cJSON_AddNumberToObject(ver_json, "downLoadStatus", 2);
            }

            ptag.port = CANBUS_0;
            data_tmp = cJSON_Print(ver_json);
            if (strlen(data_tmp) > 2)
            {
                ptag.tag_node = data_tmp;
                pp_send_tag_data(var->session, &ptag);
            }
            cJSON_Delete(ver_json);
            ver_json = NULL;
            free(data_tmp);
        }

        free(buff);
    }

    return 0;
}
