#include "SQLiteModule.h"
#include "../utility/utility.h"
#include "../3rdParty/easylogging/easylogging++.h"

#define BUFFER_SIZE             1024 

SQLite::SQLite()
{
    pDB=NULL;
    errMsg=NULL;
}

SQLite::~SQLite()
{

}

bool SQLite::initSQLite()
{
    std::string strDbFileName;      //*.db name
    std::string strPath = GetProcDir(); 
    strPath.append("fmdata.db");
    strDbFileName = strPath;

    int res = sqlite3_open(strDbFileName.c_str(), &pDB);
    LOG(INFO)<<"DbFileName:"<<strDbFileName.c_str();
    if(res != SQLITE_OK)
    {
        LOG(ERROR)<<"open db file failed:"<<strDbFileName.data();
        return false;
    }
    try
    {
        _createTable(); 
    }
    catch(std::exception &ex)
    {
        LOG(ERROR)<<"create table exception:"<<ex.what();
        return false;
    }
    return true;
}

bool SQLite::_createTable()
{
    bool rlt=true;
    std::string strTableName="fmOrderFailed";
    if(!isTableExist(pDB,strTableName)){
        char szCreate[1024]={0};
        sprintf(szCreate,"create table %s(id BIGINT NOT NULL,\
                                          msg TEXT,\
                                          logtime TIMESTAMP default (datetime('now', 'localtime')),\
                                          PRIMARY KEY (id))",strTableName.c_str());
        if(!_execSql(szCreate)){
            exit(0);
        }
    }
    else{
        LOG(INFO)<<strTableName.data()<<" has exist";
    }
    return rlt;

}

void SQLite::closeSQLite()
{
    if(pDB)
        sqlite3_close(pDB); 
}

bool SQLite::isTableExist(sqlite3 *sqDb, std::string strTableName)
{
    char szQuery[1024] = {0};
    sprintf(szQuery, "SELECT count(*) FROM sqlite_master WHERE type=\"table\" AND name=\"%s\"", strTableName.c_str());
    sqlite3_stmt *pstmt;
    sqlite3_prepare(sqDb, szQuery, strlen(szQuery), &pstmt, NULL);
    sqlite3_step(pstmt);
    int count=sqlite3_column_int(pstmt,0);
    sqlite3_finalize(pstmt);
    if(count > 0)
       return true;
    return false;
}

int SQLite::isRecordExist(std::string strTable,std::string strKey)
{
    char* lpSql = new char[BUFFER_SIZE];
    sprintf(lpSql, "select * from %s where id = '%s'",strTable.c_str(),strKey.c_str());    
    char** pResult;  
    int nRow = 0;   
    int nCol = 0;
    int nResult = sqlite3_get_table(pDB,lpSql,&pResult,&nRow,&nCol,&errMsg);  
    delete[] lpSql;
    if (nResult != SQLITE_OK)  
    {
        LOG(ERROR)<<"sqlite3_get_table error:"<<errMsg;
        return -1;
    }
    return nRow;
}

bool SQLite::_execSql(const char* sql)
{
    bool rlt=true;
    int res = sqlite3_exec(pDB,sql, 0, 0, &errMsg); 
    if(res != SQLITE_OK)
    {
        LOG(ERROR)<<"exec sql failed:"<<sql<<"  failed info:"<<errMsg;
        rlt=false;
    }
    return rlt;
}

bool SQLite::insert(const char* sql)
{
    return _execSql(sql);
}

bool SQLite::update(const char* sql)
{
    return _execSql(sql);
}

bool SQLite::remove(const char* sql)
{
    return _execSql(sql);
}

std::vector<orderSendFailedObj> vecOrders;
int callbackQuery(void* data,int n_columns,char** column_values,char** column_names)
{   
    try
    {
        orderSendFailedObj order;
        order.timestamp=atoll(column_values[0]);
        order.order_json=column_values[1];
        vecOrders.push_back(order);
        
    }
    catch(std::exception &ex)
    {
        LOG(ERROR)<<"read data failed:"<<ex.what();
        return -1;
    }

    return 0;
}

void SQLite::query(const char* sql,std::vector<orderSendFailedObj> &vecFailedOrders)
{
    vecOrders.clear();
    int rlt = sqlite3_exec(pDB,sql,callbackQuery, 0, &errMsg);
    if(rlt!= SQLITE_OK)
    {
        LOG(ERROR)<<"query failed:"<<errMsg;
    }
    else{
        vecFailedOrders.assign(vecOrders.begin(), vecOrders.end());
    }
}
