/***************************************************************************
 *   Copyright (C) 2009 by Manuel Schrape                                  *
 *   manuel.schrape@gmx.de                                                 *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License.        *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "cConnection.h"

cConnection::cConnection()
{
    i_Type = 0;

    TTY = new ManageSerialPort();
    o_Timer = new QTimer(this);

    connect(o_Timer,   SIGNAL(timeout()),       SLOT(slot_Timer()));

    TTY->setBaudRate(BAUD57600);   //BaudRate
    TTY->setDataBits(DATA_8);      //DataBits
    TTY->setParity(PAR_NONE);      //Parity
    TTY->setStopBits(STOP_1);      //StopBits
    TTY->setFlowControl(FLOW_OFF); //FlowControl

    TTY->setTimeout(0, 10);
    TTY->enableSending();
    TTY->enableReceiving();

    b_isOpen = false;
}

void cConnection::new_Data(QString Data)
{
    Data = Data;

    while ((RxData.String.length() > 1) && (RxData.String.at(1) == '#'))
    {
        RxData.String.remove(0,1);
    }

    if (ToolBox::check_CRC(RxData.String))
    {
        RxData.Input = RxData.String.toLatin1().data();
        emit(newData(RxData));
    }
    else
    {
        emit(showTerminal(2, RxData.String));
    }

}

void cConnection::slot_newDataReceived(const QByteArray &dataReceived)
{
    const char *RXt;
    RXt = dataReceived.data();
    int a = 0;

    while (RXt[a] != '\0')
    {
        if (RXt[a] == '\r')
        {
            new_Data(QString(""));
            RxData.String = QString("");
        }
        else
        {
            RxData.String = RxData.String + QString(RXt[a]);
        }
        a++;
    }
}

bool cConnection::isOpen()
{
    return b_isOpen;
}

bool cConnection::Close()
{
    switch(i_Type)
    {
        case C_TTY :
        {
            TTY->close();

            disconnect(TTY, SIGNAL(newDataReceived(const QByteArray &)), this, 0);

            b_isOpen = false;
        }
        break;
        case C_IP :
        {
            TcpSocket->disconnectFromHost();
            disconnect(TcpSocket, SIGNAL(connected()), 0, 0);
            disconnect(TcpSocket, SIGNAL(readyRead()), 0, 0);
            disconnect(TcpSocket, SIGNAL(disconnected()), 0, 0);

            b_isOpen = false;
        }
        break;
    }

    return b_isOpen;
}

bool cConnection::Open(int Typ, QString Address)
{
    switch(Typ)
    {
        case C_TTY :
        {
            TTY->setPort(Address); //Port
            TTY->open();

            ToolBox::Wait(1000);

            if (TTY->isOpen())
            {
                connect(TTY, SIGNAL(newDataReceived(const QByteArray &)), this, SLOT(slot_newDataReceived(const QByteArray &)));

                TTY->receiveData();
                b_isOpen = true;
                i_Type = C_TTY;
            }
        }
        break;
        case C_IP :
        {
            QStringList Host = Address.split(":");

            TcpSocket = new(QTcpSocket);
            TcpSocket->connectToHost (Host[1], Host[2].toInt());

            connect(TcpSocket, SIGNAL(connected()), this, SLOT(slot_IP_Connected()) );
//            connect(TcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(slot_Error(QAbstractSocket::SocketError)));
            b_isOpen = true;
            i_Type = C_IP;
        }
        break;
    }

    return b_isOpen;
}

void cConnection::slot_IP_Connected()
{
    connect(TcpSocket, SIGNAL(readyRead()), SLOT(slot_IP_ReadLine()));
    connect(TcpSocket, SIGNAL(disconnected()),TcpSocket, SLOT(deleteLater()));
    connect(TcpSocket, SIGNAL(disconnected()),this, SLOT(slot_IP_Disconnect()));

//    emit sig_Connected();
}

void cConnection::slot_IP_Disconnect()
{
    disconnect(TcpSocket, SIGNAL(disconnected()), 0, 0);
    disconnect(TcpSocket, SIGNAL(readyRead()), 0, 0);
//    emit sig_Disconnected(1);
}

void cConnection::slot_IP_ReadLine()
{
    QString Input = QString(TcpSocket->readLine(TcpSocket->bytesAvailable())).remove(QChar(' '));

    int Len = Input.length();

    for (int z = 0; z < Len; z++)
    {
        if (Input[z] == '\r')
        {
            new_Data(QString(""));
            RxData.String = QString("");
        }
        else
        {
            RxData.String = RxData.String + Input[z];
        }
    }
}

bool cConnection::send_Cmd(char CMD, int Address, char Data[150],unsigned int Length, bool Resend)
{
    if (b_isOpen)
    {
        QByteArray Temp;
        QString TX_Data;

        if (CMD != '#')
        {
            TX_Data = ToolBox::Encode64(Data, Length);

            TX_Data = QString("#") + (QString('a' + Address)) + QString(CMD) + TX_Data;
            TX_Data = ToolBox::add_CRC(TX_Data) + '\r';

            Temp = QByteArray(TX_Data.toUtf8());

            if (Resend)
            {
                o_Timer->start(TICKER);
                s_ReSend = Temp;
            }
        }
        else
        {
            for (unsigned int a = 0; a < Length; a++)
            {
                Temp[a] = Data[a];
            }
        }

        switch(i_Type)
        {
            case C_TTY :
            {
                TTY->sendData(Temp);
            }
            break;
            case C_IP :
            {
                TcpSocket->write(Temp);
            }
            break;
        }

        emit(showTerminal(3, TX_Data));
    }
    return true;
}

void cConnection::stop_ReSend()
{
    o_Timer->stop();
}

void cConnection::slot_Timer()
{
        switch(i_Type)
        {
            case C_TTY :
            {
                TTY->sendData(s_ReSend);
            }
            break;
            case C_IP :
            {
                TcpSocket->write(s_ReSend);
            }
            break;
        }

        emit(showTerminal(3, QString(s_ReSend)));
}
