#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "clientsocket.h"
#include "clientglobals.h"

#include <QHostAddress>
#include <QHostInfo>
#include <QTimer>
#include <QStringList>
#include <QApplication>
#include <QSettings>
#include <QNetworkProxy>
#include <QMessageBox>
#include <QAudioOutput>
#include <QAudioFormat>
#include <QAudioOutput>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QWidget(parent), ui(new Ui::MainWindow), m_audioDevice(0)
{
    m_connection = new ClientSocket(this);
    ui->setupUi(this);
    ui->mainView->setCurrentConnection(m_connection);
    QTimer::singleShot(0,this, SLOT(initConnection()));
}

void MainWindow::initAudio()
{
/*
    connect( m_connection, SIGNAL(startAudioChannel()),
             m_player->alsa(), SLOT(startPlaying()));
    connect( m_connection, SIGNAL(stopAudioChannel()),
             m_player->alsa(), SLOT(stopPlaying()));
    connect( m_connection, SIGNAL(audioData(QByteArray)),
             m_player->alsa(), SLOT(bufferData(QByteArray)));
*/

}

/*
  [Connection]
  Host=10.0.15.28
  Display=3
  SharedSession=false
  EncodingPriorites=ZLIB,HEXTILE,RAW
  [Audio]
  Enabled=true
  Format=1
  Frequency=44100
  Channels=2
  [Auth]
  Password=mypass
  Type=None

  */

void MainWindow::initConnection()
{
    QString file = QCoreApplication::arguments().value(1);
    if( !file.isEmpty() )
    {
        QSettings settings(file, QSettings::IniFormat, this);
        m_connection->setAuthenticationType(
                ClientGlobals::mapAuthType( settings.value("Auth/Type", "None").toString()));
        m_connection->setAuthSubtype(
                ClientGlobals::mapAuthSubType( settings.value("Auth/SubType", "TLSNone").toString()));
        m_connection->setPassword(
                settings.value("Auth/Password").toByteArray());
        m_connection->setCaCertPath(
                settings.value("Auth/CaCertPath").toString());
        m_connection->setSharedSession(
                settings.value("Connection/SharedSession", false).toBool());
        m_connection->setEncodingPriorites(
                settings.value("Connection/EncodingPriorites", "RAW").toStringList());
        m_connection->setAudioEnabled(
                settings.value("Audio/Enabled", false).toBool());
        m_connection->setUseNativeKeys(true);
        if ( settings.value("Proxy/Enabled",false).toBool() )
        {
            QNetworkProxy proxy;
            proxy.setType((QNetworkProxy::ProxyType) settings.value("Proxy/Type", QNetworkProxy::Socks5Proxy).toInt());
            proxy.setHostName(settings.value("Proxy/Server").toString());
            if ( settings.contains("Proxy/Port"))
                proxy.setPort(settings.value("Proxy/Port").toInt() );
            if ( settings.contains("Proxy/Username"))
                proxy.setUser(settings.value("Proxy/Username").toString());
            if ( settings.contains("Proxy/Password"))
                proxy.setPassword(settings.value("Proxy/Password").toString());
            QNetworkProxy::setApplicationProxy(proxy);
        }
    }
    else
    {
        QMessageBox::critical ( this, tr("Connection error"), tr("Please provide a connection file."));
        QCoreApplication::quit();
    }

    connect( this, SIGNAL(disconnectFromHost()),
             m_connection, SLOT(disconnectFromHost()));
    connect( m_connection, SIGNAL(framebufferResize(QSize)),
             ui->mainView, SLOT(handleFramebufferResize(QSize)));
    connect( m_connection, SIGNAL(framebufferResize(QSize)),
             this, SLOT(handleResize()));
    connect( m_connection, SIGNAL(sendFramebufferChange(QRect,QImage)),
             ui->mainView, SIGNAL(mergeFramebufferChange(QRect,QImage)));
    connect( m_connection, SIGNAL(framebufferUpdate()),
             ui->mainView, SLOT(updateImage()));
    connect( m_connection, SIGNAL(connected()),
             this, SLOT(handleConnected()));
    connect( m_connection, SIGNAL(disconnected()),
             this, SLOT(handleDisconnected()));
    connect( m_connection, SIGNAL(enableNativeKeys()),
             ui->mainView, SLOT(enableNativeKeySyms()));
    connect( m_connection, SIGNAL(enableRelativePointer()),
             ui->mainView, SLOT(enableRelativePointer()));
    connect( m_connection, SIGNAL(enableAudio()),
             this, SLOT(handleSetupAudio()));
    connect( m_connection, SIGNAL(desktopNameChanged(QString)),
             this, SLOT(handleDesktopNameChanged(QString)));

    ui->mainView->setCurrentConnection( m_connection );
    connectToHost();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::connectToHost()
{

    QString file = QCoreApplication::arguments().value(1);
    if( !file.isEmpty() )
    {
        QSettings settings(file, QSettings::IniFormat, this);
        QString host = settings.value("Connection/Host").toString();
        quint16 port = settings.value("Connection/Display", 0).toInt() + 5900;
        QList<QHostAddress> addresses = QHostInfo::fromName(host).addresses();
        if ( addresses.size() > 0 )
        {
            m_connection->connectToHost( addresses.at(0), port);
        }
        else
        {
            QMessageBox::critical ( this, tr("Connection error"), tr("Could not connect to host '%1'").arg(host));
            QCoreApplication::quit();
        }
    }
    else
    {
        QMessageBox::critical ( this, tr("Connection error"), tr("Please provide a connection file."));
        QCoreApplication::quit();
    }
}

void MainWindow::handleResize()
{
    adjustSize();
}

void MainWindow::handleConnected()
{
    ui->mainView->listenForEvents(true);
}

void MainWindow::handleDisconnected()
{
    ui->mainView->listenForEvents(false);
    QMessageBox::information( this, tr("Connection status"), tr("Host disconnected."));
    QCoreApplication::quit();
}

void MainWindow::handleSetupAudio()
{
    QAudioFormat format;
    QString file = QCoreApplication::arguments().value(1);
    if( !file.isEmpty() )
    {
        QSettings settings(file, QSettings::IniFormat, this);
        if ( settings.value("Audio/Enabled", false ).toBool() )
        {
            format.setSampleSize( settings.value("Audio/SampleSize", 8 ).toInt());
            format.setSampleType( (QAudioFormat::SampleType)settings.value("Audio/SampleType", 1 ).toInt());
            format.setFrequency( settings.value("Audio/Frequency", 48000).toInt() );
            format.setChannels( settings.value("Audio/Channels", 1).toInt());
            m_audioDevice = new QAudioOutput(format,this);
        }
    }
    else
    {
        QMessageBox::critical ( this, tr("Connection error"), tr("Please provide a connection file."));
        QCoreApplication::quit();
    }

    if ( m_audioDevice )
    {
        m_connection->setAudioDevice( m_audioDevice );
        m_connection->sendEnableAudio();
    }
}

void MainWindow::handleDesktopNameChanged( const QString &name )
{
    setWindowTitle( name );
}

