/*
 * OutputTask.c
 *
 *  Created on: 2020年2月25日
 *      Author: 7564
 */

#include    "OutputTask.h"

bool isOpen;

int InitComPort()
{
    int fd;
    struct termios tios;

    fd = open(priPortName, O_RDWR);
    if(fd<=0)
    {
        #ifdef SystemLogMessage
        DEBUG_ERROR("open 407 Communication port NG \n");
        #endif
        return -1;
    }
    ioctl (fd, TCGETS, &tios);
    tios.c_cflag = B115200| CS8 | CLOCAL | CREAD;
    tios.c_lflag = 0;
    tios.c_iflag = 0;
    tios.c_oflag = 0;
    tios.c_cc[VMIN]=0;
    tios.c_cc[VTIME]=(unsigned char)1;
    tios.c_lflag=0;
    tcflush(fd, TCIFLUSH);
    ioctl (fd, TCSETS, &tios);

    return fd;
}

unsigned long GetTimeoutValue(struct timeval _sour_time)
{
    struct timeval _end_time;
    gettimeofday(&_end_time, NULL);

    return 1000000 * (_end_time.tv_sec - _sour_time.tv_sec) + _end_time.tv_usec - _sour_time.tv_usec;
}

void ShowMainMsg()
{
    printf("Max Vol : %f, Max Cur : %d, POW : %d \n", UnSafeDataInfo->PSU_VOLTAGE,
            UnSafeDataInfo->PSU_CURRENT, UnSafeDataInfo->PSU_POWER);
    printf("=> ");
}

void ChkButtonStatus()
{
    if (Button1 == PRESS && !leftBtnPush)
    {
        if(!leftBtnPush)
        {
            leftBtnPush = true;
            if (_charging_mode == CHARGING_MODE_STOP)
            {
                _charging_mode = CHARGING_MODE_START;
                printf("****************** Switch to Charging Mode ******************\n");
            }
        }
        else if (Button1 == RELEASE)
        {
            if(leftBtnPush)
            {
                leftBtnPush = false;
            }
        }
    }

    if (Button2 == PRESS && !rightBtnPush)
    {
        if(!rightBtnPush)
        {
            rightBtnPush = true;
            if (_charging_mode == CHARGING_MODE_START)
            {
                _charging_mode = CHARGING_MODE_TERMINATING;
                printf("****************** Switch to Stop Mode ******************\n");
            }
        }
        else if (Button2 == RELEASE)
        {
            if(rightBtnPush)
            {
                rightBtnPush = false;
            }
        }
    }
}

void GetModuleCountCallback(byte group, byte count)
{
    printf("group = %d, count = %d \n", group, count);
    if (group == SYSTEM_CMD)
        UnSafeDataInfo->PSU_COUNT = count;
}

void GetAvailableCapCallback(byte address, short maxVol, short minVol, short maxCur, short totalPow)
{
    int _groupPower = 0, _groupCurrent = 0;

    UnSafeDataInfo->PsuModule[address].PSU_VOLTAGE_INFO = maxVol;
    UnSafeDataInfo->PsuModule[address].PSU_CURRENT_INFO = maxCur;
    UnSafeDataInfo->PsuModule[address].PSU_POWER_INFO = totalPow;

    for (byte index = 0; index < UnSafeDataInfo->PSU_COUNT; index++)
    {
        _groupCurrent += UnSafeDataInfo->PsuModule[address].PSU_CURRENT_INFO;
        _groupPower += UnSafeDataInfo->PsuModule[address].PSU_POWER_INFO;
    }

    UnSafeDataInfo->PSU_VOLTAGE = maxVol;
    UnSafeDataInfo->PSU_CURRENT = _groupCurrent;
    UnSafeDataInfo->PSU_POWER = _groupPower;
}

void GetStatusCallback(byte group, byte address, byte temp, int alarm)
{
    printf("alarm = %d \n", alarm);
}

void GetInputVoltageCallback(byte address, unsigned short vol1, unsigned short vol2, unsigned short vol3)
{
    printf("vol1 = %d, vol2 = %d, vol3 = %d \n", vol1, vol2, vol3);
}

int CreateShareMemory()
{
    int MeterSMId;

    if ((MeterSMId = shmget(ShmTestKey, sizeof(struct UnSafeData), IPC_CREAT | 0777)) < 0)
    {
        return 0;
    }
    else if ((UnSafeDataInfo = shmat(MeterSMId, NULL, 0))   == (void *) -1)
    {
        return 0;
    }
    memset(UnSafeDataInfo, 0, sizeof(struct UnSafeData));

    return 1;
}

static void get_char(char *word)
{
    fd_set rfds;
    struct timeval tv;

    FD_ZERO(&rfds);
    FD_SET(0, &rfds);
    tv.tv_sec = 0;
    tv.tv_usec = 10; //wait input timout time

    //if input
    if (select(1, &rfds, NULL, NULL, &tv) > 0)
    {
        fgets(word, 128, stdin);
    }
}

void GetInputString()
{
    char word[128];
    char newString[7][10];
    int i, j, ctr;

    get_char(word);

    if (strlen(word) == 0)
        return;
    //fgets(word, sizeof(word), stdin);

    j = 0;
    ctr = 0;
    for (i = 0; i <= (strlen(word)); i++) {
        if (word[i] == ' ' || word[i] == '\0' || word[i] == 10) {
            newString[ctr][j] = '\0';
            ctr++;
            j = 0;
        } else {
            newString[ctr][j] = word[i];
            j++;
        }
    }

    VOLTAGE = atof(newString[0]);
    CURRENT = atof(newString[1]);
    if (VOLTAGE <= UnSafeDataInfo->PSU_VOLTAGE && CURRENT <= UnSafeDataInfo->PSU_CURRENT)
    {
        //printf("OutputVol = %f, OutputCur = %f \n", VOLTAGE, CURRENT);
    }
    else
    {
        ShowMainMsg();
    }
}

void GetIavailableCallback(byte address, unsigned short Iavail, unsigned short Vext)
{
    //printf("address = %d, Iavail = %d, Vext = %d \n", address, Iavail, Vext);
}

void GetOutputAndTempCallback(byte address, unsigned short outputVol,
        unsigned short outputCur, unsigned short outputPower, unsigned char Temperature)
{
    //printf("***Output Value and Temp*** address = %d, Vol = %d, Cur = %d, Pow = %d, Temp = %d \n",
    //      address, outputVol, outputCur, outputPower, Temperature);
}

void GetModuleStatusCallback(byte address, unsigned char isErr, unsigned char status,
        unsigned char err1, unsigned char err2, unsigned char err3, unsigned char err4)
{
    //int alarm = (err2 << 24) | (err3 << 16) | (err4 << 8);

    // err2 == state 2
    // err3 == state 1
    // err4 == state 0
    //printf("***Status*** address = %d, alarm = %d \n", address, alarm);
//  printf("***Status*** address = %d, err1 = %d, err2 = %d, err3 = %d, err4 = %d \n",
//          address, err1,err2,err3,err4);
}

void GetModuleInputCallback(byte address, unsigned short inputR,
        unsigned short inputS, unsigned short inputT)
{

}

int main(void)
{
    isOpen =false;

    if(CreateShareMemory() == 0)
    {
        printf("CreateShareMemory fail. \n");
        return 0;
    }
    RefreshModuleCount(&GetModuleCountCallback);
    RefreshAvailableCap(&GetAvailableCapCallback);

    RefreshStatus(&GetStatusCallback);
    RefreshInputVol(&GetInputVoltageCallback);

    RefreshIavailable(&GetIavailableCallback);

    AutoMode_RefreshOutputAndTemp(&GetOutputAndTempCallback);
    AutoMode_RefreshModuleStatus(&GetModuleStatusCallback);
    AutoMode_RefreshModuleInput(&GetModuleInputCallback);

    Uart1Fd = InitComPort();
    libInitialize = InitialCommunication();

    if (Uart1Fd < 0 || !libInitialize)
    {
        printf("Initial port fail. \n");
        return 0;
    }

    sleep(5);
    gettimeofday(&_cmdSubPriority_time, NULL);
    VOLTAGE = 0.0;
    CURRENT = 0.0;

    SwitchPower(SYSTEM_CMD, PSU_POWER_OFF);
//  while (1)
//  {
//      printf("++++++++++++++2++++++++++++++++++++++++++++++++++++++\n");
//      SetWalkInConfig(0, YES, 0);
//      SetWalkInConfig(1, NO, 0);
//      printf("++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
//      sleep(1);
//  }
//
//  sleep(1);
//      printf("++++++++++++++2++++++++++++++++++++++++++++++++++++++\n");
//      SetWalkInConfig(SYSTEM_CMD, NO, 0);
//      printf("++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
//  return 0;
    while (1)
    {
        GetInputGpioStatus();
        //ChkButtonStatus();
        // 切換 Walk-in mode (default 5s -> 2s)
        SetWalkInConfig(SYSTEM_CMD, NO, 0);

        int time = GetTimeoutValue(_cmdSubPriority_time) / 1000;
        while(isGetCount == YES)
        {
            if (_charging_mode == CHARGING_MODE_START)
            {
                // 取得模塊輸出額定電流能力
                GetModuleIavailable(0);
            }

            GetInputString();
            if (VOLTAGE > 150 && CURRENT >= 0)
                _charging_mode = CHARGING_MODE_START;
            else
                _charging_mode = CHARGING_MODE_TERMINATING;
            //printf("_charging_mode = %d \n", _charging_mode);
            switch(_charging_mode)
            {
                case CHARGING_MODE_START:
                {
                    //if (!isOpen)
                    {
                        //SwitchPower(SYSTEM_CMD, PSU_POWER_ON);
                        //FlashLed(SYSTEM_CMD, PSU_FLASH_ON);
                        SetDirModulePresentOutput(0,
                                                VOLTAGE * 10,
                                                CURRENT * 10,
                                                0x01,
                                                0x01);
                    }
                    //PresentOutputVol(SYSTEM_CMD, VOLTAGE * 10, CURRENT * 10);
                }
                    break;
                case CHARGING_MODE_TERMINATING:
                {
                    //if (isOpen)
                    {
                        SetDirModulePresentOutput(0,
                            VOLTAGE * 10,
                            CURRENT * 10,
                            0x00,
                            0x01);
                        //SwitchPower(SYSTEM_CMD, PSU_POWER_OFF);
                        //FlashLed(SYSTEM_CMD, PSU_FLASH_NORMAL);
                    }
                }
                    break;
            }
            //GetStatus(0);
            //GetModuleInput(0);
            sleep(1);
        }

        if (UnSafeDataInfo->PSU_COUNT <= 0)
        {
            if (time > 1000)
            {
                printf("Step 1 : GetModuleCount...... \n");
                GetModuleCount(SYSTEM_CMD);
                gettimeofday(&_cmdSubPriority_time, NULL);
            }
        }
        else if (time < 5000)
        {
            printf("Step 2 : GetModuleCap...... \n");
            GetModuleCap(0);

            SwitchPower(SYSTEM_CMD, PSU_POWER_OFF);
            FlashLed(SYSTEM_CMD, PSU_FLASH_NORMAL);
        }
        else
        {
            ShowMainMsg();
            isGetCount = YES;
        }

        sleep(1);
    }

    return 0;
}