// PRIVATE: Socket connection methods
void MainWindow::connectSocket()
{
    Q_ASSERT(nullptr == _socket);

    _socket = new QTcpSocket();

    _socket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);

    // TcpSocket: Connect signals and slots
    bool isOk;

    isOk = connect(_socket, SIGNAL(readyRead()), this, SLOT(onDataRecieved()));
    Q_ASSERT(isOk);
    Q_UNUSED(isOk);

    isOk = connect(_socket, SIGNAL(connected()), this, SLOT(onConnected()));
    Q_ASSERT(isOk);
    Q_UNUSED(isOk);

    isOk = connect(_socket, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
    Q_ASSERT(isOk);
    Q_UNUSED(isOk);

    isOk = connect(_socket, SIGNAL(error(QAbstractSocket::SocketError)),
                   this, SLOT(onErrorSocket(QAbstractSocket::SocketError)));
    Q_ASSERT(isOk);
    Q_UNUSED(isOk);

    _socket->connectToHost(_programSettings.server.ipV4Address,
                           _programSettings.server.port);
    setWindowTitle(QString("%1 " + tr("Connecting...") + " %2:%3")
                   .arg(_programSettings.application.name)
                   .arg(_programSettings.server.ipV4Address)
                   .arg(_programSettings.server.port));
}
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{  
    // Load program settings from "assets/config.xml"
    ConfigLoader configLoader(CONFIG_FILE, this);
    _programSettings = configLoader.getProgramSettings();

    // Load program setting from persistant storage
    QCoreApplication::setOrganizationName(ORGANIZATION_NAME);
    QCoreApplication::setOrganizationDomain(ORGANIZATION_DOMAIN);
    QCoreApplication::setApplicationName(APPLICATION_NAME);

    _programSettingsPersistant = new QSettings(this);

    // Setup the GUI
    ui->setupUi(this);  
    connect(ui->action_About, SIGNAL(triggered()), this, SLOT(onActionAboutTriggered()));

    // Setup the indicators display area
    _scene = new CGraphicsScene(this);
    ui->graphicsView->setScene(_scene);

    QString imageFilePath = ASSETS_PATH + _programSettings.backgroundImageFileName;
    QImage imageBackgroundImage(ASSETS_PATH + _programSettings.backgroundImageFileName);
    if (imageBackgroundImage.isNull()) {
        qDebug() << "Background image failed to load: " + imageFilePath;
    }

    ui->graphicsView->setBackgroundBrush(QBrush(QColor(50, 50, 50)));

    QRect sceneRect(0, 0, imageBackgroundImage.width(), imageBackgroundImage.height());
    QGraphicsRectItem* sceneRectItemBackground = _scene->addRect(sceneRect);
    sceneRectItemBackground->setBrush(QBrush(imageBackgroundImage));

    // Load the indicators
    _listIndicatorProperties = configLoader.getIndicatorProperties();

    for (IndicatorProperties currentIndicatorProperties: _listIndicatorProperties) {
        TemperatureIndicator* temperatureIndicator =
                new TemperatureIndicator(currentIndicatorProperties,
                                         _programSettings,
                                         ui->listWidget,
                                         _scene);
        temperatureIndicator->setPosition(currentIndicatorProperties.position);
        temperatureIndicator->setSensorState(SensorState::Disconnected);
        temperatureIndicator->update();

        QString key = QString::number(temperatureIndicator->getSensorId());
        if (_programSettingsPersistant->contains(key))  {
            qreal temperature = _programSettingsPersistant->value(key).toDouble();
            temperatureIndicator->setTemperatureTarget(temperature);
        }
        else {
            temperatureIndicator->setTemperatureTarget(currentIndicatorProperties.temperatureTarget);
            _programSettingsPersistant->setValue(key, temperatureIndicator->getTemperatureTarget());
        }

        _temperatureIndicators.push_back(temperatureIndicator);
    }

    bool isOk;
    for(auto indicator: _temperatureIndicators) {
        isOk = connect(indicator,
                       SIGNAL(doubleClicked(QGraphicsSceneMouseEvent*)),
                       this,
                       SLOT(onTemperatureIndicatorDoubleClicked(QGraphicsSceneMouseEvent*)));
        Q_ASSERT(isOk);
        Q_UNUSED(isOk);
    }

    _currentTemperatureIndicator = _temperatureIndicators[0];
    _currentTemperatureIndicator->setIndicatorSelected(true);

    // Connect QListWidget signal to TemperatureIndicators
    isOk = connect(ui->listWidget,
                   SIGNAL(itemClicked(QListWidgetItem*)),
                   this,
                   SLOT(onListWidgetItemClicked(QListWidgetItem*)));
    Q_ASSERT(isOk);
    Q_UNUSED(isOk);

    isOk = connect(ui->listWidget,
                   SIGNAL(itemDoubleClicked(QListWidgetItem*)),
                   this,
                   SLOT(onListWidgetItemDoubleClicked(QListWidgetItem*)));
    Q_ASSERT(isOk);
    Q_UNUSED(isOk);

    // Setup socket
    connectSocket();

    connect(_socket, SIGNAL(readyRead()), this, SLOT(onDataRecieved()) );
    connect(_socket, SIGNAL(connected()), this, SLOT(onConnected()) );
    connect(_socket, SIGNAL(disconnected()), this, SLOT(onDisconnected()) );
    connect(_socket, SIGNAL(error(QAbstractSocket::SocketError)),
            this, SLOT(onErrorSocket(QAbstractSocket::SocketError)));
}