/*
Gwenview - printing support
Copyright (c) 2003 Angelo Naselli
 
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
 
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.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
*/
// TQt
#include <tqcheckbox.h>
#include <tqlayout.h>
#include <tqpainter.h>
#include <tqradiobutton.h>
#include <tqvbuttongroup.h>

// KDE
#include <kcombobox.h>
#include <kdebug.h>
#include <kdialog.h>
#include <tdelocale.h>
#include <knuminput.h>
#include <kprinter.h>

// Local
#include "document.h"
#include "printdialogpagebase.h"
#include "printdialog.moc"

namespace Gwenview {


const char* STR_TRUE="true";
const char* STR_FALSE="false";

static inline Unit stringToUnit(const TQString& unit) {
	if (unit == i18n("Millimeters")) {
		return GV_MILLIMETERS;
	} else if (unit == i18n("Centimeters")) {
		return GV_CENTIMETERS;
	} else {//Inches
		return GV_INCHES;
	}
}

static inline TQString unitToString(Unit unit) {
	if (unit == GV_MILLIMETERS) {
		return i18n("Millimeters");
	} else if (unit == GV_CENTIMETERS) {
		return i18n("Centimeters");
	} else { //GV_INCHES
		return i18n("Inches");
	}
}


static inline double unitToMM(Unit unit) {
	if (unit == GV_MILLIMETERS) {
		return 1.;
	} else if (unit == GV_CENTIMETERS) {
		return 10.;
	} else { //GV_INCHES
		return 25.4;
	}
}


PrintDialogPage::PrintDialogPage( Document* document, TQWidget *parent, const char *name )
		: KPrintDialogPage( parent, name ) {
	mDocument = document;
	mContent = new PrintDialogPageBase(this);
	setTitle( mContent->caption() );

	TQVBoxLayout *layout = new TQVBoxLayout( this );
	layout->addWidget( mContent );

	connect(mContent->mWidth, TQ_SIGNAL( valueChanged( double )), TQ_SLOT( slotWidthChanged( double )));
	connect(mContent->mHeight, TQ_SIGNAL( valueChanged( double )), TQ_SLOT( slotHeightChanged( double )));
	connect(mContent->mKeepRatio, TQ_SIGNAL( toggled( bool )), TQ_SLOT( toggleRatio( bool )));
	connect(mContent->mUnit, TQ_SIGNAL(activated(const TQString &)), TQ_SLOT(slotUnitChanged(const TQString& )));

	mPreviousUnit = GV_MILLIMETERS;
}

PrintDialogPage::~PrintDialogPage() {}

void PrintDialogPage::getOptions( TQMap<TQString,TQString>& opts, bool /*incldef*/ ) {
	opts["app-gwenview-position"] = TQString::number(getPosition(mContent->mPosition->currentText()));
	opts["app-gwenview-printFilename"] = mContent->mAddFileName->isChecked() ? STR_TRUE : STR_FALSE;
	opts["app-gwenview-printComment"] = mContent->mAddComment->isChecked() ? STR_TRUE : STR_FALSE;
	opts["app-gwenview-scale"] = TQString::number(
		mContent->mNoScale->isChecked() ? GV_NOSCALE
		: mContent->mFitToPage->isChecked() ? GV_FITTOPAGE
		: GV_SCALE);
	opts["app-gwenview-fitToPage"] = mContent->mFitToPage->isChecked() ? STR_TRUE : STR_FALSE;
	opts["app-gwenview-enlargeToFit"] = mContent->mEnlargeToFit->isChecked() ? STR_TRUE : STR_FALSE;

	opts["app-gwenview-scaleKeepRatio"] = mContent->mKeepRatio->isChecked() ? STR_TRUE : STR_FALSE;
	opts["app-gwenview-scaleUnit"] = TQString::number(stringToUnit(mContent->mUnit->currentText()));
	opts["app-gwenview-scaleWidth"] = TQString::number( scaleWidth() );
	opts["app-gwenview-scaleHeight"] = TQString::number( scaleHeight() );

}

void PrintDialogPage::setOptions( const TQMap<TQString,TQString>& opts ) {
	int val;
	bool ok;
	TQString stVal;

	val = opts["app-gwenview-position"].toInt( &ok );
	if (ok) {
		stVal = setPosition(val);
		mContent->mPosition->setCurrentItem(stVal);
	}

	mContent->mAddFileName->setChecked( opts["app-gwenview-printFilename"] == STR_TRUE );
	mContent->mAddComment->setChecked( opts["app-gwenview-printComment"] == STR_TRUE );
	// Starts from id 1 because 0 is returned if not ok, and seems to have a weird
	// problem with id 2 (last id) otherwise :(
	ScaleId scaleButtonId = static_cast<ScaleId>( opts["app-gwenview-scale"].toInt( &ok ) );
 	if (ok) {
		mContent->mScaleGroup->setButton( scaleButtonId );
 	} else {
 		mContent->mScaleGroup->setButton( GV_NOSCALE );
 	}
	mContent->mEnlargeToFit->setChecked( opts["app-gwenview-enlargeToFit"] == STR_TRUE );

	Unit unit = static_cast<Unit>( opts["app-gwenview-scaleUnit"].toInt( &ok ) );
	if (ok) {
		stVal = unitToString(unit);
		mContent->mUnit->setCurrentItem(stVal);
		mPreviousUnit = unit;
	}

	mContent->mKeepRatio->setChecked( opts["app-gwenview-scaleKeepRatio"] == STR_TRUE );

	double dbl;
	dbl = opts["app-gwenview-scaleWidth"].toDouble( &ok );
	if ( ok ) setScaleWidth( dbl );
	dbl = opts["app-gwenview-scaleHeight"].toDouble( &ok );
	if ( ok ) setScaleHeight( dbl );
}

double PrintDialogPage::scaleWidth() const {
	return mContent->mWidth->value();
}

double PrintDialogPage::scaleHeight() const {
	return mContent->mHeight->value();
}

void PrintDialogPage::setScaleWidth( double value ) {
	mContent->mWidth->setValue(value);
}

void PrintDialogPage::setScaleHeight( double value ) {
	mContent->mHeight->setValue(value);
}

int PrintDialogPage::getPosition(const TQString& align) {
	int alignment;

	if (align == i18n("Central-Left")) {
		alignment = TQt::AlignLeft | TQt::AlignVCenter;
	} else if (align == i18n("Central-Right")) {
		alignment = TQt::AlignRight | TQt::AlignVCenter;
	} else if (align == i18n("Top-Left")) {
		alignment = TQt::AlignTop | TQt::AlignLeft;
	} else if (align == i18n("Top-Right")) {
		alignment = TQt::AlignTop | TQt::AlignRight;
	} else if (align == i18n("Bottom-Left")) {
		alignment = TQt::AlignBottom | TQt::AlignLeft;
	} else if (align == i18n("Bottom-Right")) {
		alignment = TQt::AlignBottom | TQt::AlignRight;
	} else if (align == i18n("Top-Central")) {
		alignment = TQt::AlignTop | TQt::AlignHCenter;
	} else if (align == i18n("Bottom-Central")) {
		alignment = TQt::AlignBottom | TQt::AlignHCenter;
	} else	{
		// Central
		alignment = TQt::AlignCenter; // TQt::AlignHCenter || TQt::AlignVCenter
	}

	return alignment;
}

TQString PrintDialogPage::setPosition(int align) {
	TQString alignment;

	if (align == (TQt::AlignLeft | TQt::AlignVCenter)) {
		alignment = i18n("Central-Left");
	} else if (align == (TQt::AlignRight | TQt::AlignVCenter)) {
		alignment = i18n("Central-Right");
	} else if (align == (TQt::AlignTop | TQt::AlignLeft)) {
		alignment = i18n("Top-Left");
	} else if (align == (TQt::AlignTop | TQt::AlignRight)) {
		alignment = i18n("Top-Right");
	} else if (align == (TQt::AlignBottom | TQt::AlignLeft)) {
		alignment = i18n("Bottom-Left");
	} else if (align == (TQt::AlignBottom | TQt::AlignRight)) {
		alignment = i18n("Bottom-Right");
	} else if (align == (TQt::AlignTop | TQt::AlignHCenter)) {
		alignment = i18n("Top-Central");
	} else if (align == (TQt::AlignBottom | TQt::AlignHCenter)) {
		alignment = i18n("Bottom-Central");
	} else	{
		// Central: TQt::AlignCenter or (TQt::AlignHCenter || TQt::AlignVCenter)
		alignment = i18n("Central");
	}

	return alignment;
}

// SLOTS
void PrintDialogPage::slotHeightChanged (double value) {
	mContent->mWidth->blockSignals(true);
	mContent->mHeight->blockSignals(true);

	if (mContent->mKeepRatio->isChecked()) {
		double width = (mDocument->width() * value) / mDocument->height();
		mContent->mWidth->setValue( width ? width : 1.);
	}
	mContent->mHeight->setValue(value);

	mContent->mWidth->blockSignals(false);
	mContent->mHeight->blockSignals(false);

}

void PrintDialogPage::slotWidthChanged (double value) {
	mContent->mWidth->blockSignals(true);
	mContent->mHeight->blockSignals(true);
	if (mContent->mKeepRatio->isChecked()) {
		double height = (mDocument->height() * value) / mDocument->width();
		mContent->mHeight->setValue( height ? height : 1);
	}
	mContent->mWidth->setValue(value);
	mContent->mWidth->blockSignals(false);
	mContent->mHeight->blockSignals(false);
}

void PrintDialogPage::toggleRatio(bool enable) {
	if (!enable) return;
	// choosing a startup value of 15x10 cm (common photo dimention)
	// mContent->mHeight->value() or mContent->mWidth->value()
	// are usually empty at startup and hxw (0x0) isn't good IMO keeping ratio
	double hValue, wValue;
	if (mDocument->height() > mDocument->width()) {
		hValue = mContent->mHeight->value();
		if (!hValue) hValue = 150*unitToMM(mPreviousUnit);
		wValue = (mDocument->width() * hValue)/ mDocument->height();
	} else {
		wValue = mContent->mWidth->value();
		if (!wValue) wValue = 150*unitToMM(mPreviousUnit);
		hValue = (mDocument->height() * wValue)/ mDocument->width();
	}
	
	mContent->mWidth->blockSignals(true);
	mContent->mHeight->blockSignals(true);
	mContent->mWidth->setValue(wValue);
	mContent->mHeight->setValue(hValue);
	mContent->mWidth->blockSignals(false);
	mContent->mHeight->blockSignals(false);
}


void PrintDialogPage::slotUnitChanged(const TQString& string) {
	Unit newUnit = stringToUnit(string);
	double ratio = unitToMM(mPreviousUnit) / unitToMM(newUnit);

	mContent->mWidth->blockSignals(true);
	mContent->mHeight->blockSignals(true);

	mContent->mWidth->setValue( mContent->mWidth->value() * ratio);
	mContent->mHeight->setValue( mContent->mHeight->value() * ratio);

	mContent->mWidth->blockSignals(false);
	mContent->mHeight->blockSignals(false);

	mPreviousUnit = newUnit;
}




} // namespace
