/****************************************************************************
**
** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com>
** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtSerialPort module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "consolesettings.h"
#include "ui_consolesettings.h"

#include <QtSerialPort/QSerialPortInfo>
#include <QIntValidator>
#include <QLineEdit>

QT_USE_NAMESPACE

ConsoleSettings::ConsoleSettings(QWidget *parent) :
	QDialog(parent),
	ui(new Ui::ConsoleSettings)
{
	ui->setupUi(this);

	intValidator = new QIntValidator(0, 4000000, this);

	ui->baudRateBox->setInsertPolicy(QComboBox::NoInsert);

	connect(ui->applyButton, SIGNAL(clicked()),
	        this, SLOT(apply()));
	connect(ui->serialPortInfoListBox, SIGNAL(currentIndexChanged(int)),
	        this, SLOT(showPortInfo(int)));
	connect(ui->baudRateBox, SIGNAL(currentIndexChanged(int)),
	        this, SLOT(checkCustomBaudRatePolicy(int)));

	fillPortsParameters();
	fillPortsInfo();

	updateSettings();
}

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

ConsoleSettings::Settings ConsoleSettings::settings() const
{
	return currentSettings;
}

void ConsoleSettings::showPortInfo(int idx)
{
	if (idx != -1) {
		QStringList list = ui->serialPortInfoListBox->itemData(idx).toStringList();
		ui->descriptionLabel->setText(tr("Description: %1").arg(list.at(1)));
		ui->manufacturerLabel->setText(tr("Manufacturer: %1").arg(list.at(2)));
		ui->serialNumberLabel->setText(tr("Serial number: %1").arg(list.at(3)));
		ui->locationLabel->setText(tr("Location: %1").arg(list.at(4)));
		ui->vidLabel->setText(tr("Vendor Identifier: %1").arg(list.at(5)));
		ui->pidLabel->setText(tr("Product Identifier: %1").arg(list.at(6)));
	}
}

void ConsoleSettings::apply()
{
	updateSettings();
	hide();
}

void ConsoleSettings::checkCustomBaudRatePolicy(int idx)
{
	bool isCustomBaudRate = !ui->baudRateBox->itemData(idx).isValid();
	ui->baudRateBox->setEditable(isCustomBaudRate);
	if (isCustomBaudRate) {
		ui->baudRateBox->clearEditText();
		QLineEdit *edit = ui->baudRateBox->lineEdit();
		edit->setValidator(intValidator);
	}
}

void ConsoleSettings::fillPortsParameters()
{
	ui->baudRateBox->addItem(QStringLiteral("9600"), QSerialPort::Baud9600);
	ui->baudRateBox->addItem(QStringLiteral("19200"), QSerialPort::Baud19200);
	ui->baudRateBox->addItem(QStringLiteral("38400"), QSerialPort::Baud38400);
	ui->baudRateBox->addItem(QStringLiteral("115200"), QSerialPort::Baud115200);
	ui->baudRateBox->addItem(QStringLiteral("Custom"));

	ui->dataBitsBox->addItem(QStringLiteral("5"), QSerialPort::Data5);
	ui->dataBitsBox->addItem(QStringLiteral("6"), QSerialPort::Data6);
	ui->dataBitsBox->addItem(QStringLiteral("7"), QSerialPort::Data7);
	ui->dataBitsBox->addItem(QStringLiteral("8"), QSerialPort::Data8);
	ui->dataBitsBox->setCurrentIndex(3);

	ui->parityBox->addItem(QStringLiteral("None"), QSerialPort::NoParity);
	ui->parityBox->addItem(QStringLiteral("Even"), QSerialPort::EvenParity);
	ui->parityBox->addItem(QStringLiteral("Odd"), QSerialPort::OddParity);
	ui->parityBox->addItem(QStringLiteral("Mark"), QSerialPort::MarkParity);
	ui->parityBox->addItem(QStringLiteral("Space"), QSerialPort::SpaceParity);

	ui->stopBitsBox->addItem(QStringLiteral("1"), QSerialPort::OneStop);
#ifdef Q_OS_WIN
	ui->stopBitsBox->addItem(QStringLiteral("1.5"), QSerialPort::OneAndHalfStop);
#endif
	ui->stopBitsBox->addItem(QStringLiteral("2"), QSerialPort::TwoStop);

	ui->flowControlBox->addItem(QStringLiteral("None"), QSerialPort::NoFlowControl);
	ui->flowControlBox->addItem(QStringLiteral("RTS/CTS"), QSerialPort::HardwareControl);
	ui->flowControlBox->addItem(QStringLiteral("XON/XOFF"), QSerialPort::SoftwareControl);
}

void ConsoleSettings::fillPortsInfo()
{
	ui->serialPortInfoListBox->clear();
	static const QString blankString = QObject::tr("N/A");
	QString description;
	QString manufacturer;
	QString serialNumber;
	Q_FOREACH (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
		QStringList list;
		description = info.description();
		manufacturer = info.manufacturer();
		//serialNumber = info.serialNumber();
		list << info.portName()
		     << (!description.isEmpty() ? description : blankString)
		     << (!manufacturer.isEmpty() ? manufacturer : blankString)
		     << (!serialNumber.isEmpty() ? serialNumber : blankString)
		     << info.systemLocation()
		     << (info.vendorIdentifier() != 0u ? QString::number(info.vendorIdentifier(), 16) : blankString)
		     << (info.productIdentifier() != 0u ? QString::number(info.productIdentifier(), 16) : blankString);

		ui->serialPortInfoListBox->addItem(list.first(), list);
	}
}

void ConsoleSettings::selectPortName(const QString portName) {
	if (portName.isEmpty()) return;
	int ix = ui->serialPortInfoListBox->findText(portName);
	if (ix >= 0) {
		currentSettings.name = portName;
		ui->serialPortInfoListBox->setCurrentIndex(ix);
	}
}

void ConsoleSettings::updateSettings()
{
	currentSettings.name = ui->serialPortInfoListBox->currentText();

	if (ui->baudRateBox->currentIndex() == 4) {
		currentSettings.baudRate = ui->baudRateBox->currentText().toInt();
	} else {
		currentSettings.baudRate = static_cast<QSerialPort::BaudRate>(
		                               ui->baudRateBox->itemData(ui->baudRateBox->currentIndex()).toInt());
	}
	currentSettings.stringBaudRate = QString::number(currentSettings.baudRate);

	currentSettings.dataBits = static_cast<QSerialPort::DataBits>(
	                               ui->dataBitsBox->itemData(ui->dataBitsBox->currentIndex()).toInt());
	currentSettings.stringDataBits = ui->dataBitsBox->currentText();

	currentSettings.parity = static_cast<QSerialPort::Parity>(
	                             ui->parityBox->itemData(ui->parityBox->currentIndex()).toInt());
	currentSettings.stringParity = ui->parityBox->currentText();

	currentSettings.stopBits = static_cast<QSerialPort::StopBits>(
	                               ui->stopBitsBox->itemData(ui->stopBitsBox->currentIndex()).toInt());
	currentSettings.stringStopBits = ui->stopBitsBox->currentText();

	currentSettings.flowControl = static_cast<QSerialPort::FlowControl>(
	                                  ui->flowControlBox->itemData(ui->flowControlBox->currentIndex()).toInt());
	currentSettings.stringFlowControl = ui->flowControlBox->currentText();

	currentSettings.localEchoEnabled = ui->localEchoCheckBox->isChecked();
}
