#include "channelthread.h"

bool endOfMusic;

void syncFunc(HSYNC handle, DWORD channel, DWORD data, void *user)
{
    BASS_ChannelRemoveSync(channel, handle);
    BASS_ChannelStop(channel);
    qDebug() << "End of playback!";
    endOfMusic = true;
}

channelthread::channelthread(QObject *parent) :
    QThread(parent)
{
    if (!BASS_Init(-1, 44100, 0, NULL, NULL))
    {
        qDebug() << "Cannot initialize device";
    }

    t = new QTimer(this);
    t2 = new QTimer(this);
    t3 = new QTimer(this);
    connect(t, SIGNAL(timeout()), this, SLOT(signalUpdate()));
    connect(t2, SIGNAL(timeout()), this, SLOT(updateSpectrum()));
    connect(t3, SIGNAL(timeout()), this, SLOT(updateTime()));
    t3->start(500);
    endOfMusic = true;
    minValue = 0.0f;
    serOpn = false;
    playing = false;
}

bool channelthread::openPort(const char *name, BaudRateType baudrate)
{
    port = new QextSerialPort(name, QextSerialPort::EventDriven);

    port->setBaudRate(baudrate);
    port->setFlowControl(FLOW_OFF);
    port->setParity(PAR_NONE);
    port->setDataBits(DATA_8);
    port->setStopBits(STOP_1);
    port->open(QIODevice::ReadWrite);
    serOpn = true;
    return port->isOpen();
}

void channelthread::portOpen(QString name)
{
    bool openSuccesful = openPort(name.toAscii(), BAUD115200);
    if (!openSuccesful)
        qDebug() << "Error: Failed to open port.\n";
    else
        qDebug() << "Serial port at " + name + " opened with a BAUD rate of 115200 bps.\n";
    serOpn = true;
}

void channelthread::portClose()
{
    port->close();
    serOpn = false;
}

void channelthread::signalUpdate()
{
    if (endOfMusic == false)
    {
        emit curPos(BASS_ChannelBytes2Seconds(chan, BASS_ChannelGetPosition(chan, BASS_POS_BYTE)),
                    BASS_ChannelBytes2Seconds(chan, BASS_ChannelGetLength(chan, BASS_POS_BYTE)));
    }
    else
    {
        emit endOfPlayback();
        playing = false;
    }
}

void channelthread::play(QString filename)
{
    BASS_ChannelStop(chan);

    if (!(chan = BASS_StreamCreateFile(false, filename.toLatin1(), 0, 0, BASS_SAMPLE_LOOP))
        && !(chan = BASS_MusicLoad(false, filename.toLatin1(), 0, 0, BASS_MUSIC_RAMP | BASS_SAMPLE_LOOP, 1)))
            qDebug() << "Can't play file";
    else
    {
        endOfMusic = false;
        BASS_ChannelPlay(chan, true);
        emit statusString((QString("Playing: ")) + filename);
        t->start(100);
        BASS_ChannelSetSync(chan, BASS_SYNC_END, 0, &syncFunc, 0);
        t2->start(30);
        playing = true;
    }
}

void channelthread::pause()
{
    BASS_ChannelPause(chan);
    emit statusString((QString("Paused: ")));
    t->stop();
    playing = false;
}

void channelthread::resume()
{
    if (!BASS_ChannelPlay(chan, false))
        qDebug() << "Error resuming";
    else
    {
        emit statusString((QString("Playing: ")));
        t->start(98);
        playing = true;
    }
}

void channelthread::stop()
{
    BASS_ChannelStop(chan);
    emit statusString((QString("Stopped: ")));
    t->stop();
    playing = false;
}

void channelthread::changePosition(int position)
{
    BASS_ChannelSetPosition(chan, BASS_ChannelSeconds2Bytes(chan, position), BASS_POS_BYTE);
}

void channelthread::updateSpectrum()
{
    if (checked == false) {
    if ((serOpn == true))
    {
        BASS_ChannelGetData(chan, fft, BASS_DATA_FFT256); // get the FFT data
        char ydisp = 's';
        port->write(&ydisp, 1);
        int b0 = 0, y = 0;
        for (int x = 0; x < BANDS; x++)
        {
            float peak = 0;
            float lowest = 100;
            int b1 = qPow(2, x * 10.0 / (BANDS - 1));
            if (b1 > 127)
                b1 = 127;
            if (b1 <= b0)
                b1 = b0+ 1;
            for (; b0 < b1; b0++)
            {
                if (peak < fft[1 + b0])
                    peak = fft[1 + b0];
                if (lowest > fft[1 + b0])
                    lowest = fft[1 + b0];
            }
            y = qSqrt(peak) * 2 * SPEC_HEIGHT - 4;
            if (y > SPEC_HEIGHT)
                y = SPEC_HEIGHT;
            ydisp = 0xFF;
            for (int z = 0; z < 8 - (y / 50); z++)
                ydisp &= ~(1<<z);
            port->write(&ydisp, 1);
        }
        ydisp = 'x';
        port->write(&ydisp, 1);
        //port->waitForReadyRead(3000);
        //qDebug() << "Here! 2\n";
        //char data;
        //port->read(&data, 1);
    }}
}

void channelthread::updateTime()
{
    static bool colon = false;
    if (checked == true)
    {
        if ((serOpn == true))
        {
            char a = 't';
            port->write(&a, 1);
            curTime = QTime::currentTime();
            int hr, min;
            hr = curTime.hour();
            min = curTime.minute();
            if (hr > 12)
                hr = hr - 12;
            else if (hr == 0)
                hr = 12;
            if (hr < 10)
                port->write((QString("0") + QString::number(hr)).toLocal8Bit());
            else
                port->write(QString::number(hr).toLocal8Bit());
            qDebug() << QString::number(hr).toLocal8Bit();
            port->flush();
            if (min < 10)
                port->write((QString("0") + QString::number(min)).toLocal8Bit());
            else
                port->write(QString::number(min).toLocal8Bit());
            qDebug() << QString::number(min).toLocal8Bit();
            port->flush();
            if (colon == false)
            {
                colon = true;
                a = ':';
                port->write(&a, 1);
            }
            else
            {
                colon = false;
                a = '0';
                port->write(&a, 1);
            }
            a = 'x';
            port->write(&a, 1);
        }
    }
}

void channelthread::checkBoxChange(bool checked1)
{
    if (checked1 == true)
    {
        checked = true;
        if (serOpn == true) {
        char a = 's';
        port->write(&a, 1);
        port->flush();
        for (int i = 0; i < 16; i++)
        {
            a = 0x00;
            port->write(&a, 1);
            port->flush();
        }
        a = 'x';
        port->write(&a, 1);
        port->flush();
    }
    }
    else
    {
        checked = false;
    }
}

void channelthread::run()
{
    while(1)
    {

    }
}
