/*
 *  Copyright (C) 2007-2008 CMM Sigma Andrzej Chmielowiec <cmmsigma@cmmsigma.eu>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 3
 *  as published by the Free Software Foundation.
 *
 *  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.
 */

#include "CaNewDialog.h"
#include "STokenDialog.h"

#include <QtGui>

QLineEditFiltered::QLineEditFiltered(QWidget *parent): QLineEdit(parent)
{
	connect(this, SIGNAL(textChanged(const QString&)), this, 
		SLOT(textCheck(const QString&)));
}

void
QLineEditFiltered::textCheck(const QString &name)
{
	foreach (QChar c, name)
	{
		if ((c < 'a' || c > 'z') 
			&& (c < 'A' || c > 'Z') 
			&& (c < '0' || c > '9') 
			&& c != '-' && c != '_'
			&& c != ' ')
		{
			QMessageBox::information(this, tr("Incorrect data"), 
				tr("This field can store alphanumeric characters "
				"[a-z][A-Z][0-9], '_', '-' and ' ' only."));
			setText(mCorrectText);
		}
	}
	
	mCorrectText = text();
}


CaNewDialog::CaNewDialog(QWidget *parent, Qt::WindowFlags f): QDialog(parent, f)
{
	QGridLayout *layout = new QGridLayout();
	
	mailWidget = new MailAccountWidget(true, true, this);

	QTabWidget *tab = new QTabWidget();
	tab->addTab(createGeneralTab(), tr("General"));
	tab->addTab(createCaSubjectTab(), tr("CA data"));
	tab->addTab(createPolicyTab(), tr("CA policy"));
	tab->addTab(mailWidget, tr("Mail account"));
	
	mCancel = new QPushButton(tr("Ca&ncel"));
	connect(mCancel, SIGNAL(clicked()), this, SLOT(reject()));
	mAccept = new QPushButton(tr("Crea&te"));
	connect(mAccept, SIGNAL(clicked()), this, SLOT(accept()));
	
	layout->addWidget(tab, 0, 0, 1, 3);
	layout->addWidget(mAccept, 1, 1);
	layout->addWidget(mCancel, 1, 2);
	
	layout->setColumnStretch(0, 1);
	layout->setRowStretch(0, 1);
	
	setLayout(layout);
}

QString
CaNewDialog::name()
{
	return mName->text();
}

QString
CaNewDialog::caKeyName()
{
	return mCaKeyName->text();
}

int
CaNewDialog::defaultCertDays()
{
	return mDefaultCertDays->value();
}

int
CaNewDialog::defaultCrlDays()
{
	return mDefaultCrlDays->value();
}

QString
CaNewDialog::caAlgo()
{
	return mDefaultAlgo->itemData(mDefaultAlgo->currentIndex()).toString();
}

QString
CaNewDialog::defaultMD()
{
	QString md = mDefaultMD->itemData(mDefaultMD->currentIndex()).toString();
	
	if (caAlgo().startsWith(QString("ec:")))
		md = QString("ecdsa-with-") + md;
	
	else
		md = md + QString("WithRSAEncryption");
	
	return md;
}

int
CaNewDialog::caCertDays()
{
	return mCaCertDays->value();
}

QString
CaNewDialog::caSubject()
{
	QString subject;
	
	if (mCaCountryCode->text() != QString())
		subject.append("/C=").append(mCaCountryCode->text());
	
	if (mCaStateOrProvinceName->text() != QString())
		subject.append("/ST=").append(mCaStateOrProvinceName->text());
	
	if (mCaLocalityName->text() != QString())
		subject.append("/L=").append(mCaLocalityName->text());
	
	if (mCaOrganizationName->text() != QString())
		subject.append("/O=").append(mCaOrganizationName->text());
	
	if (mCaOrganizationalUnitName->text() != QString())
		subject.append("/OU=").append(mCaOrganizationalUnitName->text());
	
	if (mCaCommonName->text() != QString())
		subject.append("/CN=").append(mCaCommonName->text());
	
	if (mCaEmailAddress->text() != QString())
		subject.append("/emailAddress=").append(mCaEmailAddress->text());
	
	return subject;
}

QString
CaNewDialog::policyCountryName()
{
	QComboBox *combo = mPolicyCountryName;
	return combo->itemData(combo->currentIndex()).toString();
}

QString
CaNewDialog::policyStateOrProvinceName()
{
	QComboBox *combo = mPolicyStateOrProvinceName;
	return combo->itemData(combo->currentIndex()).toString();
}

QString
CaNewDialog::policyLocalityName()
{
	QComboBox *combo = mPolicyLocalityName;
	return combo->itemData(combo->currentIndex()).toString();
}

QString
CaNewDialog::policyOrganizationName()
{
	QComboBox *combo = mPolicyOrganizationName;
	return combo->itemData(combo->currentIndex()).toString();
}

QString
CaNewDialog::policyOrganizationalUnitName()
{
	QComboBox *combo = mPolicyOrganizationalUnitName;
	return combo->itemData(combo->currentIndex()).toString();
}

QString
CaNewDialog::policyCommonName()
{
	QComboBox *combo = mPolicyCommonName;
	return combo->itemData(combo->currentIndex()).toString();
}

QString
CaNewDialog::policyEmailAddress()
{
	QComboBox *combo = mPolicyEmailAddress;
	return combo->itemData(combo->currentIndex()).toString();
}

void
CaNewDialog::accept()
{
	if (mName->text().isEmpty())
	{
		QMessageBox::information(this, tr("Missing data"), tr("Enter CA's name."));
		return;
	}
	
#ifndef STOKEN_SOFT
	if (mCaKeyName->text().isEmpty())
	{
		QMessageBox::information(this, tr("Missing data"), tr("Enter CA's key name."));
		return;
	}
#endif
	
	if (mCaCommonName->text().isEmpty())
	{
		QMessageBox::information(this, tr("Missing data"), tr("Enter CA's common "
			"name (this field is required)."));
		return;
	}
	
	if (QDir(mName->text()).exists())
	{
		QMessageBox::information(this, QObject::tr("Information"), QObject::tr("CA with given "
			"name already exists. Please specify other name."));
		return;
	}
	
	QDialog::accept();
}

void
CaNewDialog::browseCaKeyName()
{
	QString keyName;
	
	keyName = STokenDialog::getKeyName(tr("Key selection"), this);
	
	if (keyName != QString())
		mCaKeyName->setText(keyName);
}

QWidget*
CaNewDialog::createGeneralTab()
{
	QWidget *widget = new QWidget();
	QGridLayout *layout = new QGridLayout();
	
	widget->setLayout(layout);

#ifndef STOKEN_SOFT
	QGroupBox *box = new QGroupBox(tr("CA's name and key"));
#else
	QGroupBox *box = new QGroupBox(tr("CA's name"));
#endif
	QGridLayout *boxLayout = new QGridLayout();
	
	box->setLayout(boxLayout);
	
	mName = new QLineEditFiltered();
	mCaKeyName = new QLineEdit();
	
#ifndef STOKEN_SOFT
	mCaKeyBrowse = new QPushButton(tr("Select"));
	connect(mCaKeyBrowse, SIGNAL(clicked()), this, SLOT(browseCaKeyName()));
	boxLayout->addWidget(new QLabel(tr("CA's key<sup>*</sup>")), 1, 0);
	boxLayout->addWidget(mCaKeyName, 1, 1, 1, 2);
	boxLayout->addWidget(mCaKeyBrowse, 2, 2);
#endif
	boxLayout->addWidget(new QLabel(tr("CA's name<sup>*</sup>")), 0, 0);
	boxLayout->addWidget(mName, 0, 1, 1, 2);
	boxLayout->setColumnStretch(1, 1);
	
	layout->addWidget(box, 0, 0);
	
	box = new QGroupBox(tr("Default settings"));
	boxLayout = new QGridLayout();
	
	box->setLayout(boxLayout);
	
	mDefaultCertDays = new QSpinBox();
	mDefaultCertDays->setMinimum(1);
	mDefaultCertDays->setMaximum(20 * 365);
	mDefaultCertDays->setValue(365);
	mDefaultCertDays->setSuffix(tr(" [days]"));
	
	mDefaultCrlDays = new QSpinBox();
	mDefaultCrlDays->setMinimum(1);
	mDefaultCrlDays->setMaximum(183);
	mDefaultCrlDays->setValue(30);
	mDefaultCrlDays->setSuffix(tr(" [days]"));
	
	mDefaultAlgo = new QComboBox();
	mDefaultAlgo->addItem(QString("ECDSA-256"), QVariant(QString("ec:prime256v1")));
	mDefaultAlgo->addItem(QString("ECDSA-384"), QVariant(QString("ec:secp384r1")));
	mDefaultAlgo->addItem(QString("RSA-2048"), QVariant(QString("rsa:2048")));
	mDefaultAlgo->addItem(QString("RSA-3072"), QVariant(QString("rsa:3072")));
	mDefaultAlgo->addItem(QString("RSA-4096"), QVariant(QString("rsa:4096")));
	mDefaultAlgo->setCurrentIndex(0);
#ifndef STOKEN_SOFT
	mDefaultAlgo->setEnabled(false);
#endif
	
	mDefaultMD = new QComboBox();
	mDefaultMD->addItem(QString("SHA-256"), QVariant(QString("sha256")));
	mDefaultMD->addItem(QString("SHA-224"), QVariant(QString("sha224")));
	mDefaultMD->addItem(QString("SHA-1"), QVariant(QString("sha1")));
	mDefaultMD->setCurrentIndex(0);
	
	boxLayout->addWidget(new QLabel(tr("User certificate vaildity period")), 0, 0);
	boxLayout->addWidget(mDefaultCertDays, 0, 1, 1, 2);
	boxLayout->addWidget(new QLabel(tr("CRL list vaildity period")), 1, 0);
	boxLayout->addWidget(mDefaultCrlDays, 1, 1, 1, 2);
	boxLayout->addWidget(new QLabel(tr("Signature algorithm")), 2, 0);
	boxLayout->addWidget(mDefaultAlgo, 2, 1, 1, 2);
	boxLayout->addWidget(new QLabel(tr("Hash function")), 3, 0);
	boxLayout->addWidget(mDefaultMD, 3, 1, 1, 2);
	boxLayout->setColumnStretch(1, 1);
	
	layout->addWidget(box, 1, 0);
	
	layout->setRowStretch(2, 1);
	
	return widget;
}

QWidget*
CaNewDialog::createCaSubjectTab()
{
	QWidget *widget = new QWidget();
	QGridLayout *layout = new QGridLayout();
	
	widget->setLayout(layout);
	
	QGroupBox *box = new QGroupBox(tr("CA's certificate validity"));
	QGridLayout *boxLayout = new QGridLayout();
	
	box->setLayout(boxLayout);
	
	mCaCertDays = new QSpinBox();
	mCaCertDays->setMinimum(1);
	mCaCertDays->setMaximum(20 * 365);
	mCaCertDays->setValue(20 * 365);
	mCaCertDays->setSuffix(tr(" [days]"));
	
	boxLayout->addWidget(new QLabel(tr("Certificate validity period")), 0, 0);
	boxLayout->addWidget(mCaCertDays, 0, 1);
	
	boxLayout->setColumnStretch(1, 1);
	layout->addWidget(box, 0, 0);
	
	box = new QGroupBox(tr("CA's information"));
	boxLayout = new QGridLayout();
	
	box->setLayout(boxLayout);
	
	boxLayout->addWidget(new QLabel(tr("Country code")), 0, 0);
	mCaCountryCode = new QLineEdit;
	mCaCountryCode->setMaxLength(2);
	boxLayout->addWidget(mCaCountryCode, 0, 1);
	
	boxLayout->addWidget(new QLabel(tr("Region")), 1, 0);
	mCaStateOrProvinceName = new QLineEditFiltered;
	boxLayout->addWidget(mCaStateOrProvinceName, 1, 1);
	
	boxLayout->addWidget(new QLabel(tr("City")), 2, 0);
	mCaLocalityName = new QLineEditFiltered;
	boxLayout->addWidget(mCaLocalityName, 2, 1);
	
	boxLayout->addWidget(new QLabel(tr("Organization")), 3, 0);
	mCaOrganizationName = new QLineEditFiltered;
	boxLayout->addWidget(mCaOrganizationName, 3, 1);
	
	boxLayout->addWidget(new QLabel(tr("Department")), 4, 0);
	mCaOrganizationalUnitName = new QLineEditFiltered;
	boxLayout->addWidget(mCaOrganizationalUnitName, 4, 1);
	
	boxLayout->addWidget(new QLabel(tr("Common name<sup>*</sup>")), 5, 0);
	mCaCommonName = new QLineEditFiltered;
	connect(mCaCommonName, SIGNAL(textChanged(const QString &)),
		this, SLOT(commonChanged(const QString &)));
	boxLayout->addWidget(mCaCommonName, 5, 1);
	
	boxLayout->addWidget(new QLabel(tr("E-mail")), 6, 0);
	mCaEmailAddress = new QLineEdit;
	connect(mCaEmailAddress, SIGNAL(textChanged(const QString &)),
		this, SLOT(emailChanged(const QString &)));
	boxLayout->addWidget(mCaEmailAddress, 6, 1);
	
	boxLayout->setColumnStretch(1, 1);
	layout->addWidget(box, 1, 0);
	
	layout->addWidget(new QLabel(), 2, 0);
	layout->setRowStretch(2, 1);
	
	return widget;
}

QWidget*
CaNewDialog::createPolicyTab()
{
	QWidget *widget = new QWidget();
	QGridLayout *layout = new QGridLayout();
	
	widget->setLayout(layout);
	
	QGroupBox *box = new QGroupBox(tr("Certified subject information"));
	QGridLayout *boxLayout = new QGridLayout();
	
	box->setLayout(boxLayout);
	
	boxLayout->addWidget(new QLabel(tr("Country code")), 0, 0);
	mPolicyCountryName = new QComboBox();
	mPolicyCountryName->addItem(tr("optional"), QVariant(QString("optional")));
	mPolicyCountryName->addItem(tr("required"), QVariant(QString("supplied")));
	mPolicyCountryName->addItem(tr("significant"), QVariant(QString("match")));
	boxLayout->addWidget(mPolicyCountryName, 0, 1);
	
	boxLayout->addWidget(new QLabel(tr("Region")), 1, 0);
	mPolicyStateOrProvinceName = new QComboBox();
	mPolicyStateOrProvinceName->addItem(tr("optional"), QVariant(QString("optional")));
	mPolicyStateOrProvinceName->addItem(tr("required"), QVariant(QString("supplied")));
	mPolicyStateOrProvinceName->addItem(tr("significant"), QVariant(QString("match")));
	boxLayout->addWidget(mPolicyStateOrProvinceName, 1, 1);
	
	boxLayout->addWidget(new QLabel(tr("City")), 2, 0);
	mPolicyLocalityName = new QComboBox();
	mPolicyLocalityName->addItem(tr("optional"), QVariant(QString("optional")));
	mPolicyLocalityName->addItem(tr("required"), QVariant(QString("supplied")));
	mPolicyLocalityName->addItem(tr("significant"), QVariant(QString("match")));
	boxLayout->addWidget(mPolicyLocalityName, 2, 1);
	
	boxLayout->addWidget(new QLabel(tr("Organization")), 3, 0);
	mPolicyOrganizationName = new QComboBox();
	mPolicyOrganizationName->addItem(tr("optional"), QVariant(QString("optional")));
	mPolicyOrganizationName->addItem(tr("required"), QVariant(QString("supplied")));
	mPolicyOrganizationName->addItem(tr("significant"), QVariant(QString("match")));
	boxLayout->addWidget(mPolicyOrganizationName, 3, 1);
	
	boxLayout->addWidget(new QLabel(tr("Department")), 4, 0);
	mPolicyOrganizationalUnitName = new QComboBox();
	mPolicyOrganizationalUnitName->addItem(tr("optional"), QVariant(QString("optional")));
	mPolicyOrganizationalUnitName->addItem(tr("required"), QVariant(QString("supplied")));
	mPolicyOrganizationalUnitName->addItem(tr("significant"), QVariant(QString("match")));
	boxLayout->addWidget(mPolicyOrganizationalUnitName, 4, 1);
	
	boxLayout->addWidget(new QLabel(tr("Common name")), 5, 0);
	mPolicyCommonName = new QComboBox();
	mPolicyCommonName->addItem(tr("required"), QVariant(QString("supplied")));
	boxLayout->addWidget(mPolicyCommonName, 5, 1);
	
	boxLayout->addWidget(new QLabel(tr("E-mail")), 6, 0);
	mPolicyEmailAddress = new QComboBox();
	mPolicyEmailAddress->addItem(tr("optional"), QVariant(QString("optional")));
	mPolicyEmailAddress->addItem(tr("required"), QVariant(QString("supplied")));
	mPolicyEmailAddress->addItem(tr("significant"), QVariant(QString("match")));
	boxLayout->addWidget(mPolicyEmailAddress, 6, 1);
	
	boxLayout->setColumnStretch(1, 1);
	
	layout->addWidget(box, 0, 0);
	layout->setRowStretch(1, 1);
	
	return widget;
}

MailAccountWidget*
CaNewDialog::getMailWidget()
{
	return mailWidget;
}

void
CaNewDialog::commonChanged(const QString &common)
{
	mailWidget->setUser(common);
}

void
CaNewDialog::emailChanged(const QString &email)
{
	mailWidget->setEmail(email);
}
