#include "ZTAlarmGenerator.h"
#include "ZTAlarmGeneratorPage.h"
#include "ZTAlarms.h"
#include "ProtocolDefs.h"
#include <QFile>

CZTAlarmGenerator::CZTAlarmGenerator(QObject *parent)
{
    mAlarmGeneratorPageHandle = 0;

    mModbusZTEmulator = new CModbusZTMaster(&mZTModbusRepo);

    mZTModbusRepo.AddHRDataMap(2000,128);
    connect(mModbusZTEmulator,SIGNAL(ModbusMasterConnected(CModbusZTMaster*)),this,SLOT(ModbusMasterConnected(CModbusZTMaster*)));
    connect(mModbusZTEmulator,SIGNAL(ModbusMasterDisconnected(CModbusZTMaster*)),this,SLOT(ModbusMasterDisconnected(CModbusZTMaster*)));
    connect(mModbusZTEmulator,SIGNAL(ModbusMasterRepositoryUpdated()),this,SLOT(ModbusMasterRepositoryUpdated()));

    mModbusUpdateTimer = new QTimer();
    connect(mModbusUpdateTimer,&QTimer::timeout,this,&CZTAlarmGenerator::UpdateModbusTimerExpired);
    mModbusUpdateTimer->setSingleShot(false);
    mModbusUpdateTimer->setInterval(500);


    mWatchdogValue = false;
    mReadModbus = false;
    mIPAddress = "10.154.234.34";
}

CZTAlarmGenerator::~CZTAlarmGenerator()
{

}

void CZTAlarmGenerator::ModbusMasterConnected(CModbusZTMaster *ModbusZTMaster)
{
    mAlarmGeneratorPageHandle->ModbusMasterConnected();
    mModbusUpdateTimer->start();
}

void CZTAlarmGenerator::ModbusMasterDisconnected(CModbusZTMaster *ModbusMaster)
{
    mAlarmGeneratorPageHandle->ModbusMasterDisconnected();
    mModbusUpdateTimer->stop();
}

void CZTAlarmGenerator::ModbusMasterRepositoryUpdated()
{
    quint16 SEIFlags, SEIWD;
    bool OK,AN1Active,AN2Active;

    SEIWD = mZTModbusRepo.GetSingleReg(SEI_MODBUS_SEI_WATCHDOG_REG,&OK);
    SEIFlags = mZTModbusRepo.GetSingleReg(SEI_MODBUS_SEI_ALARMS_RESET_REG,&OK);

    AN1Active = ( (SEIFlags & SEI_MODBUS_SEI_ZT1_ALARM_RESET_MASK) != 0);
    AN2Active = ( (SEIFlags & SEI_MODBUS_SEI_ZT2_ALARM_RESET_MASK) != 0);

    mAlarmGeneratorPageHandle->UpdateSEIState(AN1Active,AN2Active,SEIWD);

}

int CZTAlarmGenerator::UpdateActiveAlarms(CZTAlarms *ActiveAlarms)
{
    quint16 WorkingReg, RankReg;

    ClearAllAlarms();

    //Set Comptage and Panne équipement alarms

    WorkingReg = 0;
    if(ActiveAlarms->mZT1AxleCountAlarm == true)
    {
        WorkingReg |= ZT1_V00_ALARM_FLAG_MASK;
    }
    if(ActiveAlarms->mZT1EquipmentFailureAlarm == true)
    {
        WorkingReg |= ZT1_PEQ1_ALARM_FLAG_MASK;
    }
    if(ActiveAlarms->mZT2AxleCountAlarm == true)
    {
        WorkingReg |= ZT2_V02_ALARM_FLAG_MASK;
    }
    if(ActiveAlarms->mZT2EquipmentFailureAlarm == true)
    {
        WorkingReg |= ZT2_PEQ2_ALARM_FLAG_MASK;
    }
    mZTModbusRepo.WriteSingleReg(MODBUS_MISC_DATA_BASE_REG_ADD,WorkingReg);

    WorkingReg = 0;
    RankReg = 0;

    for(int i = 0; i < ActiveAlarms->mZT1FNAlarmRanks.size(); i++)
    {
        switch(i + 1)
        {
            case 1:
            {
                WorkingReg |= ZT1_FN_FLAG_MASK_1;
                RankReg = ActiveAlarms->mZT1FNAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT1_RANK_FN_1_REG_ADD,RankReg);
                break;
            }
            case 2:
            {
                WorkingReg |= ZT1_FN_FLAG_MASK_2;
                RankReg = ActiveAlarms->mZT1FNAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT1_RANK_FN_2_REG_ADD,RankReg);
                break;
            }
            case 3:
            {
                WorkingReg |= ZT1_FN_FLAG_MASK_3;
                RankReg = ActiveAlarms->mZT1FNAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT1_RANK_FN_3_REG_ADD,RankReg);
                break;
            }
            case 4:
            {
                WorkingReg |= ZT1_FN_FLAG_MASK_4;
                RankReg = ActiveAlarms->mZT1FNAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT1_RANK_FN_4_REG_ADD,RankReg);
                break;
            }
        }
    }


    for(int i = 0; i < ActiveAlarms->mZT1PGAlarmRanks.size(); i++)
    {
        switch(i + 1)
        {
            case 1:
            {
                WorkingReg |= ZT1_PG_FLAG_MASK_1;
                RankReg = ActiveAlarms->mZT1PGAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT1_RANK_PG_1_REG_ADD,RankReg);
                break;
            }
            case 2:
            {
                WorkingReg |= ZT1_PG_FLAG_MASK_2;
                RankReg = ActiveAlarms->mZT1PGAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT1_RANK_PG_2_REG_ADD,RankReg);
                break;
            }
            case 3:
            {
                WorkingReg |= ZT1_PG_FLAG_MASK_3;
                RankReg = ActiveAlarms->mZT1PGAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT1_RANK_PG_3_REG_ADD,RankReg);
                break;
            }
            case 4:
            {
                WorkingReg |= ZT1_PG_FLAG_MASK_4;
                RankReg = ActiveAlarms->mZT1PGAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT1_RANK_PG_4_REG_ADD,RankReg);
                break;
            }
        }
    }

    for(int i = 0; i < ActiveAlarms->mZT1PPEAlarmRanks.size(); i++)
    {
        switch(i + 1)
        {
            case 1:
            {
                WorkingReg |= ZT1_PP_EXT_FLAG_MASK_1;
                RankReg = ActiveAlarms->mZT1PPEAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT1_RANK_PP_EXT_1_REG_ADD,RankReg);
                break;
            }
            case 2:
            {
                WorkingReg |= ZT1_PP_EXT_FLAG_MASK_2;
                RankReg = ActiveAlarms->mZT1PPEAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT1_RANK_PP_EXT_2_REG_ADD,RankReg);
                break;
            }
            case 3:
            {
                WorkingReg |= ZT1_PP_EXT_FLAG_MASK_3;
                RankReg = ActiveAlarms->mZT1PPEAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT1_RANK_PP_EXT_3_REG_ADD,RankReg);
                break;
            }
            case 4:
            {
                WorkingReg |= ZT1_PP_EXT_FLAG_MASK_4;
                RankReg = ActiveAlarms->mZT1PPEAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT1_RANK_PP_EXT_4_REG_ADD,RankReg);
                break;
            }
        }
    }
    for(int i = 0; i < ActiveAlarms->mZT1PPIAlarmRanks.size(); i++)
    {
        switch(i + 1)
        {
            case 1:
            {
                WorkingReg |= ZT1_PP_INT_FLAG_MASK_1;
                RankReg = ActiveAlarms->mZT1PPIAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT1_RANK_PP_INT_1_REG_ADD,RankReg);
                break;
            }
            case 2:
            {
                WorkingReg |= ZT1_PP_INT_FLAG_MASK_2;
                RankReg = ActiveAlarms->mZT1PPIAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT1_RANK_PP_INT_2_REG_ADD,RankReg);
                break;
            }
            case 3:
            {
                WorkingReg |= ZT1_PP_INT_FLAG_MASK_3;
                RankReg = ActiveAlarms->mZT1PPIAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT1_RANK_PP_INT_3_REG_ADD,RankReg);
                break;
            }
            case 4:
            {
                WorkingReg |= ZT1_PP_INT_FLAG_MASK_4;
                RankReg = ActiveAlarms->mZT1PPIAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT1_RANK_PP_INT_4_REG_ADD,RankReg);
                break;
            }
        }
    }

    mZTModbusRepo.WriteSingleReg(MODBUS_ZT1_ALARM_DATA_BASE_REG_ADD,WorkingReg);

    WorkingReg = 0;
    for(int i = 0; i < ActiveAlarms->mZT2PPEAlarmRanks.size(); i++)
    {
        switch(i + 1)
        {
            case 1:
            {
                WorkingReg |= ZT2_PP_EXT_FLAG_MASK_1;
                RankReg = ActiveAlarms->mZT2PPEAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT2_RANK_PP_EXT_1_REG_ADD,RankReg);
                break;
            }
            case 2:
            {
                WorkingReg |= ZT2_PP_EXT_FLAG_MASK_2;
                RankReg = ActiveAlarms->mZT2PPEAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT2_RANK_PP_EXT_2_REG_ADD,RankReg);
                break;
            }
            case 3:
            {
                WorkingReg |= ZT2_PP_EXT_FLAG_MASK_3;
                RankReg = ActiveAlarms->mZT2PPEAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT2_RANK_PP_EXT_3_REG_ADD,RankReg);
                break;
            }
            case 4:
            {
                WorkingReg |= ZT2_PP_EXT_FLAG_MASK_4;
                RankReg = ActiveAlarms->mZT2PPEAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT2_RANK_PP_EXT_4_REG_ADD,RankReg);
                break;
            }
        }
    }
    for(int i = 0; i < ActiveAlarms->mZT2PPIAlarmRanks.size(); i++)
    {
        switch(i + 1)
        {
            case 1:
            {
                WorkingReg |= ZT2_PP_INT_FLAG_MASK_1;
                RankReg = ActiveAlarms->mZT2PPIAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT2_RANK_PP_INT_1_REG_ADD,RankReg);
                break;
            }
            case 2:
            {
                WorkingReg |= ZT2_PP_INT_FLAG_MASK_2;
                RankReg = ActiveAlarms->mZT2PPIAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT2_RANK_PP_INT_2_REG_ADD,RankReg);
                break;
            }
            case 3:
            {
                WorkingReg |= ZT2_PP_INT_FLAG_MASK_3;
                RankReg = ActiveAlarms->mZT2PPIAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT2_RANK_PP_INT_3_REG_ADD,RankReg);
                break;
            }
            case 4:
            {
                WorkingReg |= ZT2_PP_INT_FLAG_MASK_4;
                RankReg = ActiveAlarms->mZT2PPIAlarmRanks.at(i);
                mZTModbusRepo.WriteSingleReg(MODBUS_ZT2_RANK_PP_INT_4_REG_ADD,RankReg);
                break;
            }
        }
    }

    mZTModbusRepo.WriteSingleReg(MODBUS_ZT2_ALARM_DATA_BASE_REG_ADD,WorkingReg);

    return RET_OK;
}

int CZTAlarmGenerator::ClearAllAlarms()
{
    QList<qint16> ClearData;
    ClearData.clear();
    for(int i = 0; i < MODBUS_ZT_TABLE_DATA_SIZE; i++)
        ClearData.append(0);

    mZTModbusRepo.WriteMultipleRegs(MODBUS_ZT_DATA_BASE_REG,ClearData);

    return RET_OK;
}

int CZTAlarmGenerator::ConnectToSEIRequest()
{
    QFile IPAddressFile("IP.txt");
    if(IPAddressFile.open(QIODevice::ReadOnly))
    {
        mIPAddress = QString(IPAddressFile.readAll());
    }

    mModbusZTEmulator->ConnectToSlave(mIPAddress,502);
    return RET_OK;
}

int CZTAlarmGenerator::DisconnectFromSEIRequest()
{
    mModbusZTEmulator->DisconnectFromSlave();
    return RET_OK;
}

void CZTAlarmGenerator::UpdateModbusTimerExpired()
{
    if(mReadModbus == false)
    {
        if(mWatchdogValue)
        {
            mZTModbusRepo.WriteSingleReg(SEI_MODBUS_ZT_WATCHDOG_REG,SEI_MODBUS_SEI_WATCHDOG_MASK);
        }
        else
        {
            mZTModbusRepo.WriteSingleReg(SEI_MODBUS_ZT_WATCHDOG_REG,0);
        }
        mWatchdogValue = !mWatchdogValue;
        mModbusZTEmulator->ReadModbusRegisters();
    }
    else
    {
        mModbusZTEmulator->SendModbusRegisters();
    }
    mReadModbus = !mReadModbus;


}
