#include "ytcore.h"
#include <stdio.h>
#include "yt_unit_shm.h"

YT_UNIT_SHM *ytShm;

extern bool myLog;
extern bool myDebug;

BpCore::BpCore(QObject *parent) :
    QObject(parent)
{
    timeoutworking=false;
    CHour = QDateTime::currentDateTime().time().hour();
    CMin = QDateTime::currentDateTime().time().minute();
    TMin = QDateTime::currentDateTime().time().minute();
    UskyID = "90001";
    UskyIP = "172.16.120.191";
    UskyPort = 51211;
    LocIP = "192.168.1.100";
    GateWay = "192.168.1.1";
    NetMask = "255.255.255.0";
    MacAddr = "0:A1:E9:40:6D:EA";
    timer = new QTimer(this);
    connect(timer,SIGNAL(timeout()),this,SLOT(time_out()));
    db = QSqlDatabase::addDatabase("QSQLITE","conf_db");
    db.setDatabaseName(QString(CONF_DB));
    recdb = QSqlDatabase::addDatabase("QSQLITE","rec_db");
    recdb.setDatabaseName(QString(REC_DB));
    if((!db.open())||(!recdb.open()))
    {
        system("echo 'Database open failed.\n'");
        exit(-1);
    }
    db_init();
    if(!shm_load())
    {
        system("echo 'Memory load failed.\n'");
        exit(-1);
    }
    printf("shm ok\n");
    uServerThread = new UServerThread(this,UskyIP,UskyPort);

    logThread = new LogThread(this);
    logThread->start();
    if(myLog)
        logThread->appendLog(QString("[%1] main appliction start\r\n")
                         .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
    dbThread = new DBThread(this,&db,&recdb);
    connect(dbThread,SIGNAL(log(QString)),this,SLOT(log(QString)));
    connect(dbThread,SIGNAL(dbg_log(QString)),this,SLOT(dbg_log(QString)));
    ytShm->dogTimeList.dogTime[CORE_MAIN].IDX = CORE_MAIN;
    ytShm->dogTimeList.dogTime[CORE_MAIN].WAITSEC = 30;
    ytShm->dogTimeList.dogTime[CORE_MAIN].ENABLED = 0x01;
    dbThread->start();
    uServerThread->start();
    for(quint8 CommId=0;CommId<4;CommId++)
    {
        if(ytShm->commList.comm[CommId].ENABLED==0x01)
        {
            dnThread[CommId] = new DNCommThread(this,CommId,true,QString(ytShm->commList.comm[CommId].PATH));
            dnThread[CommId]->setCommType(ytShm->commList.comm[CommId].CommType);
            connect(dnThread[CommId],SIGNAL(log(QString)),this,SLOT(log(QString)));
            dnThread[CommId]->start();
        }
    }
}

void BpCore::run()
{
    timer->start(500);
    printf("start\n");
}



void BpCore::log(QString txt)
{
    if(myLog)
        logThread->appendLog(txt);
}

void BpCore::dbg_log(QString txt)
{
    if(myDebug)
        logThread->appendDbgLog(txt);
}

void BpCore::confsql(QString sql)
{
    dbThread->appendSQL(1,sql);
}

void BpCore::recsql(QString sql)
{
    dbThread->appendSQL(3,sql);
}


void BpCore::time_out()
{
    if(timeoutworking)
        return;
    timeoutworking=true;
    QDateTime dt = QDateTime::currentDateTime();
    unsigned int t = dt.toTime_t();
    ytShm->dogTimeList.dogTime[CORE_MAIN].LASTFEED = t;
    QString dataStr = "";
    QString cloumn = "";

    if(TMin!=(QDateTime::currentDateTime().time().minute())){
        TMin=QDateTime::currentDateTime().time().minute();
        for(int cid=0;cid<4;cid++){
            for(int pid=1;pid<32;pid++){
                if(ytShm->sPointList.sPoint[cid][pid].ENABLED==0x01){
                    dataStr.append(QString(",%1").arg(ytShm->spStatusList.spStatus[cid][pid].REALTIME_VALUE));
                }
            }
        }
        //printf("dataStr: %s, t: %d\n",dataStr.toUtf8().data(),t);
        QString sql = QString("insert into yt_rec_realdata (Id,CommId,P_0_001,P_0_002,P_0_003,P_0_004,P_0_005,P_0_006,P_0_007,P_0_008,P_0_009,P_0_010,P_0_011,P_0_012,P_0_013,P_0_014,P_0_015,P_0_016,P_0_017,P_0_018,P_0_019,P_0_020,P_0_021,P_0_022,P_0_023,P_0_024,P_0_025,P_0_026,P_0_027,P_0_028,P_0_029,P_0_030,P_0_031, StoreTime)values(NULL,0%1,%2)").arg(dataStr).arg(t);
        dbThread->appendSQL(3,sql);
        uServerThread->appendAllRealdata();
    }

    timeoutworking=false;
}

bool BpCore::chk_table(QString tbname, QStringList tables)
{
    printf("chk table %s\n",tbname.toUtf8().data());
    for(int i=0;i<tables.length();i++)
    {
        if(strcmp(tables.at(i).toUtf8().data(),tbname.toUtf8().data())==0)
            return true;
    }
    return false;
}

void BpCore::db_init()
{
    if(!chk_table("yt_t_syscom",db.tables()))
    {
        if(db.transaction())
        {
            db.exec(QString("create table yt_t_syscom (Id integer, UskyID text, UskyIP text, UskyPort integer)"));
            db.exec(QString("insert into yt_t_syscom (Id, UskyID, UskyIP, UskyPort) values (0, '%1','%2','%3')").arg(UskyID).arg(UskyIP).arg(UskyPort));
            db.commit();
        }
    }
    if(!chk_table("yt_t_locnet",db.tables())){
        if(db.transaction())
        {
            db.exec(QString("create table yt_t_locnet (loc_ip text, gateway text, netmask text, macaddr text)"));
            db.exec(QString("insert into yt_t_locnet (loc_ip, gateway, netmask, macaddr) values ('%1','%2','%3','%4')")
                    .arg(LocIP).arg(GateWay).arg(NetMask).arg(MacAddr));
            db.commit();
        }
    }
    if(!chk_table("yt_t_comm",db.tables()))
    {
        if(db.transaction())
        {
            db.exec(QString("create table yt_t_comm (Id integer, CommType integer, CommPath text, Enabled integer)"));
            for(int i=0;i<4;i++)
            {
                if(i==0)
                    db.exec(QString("insert into yt_t_comm (Id, CommType, CommPath, Enabled) values (0,1,'/dev/ttySAC2',1)"));
                else
                    db.exec(QString("insert into yt_t_comm (Id, CommType, CommPath, Enabled) values (%1,1,'/dev/ttyO%2',%3)")
                        .arg(i).arg(i).arg(0));
            }
            db.commit();
        }
    }
    if(!chk_table("yt_rec_data",recdb.tables()))
    {
        if(recdb.transaction())
        {
            recdb.exec(QString("create table yt_rec_data (Id integer primary key autoincrement, CommId integer, BusAdd integer, AveValue real, StoreTime integer, MaxValue real, MaxTime integer, MinValue real, MinTime integer)"));
            recdb.commit();
        }
    }
    if(!chk_table("yt_rec_realdata",recdb.tables()))
    {
        if(recdb.transaction())
        {
            recdb.exec(QString("CREATE TABLE yt_rec_realdata (Id integer primary key autoincrement,CommId integer,P_0_001 real,P_0_002 real,P_0_003 real,P_0_004 real,P_0_005 real,P_0_006	real,P_0_007 real,P_0_008 real,P_0_009 real,P_0_010 real,P_0_011 real,P_0_012 real,P_0_013 real,P_0_014 real,P_0_015 real,P_0_016 real,P_0_017 real,P_0_018 real,P_0_019 real,P_0_020 real,P_0_021 real,P_0_022 real,P_0_023 real,P_0_024 real,P_0_025 real,P_0_026 real,P_0_027 real,P_0_028 real,P_0_029 real,P_0_030 real,P_0_031 real,StoreTime integer)"));
            recdb.commit();
        }
    }

}

void BpCore::shm_init()
{
    QSqlQuery qry;
    QString sql = "select loc_ip, gateway, netmask, macaddr from yt_t_locnet";
//    printf("%s\n",sql.toUtf8().data());
    qry = db.exec(sql);
    if(qry.next()){
        LocIP = qry.value(0).toString();
        GateWay = qry.value(1).toString();
        NetMask = qry.value(2).toString();
        MacAddr = qry.value(3).toString();
        sprintf(ytShm->unitNet.LocIP,"%s",LocIP.toUtf8().data());
        sprintf(ytShm->unitNet.GateWay,"%s",GateWay.toUtf8().data());
        sprintf(ytShm->unitNet.NetMask,"%s",NetMask.toUtf8().data());
        sprintf(ytShm->unitNet.MacAddr,"%s",MacAddr.toUtf8().data());
        ytShm->unitNet.UNSAVED=0x00;
    }
    qry.clear();
    sql = "select Id, CommType, CommPath, Enabled from yt_t_comm";
//    printf("%s\n",sql.toUtf8().data());
    qry = db.exec(sql);
    while(qry.next())
    {
        quint8 id = qry.value(0).toUInt()&0xff;
        quint16 commType = qry.value(1).toUInt()&0xffff;
        QString commPath = qry.value(2).toString();
        quint8 enabled = ((qry.value(3).toUInt()&0xff)==0x01)?0x01:0x00;
        ytShm->commList.comm[id].IDX = id;
        ytShm->commList.comm[id].CommType = commType;
        sprintf(ytShm->commList.comm[id].PATH,"%s",commPath.toUtf8().data());
        ytShm->commList.comm[id].ENABLED = enabled;
        ytShm->commList.comm[id].UNSAVED = 0x00;
//        printf("ID:%d\t ENABLED:%d\tPATH:%s\n",id,enabled,commPath.toUtf8().data());
    }
    qry.clear();
    qry = db.exec("select Id, SelfId, Key, UpUrl, UskyID, UskyIP, UskyPort, AgboxEnabled from yt_t_syscom");
    if(qry.next())
    {
        UskyID = qry.value(4).toString();
        UskyIP = qry.value(5).toString();
        UskyPort = qry.value(6).toUInt()&0xffff;
        sprintf(ytShm->sysShm.USKYID,"%s",UskyID.toUtf8().data());
        sprintf(ytShm->sysShm.USKYSERIP,"%s",UskyIP.toUtf8().data());
        ytShm->sysShm.USKYPORT = UskyPort;
    }
    qry.clear();
    sql = "select CommId, BusAdd, Enabled, Name, PnoType, PnoAlarm, PnoValue, PnoDly, PnoAd, Offset, OffsetFlag, PnoMax, PnoMin, AlarmH, AlarmL,SubType from yt_t_point";
//    printf("%s\n",sql.toUtf8().data());
    qry = db.exec(sql);
    while(qry.next())
    {
        quint8 commId = qry.value(0).toUInt()&0xff;
        quint8 busAdd = qry.value(1).toUInt()&0xff;
        quint8 enabled = ((qry.value(2).toUInt()&0xff)==0x01)?0x01:0x00;
        QString name = qry.value(3).toString();
        quint8 pnotype = qry.value(4).toUInt()&0xff;
        quint8 pnoalarm = qry.value(5).toUInt()&0xff;
        quint8 pnovalue = qry.value(6).toUInt()&0xff;
        quint8 pnodly = qry.value(7).toUInt()&0xff;
        quint8 pnoad = qry.value(8).toUInt()&0xff;
        quint8 offset = qry.value(9).toUInt()&0xff;
        quint8 offsetflag = qry.value(10).toUInt()&0xff;
        float pnomax = qry.value(11).toFloat();
        float pnomin = qry.value(12).toFloat();
        float alarmh = qry.value(13).toFloat();
        float alarml = qry.value(14).toFloat();
        uint subtype = qry.value(15).toUInt();
        if(commId<4){
            ytShm->sPointList.sPoint[commId][busAdd].COMM_IDX = commId;
            ytShm->sPointList.sPoint[commId][busAdd].BUS_ADD = busAdd;
            ytShm->sPointList.sPoint[commId][busAdd].ENABLED = enabled;
            bzero(ytShm->sPointList.sPoint[commId][busAdd].NAME,sizeof(ytShm->sPointList.sPoint[commId][busAdd].NAME));
            sprintf(ytShm->sPointList.sPoint[commId][busAdd].NAME,"%s",name.toUtf8().data());
            ytShm->sPointList.sPoint[commId][busAdd].PNO_TYPE = pnotype;
            ytShm->sPointList.sPoint[commId][busAdd].PNO_ALARM = pnoalarm;
            ytShm->sPointList.sPoint[commId][busAdd].PNO_VALUE = pnovalue;
            ytShm->sPointList.sPoint[commId][busAdd].PNO_DLY = pnodly;
            ytShm->sPointList.sPoint[commId][busAdd].PNO_AD = pnoad;
            ytShm->sPointList.sPoint[commId][busAdd].OFFSET = offset;
            ytShm->sPointList.sPoint[commId][busAdd].OFFSET_FLAG = offsetflag;
            ytShm->sPointList.sPoint[commId][busAdd].PNO_MAX = pnomax;
            ytShm->sPointList.sPoint[commId][busAdd].PNO_MIN = pnomin;
            ytShm->sPointList.sPoint[commId][busAdd].ALARM_H = alarmh;
            ytShm->sPointList.sPoint[commId][busAdd].ALARM_L = alarml;
            ytShm->sPointList.sPoint[commId][busAdd].SUB_TYPE = subtype;
            ytShm->sPointList.sPoint[commId][busAdd].UNSAVED = 0x00;
        }
    }

}

bool BpCore::shm_load()
{
    int shmid;
    key_t key;
    if((key = ftok(SHM_PATH,(int)SHM_PORT))==-1)
        return false;
    if((shmid = shmget(key,sizeof(YT_UNIT_SHM),IPC_CREAT|0666))==-1)
        return false;
    ytShm = (YT_UNIT_SHM *)shmat(shmid,NULL,0);

    shm_init();
    return true;
}
