/*****************************************************************************
 *
 *  splitmoviedialog.cpp -- Configure a split movie operation.
 * 
 *  Copyright (C) 2010 Starbuck <starbuck@labdv.com>
 *  All rights reserved.
 *
 *  This file is part of the Gui4 module of the DVDx 4 application.
 *
 *  GNU Lesser General Public License Usage
 *  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.
 *
 *  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.
 *
 *****************************************************************************/

#include "splitmoviedialog.h"

#ifndef WIN32
#include <math.h>
#endif
#include <QDebug>
#include <QFileInfo>
#include <QTimer>

SplitMovieDialog::SplitMovieDialog(qint64 inputFileSize, 
	const QString &inputFolder, QString *outputFolder, 
	int *volumeNumber, qint64 *volumeSize, QWidget *parent)
	: QDialog(parent)
{
	m_inputFileSize = inputFileSize;
	m_minimumOutputFileSize = 50*pow(10.0, 6); // 50 MBytes
	m_maximumDivideValue = qMin(8, qMax(3, int(inputFileSize / m_minimumOutputFileSize) + 1));
	m_outputFolder = outputFolder;
	m_outputFolderDefault = *outputFolder;
	m_outputFolderInPlace = inputFolder;
	*m_outputFolder = m_outputFolderDefault;
	m_volumeNumber = volumeNumber;
	m_volumeSize = volumeSize;

	m_volumeSizeCD700 = 737.0*pow(10.0, 6);
	m_volumeSizeCD800 = 826.0*pow(10.0, 6);
	m_volumeSizeCD900 = 912.0*pow(10.0, 6);
	m_volumeSizeDVD5 = 4700.0*pow(10.0, 6);
	m_volumeSizeDVD9 = 8540.0*pow(10.0, 6);

	m_volumeGroup = new QGroupBox();
	m_volumeLayout = new QVBoxLayout(m_volumeGroup);
	m_volumeCD700Button = new QRadioButton( tr("700MB CD"), m_volumeGroup );
	m_volumeCD700Button->setToolTip( tr("737 MegaBytes") );
	m_volumeCD800Button = new QRadioButton( tr("800MB CD"), m_volumeGroup );
	m_volumeCD800Button->setToolTip( tr("829 MegaBytes") );
	m_volumeCD900Button = new QRadioButton( tr("900MB CD"), m_volumeGroup );
	m_volumeCD900Button->setToolTip( tr("912 MegaBytes") );
	m_volumeDVD5Button = new QRadioButton( tr("4.7GB DVD"), m_volumeGroup );
	m_volumeDVD5Button->setToolTip( tr("4.700 MegaBytes") );
	m_volumeDVD9Button = new QRadioButton( tr("8.5GB DVD"), m_volumeGroup );
	m_volumeDVD9Button->setToolTip( tr("8.540 MegaBytes") );
	m_volumeUserLayout = new QHBoxLayout();
	m_volumeUserButton = new QRadioButton( m_volumeGroup );
	m_volumeUserInput = new QLineEdit( "", m_volumeGroup );
	m_volumeUserInput->setToolTip( tr("User defined slice") );
	m_volumeUserComboBox = new QComboBox(m_volumeGroup);
	m_volumeUserComboBox->addItem( tr("MB"), pow(10.0, 6) );
	m_volumeUserComboBox->addItem( tr("GB"), pow(10.0, 9) );
	m_volumeUserLayout->addWidget(m_volumeUserButton);
	m_volumeUserLayout->addWidget(m_volumeUserInput);
	m_volumeUserLayout->addWidget(m_volumeUserComboBox);
	m_volumeUserLayout->addStretch(4);
	m_volumeLayout->addWidget(m_volumeCD700Button);
	m_volumeLayout->addWidget(m_volumeCD800Button);
	m_volumeLayout->addWidget(m_volumeCD900Button);
	m_volumeLayout->addWidget(m_volumeDVD5Button);
	m_volumeLayout->addWidget(m_volumeDVD9Button);
	m_volumeLayout->addItem(m_volumeUserLayout);

	connect(m_volumeCD700Button, SIGNAL(clicked(bool)), this, SLOT(volumeUpdateSelection()));
	connect(m_volumeCD800Button, SIGNAL(clicked(bool)), this, SLOT(volumeUpdateSelection()));
	connect(m_volumeCD900Button, SIGNAL(clicked(bool)), this, SLOT(volumeUpdateSelection()));
	connect(m_volumeDVD5Button, SIGNAL(clicked(bool)), this, SLOT(volumeUpdateSelection()));
	connect(m_volumeDVD9Button, SIGNAL(clicked(bool)), this, SLOT(volumeUpdateSelection()));
	connect(m_volumeUserButton, SIGNAL(clicked(bool)), this, SLOT(volumeSelectUser()));
	connect(m_volumeUserButton, SIGNAL(clicked(bool)), this, SLOT(volumeUpdateSelection()));
	connect(m_volumeUserInput, SIGNAL(cursorPositionChanged(int,int)), this, SLOT(volumeSelectUser()));
	connect(m_volumeUserInput, SIGNAL(cursorPositionChanged(int,int)), this, SLOT(volumeUpdateSelection()));
	connect(m_volumeUserInput, SIGNAL(editingFinished()), this, SLOT(volumeUserFinishEditing()));
	connect(m_volumeUserInput, SIGNAL(selectionChanged()), this, SLOT(volumeSelectUser()));
	connect(m_volumeUserInput, SIGNAL(selectionChanged()), this, SLOT(volumeUpdateSelection()));
	connect(m_volumeUserInput, SIGNAL(textEdited(QString)), this, SLOT(volumeSelectUser()));
	connect(m_volumeUserInput, SIGNAL(textEdited(QString)), this, SLOT(volumeUpdateSelection()));
	connect(m_volumeUserComboBox, SIGNAL(activated(int)), this, SLOT(volumeSelectUser()));
	connect(m_volumeUserComboBox, SIGNAL(activated(int)), this, SLOT(volumeUpdateSelection()));
	connect(m_volumeUserComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(volumeUserChangeUnit()));

	m_divideGroup = new QGroupBox();
	m_divideLayout = new QHBoxLayout(m_divideGroup);
	m_divideLabel = new QLabel(m_divideGroup);
	m_divideSpinBox = new QSpinBox( m_divideGroup );
	m_divideSpinBox->setRange( 2, m_maximumDivideValue );
	m_divideLayout->addWidget(m_divideSpinBox);
	m_divideLayout->addWidget(m_divideLabel);

	connect(m_divideSpinBox, SIGNAL(valueChanged(int)), this, SLOT(divideSetValue(int)));

	m_methodGroup = new QButtonGroup();
	m_methodVolumeButton = new QRadioButton();
	m_methodDivideButton = new QRadioButton();
	m_methodGroup->addButton(m_methodVolumeButton);
	m_methodGroup->addButton(m_methodDivideButton);

	connect(m_methodVolumeButton, SIGNAL(clicked(bool)), this, SLOT(methodSetVolume()));
	connect(m_methodDivideButton, SIGNAL(clicked(bool)), this, SLOT(methodSetDivide()));

	m_folderGroup = new QGroupBox(tr("Output folder"));
	m_folderLayout = new QVBoxLayout(m_folderGroup);
	m_folderChoiceDefaultButton = new QRadioButton(tr("Split in user folder"), m_folderGroup);
	m_folderChoiceDefaultButton->setToolTip(m_outputFolderDefault);
	m_folderChoiceInPlaceButton = new QRadioButton(tr("Split in input folder"), m_folderGroup);
	m_folderChoiceInPlaceButton->setToolTip(m_outputFolderInPlace);
	m_folderLayout->addWidget(m_folderChoiceDefaultButton);
	m_folderLayout->addWidget(m_folderChoiceInPlaceButton);

	connect(m_folderChoiceDefaultButton, SIGNAL(clicked(bool)), this, SLOT(folderSetChoice()));
	connect(m_folderChoiceInPlaceButton, SIGNAL(clicked(bool)), this, SLOT(folderSetChoice()));

	m_windowButtonAccept = new QPushButton(tr("Split movie"), this);
	m_windowButtonAccept->setToolTip(tr("Start split job"));
	m_windowButtonReject = new QPushButton(tr("Cancel"), this);
	m_windowButtonReject->setToolTip(tr("Cancel split operation"));

	m_windowButtonLayout = new QHBoxLayout();
#ifdef Q_OS_MAC
	m_windowButtonLayout->setSpacing(10);
#endif
	m_windowButtonLayout->addStretch(3);
	m_windowButtonLayout->addWidget(m_windowButtonAccept);
	m_windowButtonLayout->addWidget(m_windowButtonReject);
	
	connect(m_windowButtonAccept, SIGNAL(clicked()), this, SLOT(accept()));
	connect(m_windowButtonReject, SIGNAL(clicked()), this, SLOT(reject()));

	m_windowLayout = new QVBoxLayout(this);
	m_windowLayout->addWidget(m_methodVolumeButton);
	m_windowLayout->addWidget(m_volumeGroup);
	m_windowLayout->addWidget(m_methodDivideButton);
	m_windowLayout->addWidget(m_divideGroup);
	m_windowLayout->addWidget(m_folderGroup);
	m_windowLayout->addItem(m_windowButtonLayout);

	setLayout(m_windowLayout);
	setAttribute(Qt::WA_AlwaysShowToolTips);
	setWindowTitle( tr("Movie split options") );

	divideSetValue( 2 );

	if (m_inputFileSize < m_volumeSizeCD700) 
	{
		m_volumeUserInput->setText(QString::number(qint64(m_inputFileSize / 2 / pow(10.0, 6))));
		m_volumeUserButton->setChecked(true);
		volumeUpdateSelection();

		m_methodDivideButton->setChecked(true);
		methodSetDivide();
	}
	else
	{
		m_methodVolumeButton->setChecked(true);
		m_volumeCD700Button->setChecked(true);
		methodSetVolume();
	}

	m_folderChoiceDefaultButton->setChecked(true);
}

void SplitMovieDialog::divideSetValue(int value)
{
	if (value < m_divideSpinBox->minimum()) value = m_divideSpinBox->minimum();
	if (value > m_divideSpinBox->maximum()) value = m_divideSpinBox->maximum();

	m_divideSpinBox->setValue( value );

	divideUpdateSelection();
}

void SplitMovieDialog::divideUpdateSelection()
{
	*m_volumeNumber = m_divideSpinBox->value();

	int megaSize = m_inputFileSize / *m_volumeNumber / pow(10.0, 6);

	if (megaSize >= 1000)
	{
		double gigaSize = (double)megaSize / pow(10.0, 3);
		m_methodDivideButton->setText( tr("Split in %1 volumes (%2GB)")
			.arg(*m_volumeNumber).arg(gigaSize, 0, 'f', 2) );
	}
	else
	{
		m_methodDivideButton->setText( tr("Split in %1 volumes (%2MB)")
			.arg(*m_volumeNumber).arg(megaSize) );
	}

	*m_volumeSize = megaSize * 1000000;
}

void SplitMovieDialog::folderSetChoice()
{
	if (m_folderChoiceInPlaceButton->isChecked())
	{
		*m_outputFolder = m_outputFolderInPlace;
	}
	else
	{
		*m_outputFolder = m_outputFolderDefault;
	}
}

void SplitMovieDialog::methodSetDivide()
{
	m_methodDivideButton->setChecked(true);

	m_divideGroup->setEnabled( true );
	m_volumeGroup->setEnabled( false );

	divideUpdateSelection();
}

void SplitMovieDialog::methodSetVolume()
{
	m_methodVolumeButton->setChecked(true);

	m_divideGroup->setEnabled( false );
	m_volumeGroup->setEnabled( true );

	m_volumeCD700Button->setEnabled(m_inputFileSize > m_volumeSizeCD700);
	m_volumeCD800Button->setEnabled(m_inputFileSize > m_volumeSizeCD800);
	m_volumeCD900Button->setEnabled(m_inputFileSize > m_volumeSizeCD900);
	m_volumeDVD5Button->setEnabled(m_inputFileSize > m_volumeSizeDVD5);
	m_volumeDVD9Button->setEnabled(m_inputFileSize > m_volumeSizeDVD9);

	volumeUpdateSelection();
}

void SplitMovieDialog::volumeSelectUser()
{
	m_volumeUserButton->setChecked(true);
}

void SplitMovieDialog::volumeUpdateSelection()
{
	double restDisplay;
	qint64 rest;

	if (m_volumeCD700Button->isChecked())		*m_volumeSize = m_volumeSizeCD700;
	else if (m_volumeCD800Button->isChecked())	*m_volumeSize = m_volumeSizeCD800;
	else if (m_volumeCD900Button->isChecked())	*m_volumeSize = m_volumeSizeCD900;
	else if (m_volumeDVD5Button->isChecked())	*m_volumeSize = m_volumeSizeDVD5;
	else if (m_volumeDVD9Button->isChecked())	*m_volumeSize = m_volumeSizeDVD9;
	else
	{
		*m_volumeSize = m_volumeUserInput->text().toDouble()
			* m_volumeUserComboBox->itemData( m_volumeUserComboBox->currentIndex() ).toDouble();
	}

	if (*m_volumeSize <= 0 || *m_volumeSize > m_inputFileSize) 
	{
		m_methodVolumeButton->setText( tr("Split in ...") );
		m_windowButtonAccept->setEnabled(false);
		return;  // avoid DIV/0 
	}	
	
	m_windowButtonAccept->setEnabled(true);

	rest = m_inputFileSize % *m_volumeSize;

	*m_volumeNumber = rest ? int(m_inputFileSize / *m_volumeSize) + 1 
							: int(m_inputFileSize / *m_volumeSize);

	if ((*m_volumeSize < m_volumeSizeDVD5 && !m_volumeUserButton->isChecked())
		|| (m_volumeUserButton->isChecked() 
			&& m_volumeUserComboBox->itemData( m_volumeUserComboBox->currentIndex() )
				.toDouble() == pow(10.0, 6)))
	{
		restDisplay = (double)rest / pow(10.0, 6);
		
		if (*m_volumeNumber == 1)
		{
			m_methodVolumeButton->setText( tr("Split in 2 volumes: %1MB + %2MB")
				.arg(*m_volumeSize / pow(10.0, 6)).arg(restDisplay, 0, 'f', 2) );
		}
		else
		{
			m_methodVolumeButton->setText( tr("Split in %1 volumes: %2 x %3MB + %4MB")
				.arg(*m_volumeNumber).arg(*m_volumeNumber - 1)
				.arg(*m_volumeSize / pow(10.0, 6)).arg(restDisplay, 0, 'f', 2) );
		}
	}
	else
	{
		restDisplay = (double)rest / pow(10.0, 9);
		
		if (*m_volumeNumber == 2)
		{
			m_methodVolumeButton->setText( tr("Split in 2 volumes: %1GB + %2GB")
				.arg(*m_volumeSize / pow(10.0, 9)).arg(restDisplay, 0, 'f', 2) );
		}
		else
		{
			m_methodVolumeButton->setText( tr("Split in %1 volumes: %2 x %3GB + %4GB")
				.arg(*m_volumeNumber).arg(*m_volumeNumber - 1)
				.arg(*m_volumeSize / pow(10.0, 9)).arg(restDisplay, 0, 'f', 2) );
		}
	}
}

void SplitMovieDialog::volumeUserChangeUnit()
{
	double userDefinedSize = m_volumeUserInput->text().toDouble();

	if (!userDefinedSize) return; 

	// Convert edited value MB from/to GB
	double convertFactor(1000.0);  // GB -> MB
	if (m_volumeUserComboBox->itemData( m_volumeUserComboBox->currentIndex() )
			.toDouble() == pow(10.0, 9))
	{
		convertFactor = 1.0 / 1000.0;  // MB -> GB
	}

	m_volumeUserInput->setText(QString::number(userDefinedSize * convertFactor));

	volumeUpdateSelection();
}

void SplitMovieDialog::volumeUserCorrectInput()
{
	double userDefinedSize = m_volumeUserInput->text().toDouble();
	
	if (userDefinedSize == 0.0)
	{
		if (m_volumeUserComboBox->itemData( m_volumeUserComboBox->currentIndex() )
			.toDouble() == pow(10.0, 6))
		{
			userDefinedSize = 690.0;
		}
		else
		{
			userDefinedSize = 4.50;
		}
	}

	m_volumeUserInput->setText(QString::number(userDefinedSize));
}

void SplitMovieDialog::volumeUserFinishEditing()
{
	volumeUserCorrectInput();
}

