/*
 * kxtodvdview.cpp
 *
 * Copyright (C) 2010 Drake Justice <djustice.kde@gmail.com>
 * 
 * GPL n such
 *
 */


#include "kxtodvdview.h"
#include "settings.h"

#include <KLocale>
#include <KIcon>
#include <KFileDialog>

#include <QDebug>
#include <QSize>
#include <QListWidgetItem>
#include <QMessageBox>
#include <QMenu>
#include <QProcess>
#include <QTime>
#include "videofile.h"
#include "encoderthread.h"
#include "authorthread.h"
#include "mkisothread.h"

KxToDvdView::KxToDvdView(QWidget *)
{
    ui_kxtodvdview_base.setupUi(this);
    settingsChanged();
    setAutoFillBackground(true);

    QSize iconSize(32,32);

    ui_kxtodvdview_base.btnAdd->setIcon(KIcon("list-add"));
    ui_kxtodvdview_base.btnAdd->setIconSize(iconSize);
    ui_kxtodvdview_base.btnDelete->setIcon(KIcon("list-remove"));
    ui_kxtodvdview_base.btnDelete->setIconSize(iconSize);
    ui_kxtodvdview_base.btnMoveUp->setIcon(KIcon("go-up"));
    ui_kxtodvdview_base.btnMoveUp->setIconSize(iconSize);
    ui_kxtodvdview_base.btnMoveDown->setIcon(KIcon("go-down"));
    ui_kxtodvdview_base.btnMoveDown->setIconSize(iconSize);
    ui_kxtodvdview_base.btnConfigure->setIcon(KIcon("configure"));
    ui_kxtodvdview_base.btnConfigure->setIconSize(iconSize);
    ui_kxtodvdview_base.btnConfigure->setEnabled(false);
    ui_kxtodvdview_base.btnCreateISO->setIcon(KIcon("tools-media-optical-burn-image"));
    ui_kxtodvdview_base.btnCreateISO->setIconSize(iconSize);
    ui_kxtodvdview_base.btnBurnDVD->setIcon(KIcon("tools-media-optical-burn"));
    ui_kxtodvdview_base.btnBurnDVD->setIconSize(iconSize);

    ui_kxtodvdview_base.progressBar->setMaximum(10800); // 3 hours

    m_burning = false;

    connect(ui_kxtodvdview_base.btnAdd, SIGNAL(clicked()), this, SLOT(btnAddClicked()));
    connect(ui_kxtodvdview_base.btnDelete, SIGNAL(clicked()), this, SLOT(btnDeleteClicked()));
    connect(ui_kxtodvdview_base.btnMoveUp, SIGNAL(clicked()), this, SLOT(btnMoveUpClicked()));
    connect(ui_kxtodvdview_base.btnMoveDown, SIGNAL(clicked()), this, SLOT(btnMoveDownClicked()));
    connect(ui_kxtodvdview_base.btnConfigure, SIGNAL(clicked()), this, SLOT(btnConfigureClicked()));

    connect(ui_kxtodvdview_base.btnCreateISO, SIGNAL(clicked()), this, SLOT(btnCreateISOClicked()));
    connect(ui_kxtodvdview_base.btnBurnDVD, SIGNAL(clicked()), this, SLOT(btnBurnDVDClicked()));

    connect(ui_kxtodvdview_base.listFiles, SIGNAL(itemSelectionChanged()), this, SLOT(toggleConfigButton()));
}

void KxToDvdView::toggleConfigButton()
{
    if (ui_kxtodvdview_base.listFiles->selectedItems().isEmpty()) {
        ui_kxtodvdview_base.btnConfigure->setEnabled(false);
    } else {
        ui_kxtodvdview_base.btnConfigure->setEnabled(true);
    }
}

void KxToDvdView::btnAddClicked()
{
    QStringList strList = KFileDialog::getOpenFileNames(KUrl(QDir::homePath()), "*.avi *.mkv *.ogg *.ogv *.mp4 *.m4v *.flv *.mpg *.mpeg", this, "Select Video File");

    if (strList.isEmpty()) { return; }

    foreach (QString str, strList) {
        if (!QFile(str).exists()) { return; }

        VideoFile f(str);

        QFileInfo fInfo(str);
        QListWidgetItem *item = new QListWidgetItem;
        item->setIcon(KIcon("video-x-generic"));
        item->setText(fInfo.fileName().left(fInfo.fileName().length() - 4) + "\n" + QString::number(fInfo.size() / 1024 / 1024) + " MB    " + QTime(0, 0, f.duration).toString("h:mm:ss") + "\n" + str);
        item->setSizeHint(QSize(360, 74));
        item->setData(32, "10");

        if (f.missingHeader) {
            QMessageBox::information(0, QFileInfo(str).fileName() , "Estimating duration from bitrate due to missing header/corruption. This may be inaccurate.");
        }

        m_currentProjectDuration = ui_kxtodvdview_base.progressBar->value() + f.duration;
        ui_kxtodvdview_base.progressBar->setValue(m_currentProjectDuration);

        // "is dvd full?" checking here. mebbe.
        
        ui_kxtodvdview_base.listFiles->addItem(item);
    }
    ui_kxtodvdview_base.btnCreateISO->setEnabled(true);
    ui_kxtodvdview_base.btnBurnDVD->setEnabled(true);
}

void KxToDvdView::btnDeleteClicked()
{
    if (ui_kxtodvdview_base.listFiles->count() == 1) {
        ui_kxtodvdview_base.btnCreateISO->setEnabled(false);
        ui_kxtodvdview_base.btnBurnDVD->setEnabled(false);
    }

    VideoFile f(ui_kxtodvdview_base.listFiles->currentItem()->text().split("\n").at(2));
    m_currentProjectDuration = ui_kxtodvdview_base.progressBar->value() - f.duration;
    ui_kxtodvdview_base.progressBar->setValue(m_currentProjectDuration);

    ui_kxtodvdview_base.listFiles->takeItem(ui_kxtodvdview_base.listFiles->currentRow());
}

void KxToDvdView::btnMoveUpClicked()
{
    if (ui_kxtodvdview_base.listFiles->selectedItems().isEmpty()) {
        return;
    }

    int index = ui_kxtodvdview_base.listFiles->currentIndex().row();

    QListWidgetItem *item = new QListWidgetItem(ui_kxtodvdview_base.listFiles->currentItem()->text());
    item->setIcon(KIcon("video-x-generic"));
    item->setData(32, ui_kxtodvdview_base.listFiles->currentItem()->data(32));
    item->setData(33, ui_kxtodvdview_base.listFiles->currentItem()->data(33));

    ui_kxtodvdview_base.listFiles->insertItem(index - 1, item);
    ui_kxtodvdview_base.listFiles->takeItem(index + 1);
    ui_kxtodvdview_base.listFiles->setCurrentItem(item);
}

void KxToDvdView::btnMoveDownClicked()
{
    if (ui_kxtodvdview_base.listFiles->selectedItems().isEmpty()) {
        return;
    }

    int index = ui_kxtodvdview_base.listFiles->currentRow();
    if ((index + 1) == ui_kxtodvdview_base.listFiles->count()) {
        return;
    }

    QListWidgetItem *item = new QListWidgetItem(ui_kxtodvdview_base.listFiles->currentItem()->text());
    item->setIcon(KIcon("video-x-generic"));
    item->setData(32, ui_kxtodvdview_base.listFiles->currentItem()->data(32));
    item->setData(33, ui_kxtodvdview_base.listFiles->currentItem()->data(33));

    ui_kxtodvdview_base.listFiles->insertItem(index + 2, item);
    ui_kxtodvdview_base.listFiles->takeItem(index);
    ui_kxtodvdview_base.listFiles->setCurrentItem(item);
}

void KxToDvdView::btnConfigureClicked()
{
    if (ui_kxtodvdview_base.listFiles->selectedItems().count() == 1) {
        m_configMenu = new QMenu;
        m_chapterDurationMenu = new QMenu("Chapter Duration");

        m_pauseAfter = new QAction("Pause after this video", m_configMenu);
        m_pauseAfter->setCheckable(true);
        m_pauseAfter->setChecked(false);
        m_chpOneMin = new QAction("1 minute", m_chapterDurationMenu);
        m_chpOneMin->setData("1");
        m_chpOneMin->setCheckable(true);
        m_chpFiveMin = new QAction("5 minute", m_chapterDurationMenu);
        m_chpFiveMin->setData("5");
        m_chpFiveMin->setCheckable(true);
        m_chpTenMin = new QAction("10 minutes", m_chapterDurationMenu);
        m_chpTenMin->setData("10");
        m_chpTenMin->setCheckable(true);
        m_chpFifteenMin = new QAction("15 minutes", m_chapterDurationMenu);
        m_chpFifteenMin->setData("15");
        m_chpFifteenMin->setCheckable(true);
        m_chpThirtyMin = new QAction("30 minute", m_chapterDurationMenu);
        m_chpThirtyMin->setData("30");
        m_chpThirtyMin->setCheckable(true);

        m_chaptersGroup = new QActionGroup(m_chapterDurationMenu);
        m_chaptersGroup->addAction(m_chpOneMin);
        m_chaptersGroup->addAction(m_chpFiveMin);
        m_chaptersGroup->addAction(m_chpTenMin);
        m_chaptersGroup->addAction(m_chpFifteenMin);
        m_chaptersGroup->addAction(m_chpThirtyMin);

        connect(m_pauseAfter, SIGNAL(triggered(bool)), this, SLOT(setPauseAfter(bool)));
        connect(m_chaptersGroup, SIGNAL(triggered(QAction*)), this, SLOT(setChapterString(QAction*)));

        QString s = ui_kxtodvdview_base.listFiles->currentItem()->data(32).toString();
        if (s == "1") {
            m_chpOneMin->setChecked(true);
        } else if (s == "5") {
            m_chpFiveMin->setChecked(true);
        } else if (s == "10") {
            m_chpTenMin->setChecked(true);
        } else if (s == "15") {
            m_chpFifteenMin->setChecked(true);
        } else if (s == "30") {
            m_chpThirtyMin->setChecked(true);
        }

        bool b = ui_kxtodvdview_base.listFiles->selectedItems().at(0)->data(33).toBool();
        if (b) { m_pauseAfter->setChecked(true); }

        m_chapterDurationMenu->addActions(m_chaptersGroup->actions());
        m_configMenu->addMenu(m_chapterDurationMenu);
        m_configMenu->addAction(m_pauseAfter);
        m_configMenu->popup(QCursor::pos());
    }
}

void KxToDvdView::setChapterString(QAction* action)
{
    ui_kxtodvdview_base.listFiles->selectedItems().at(0)->setData(32, action->data().toString());
}

void KxToDvdView::btnCreateISOClicked()
{
    if (Settings::tmpdir() == "unset") {
        m_tmpDir = QDir::homePath() + "/DVD_tmp";
    } else {
        m_tmpDir = Settings::tmpdir();
    }

    QDir d(m_tmpDir);
    if (!d.exists()) {
        d.mkdir(m_tmpDir);
        d.mkdir(m_tmpDir + "/dvd");
    }

    m_fileList.clear();

    int i = 0;
    while (i < ui_kxtodvdview_base.listFiles->count()) {
        m_fileList.append(ui_kxtodvdview_base.listFiles->item(i)->text().split("\n").at(2));
        i++;
    }

    QString vidMode = "ntsc";

    QString aspectRatio = "4:3";

    if (Settings::pal()) {
        vidMode = "pal";
    }

    if (Settings::widescreen()) {
        aspectRatio = "16:9";
    }

    ui_kxtodvdview_base.btnAdd->setEnabled(false);
    ui_kxtodvdview_base.btnDelete->setEnabled(false);
    ui_kxtodvdview_base.btnMoveUp->setEnabled(false);
    ui_kxtodvdview_base.btnMoveDown->setEnabled(false);
    ui_kxtodvdview_base.btnConfigure->setEnabled(false);
    ui_kxtodvdview_base.btnCreateISO->setEnabled(false);
    ui_kxtodvdview_base.btnBurnDVD->setEnabled(false);
    ui_kxtodvdview_base.listFiles->setEnabled(false);

    ui_kxtodvdview_base.lblStatus->setText("Encoding Video(s)...");

    m_encoder = new EncoderThread(m_fileList, m_tmpDir, vidMode, aspectRatio);
    connect(m_encoder, SIGNAL(progress(int)), this, SLOT(updateProgress(int)));
    connect(m_encoder, SIGNAL(progressMax(int)), this, SLOT(updateProgressMax(int)));
    connect(m_encoder, SIGNAL(progressFile(int)), this, SLOT(updateProgressFile(int)));
    connect(m_encoder, SIGNAL(finished()), this, SLOT(createDVDStructure()));
    m_encoder->run();
}

void KxToDvdView::btnBurnDVDClicked()
{
    m_burning = true;
    btnCreateISOClicked();
}

KxToDvdView::~KxToDvdView()
{

}

void KxToDvdView::updateProgress(int p)
{
    ui_kxtodvdview_base.progressBar->setValue(p);
    if (ui_kxtodvdview_base.progressBar->text() == "100%") {
        ui_kxtodvdview_base.progressBar->setMaximum(10800);
        ui_kxtodvdview_base.progressBar->setValue(m_currentProjectDuration);
    }
}

void KxToDvdView::updateProgressMax(int p)
{
    ui_kxtodvdview_base.progressBar->setMaximum(p);
}

void KxToDvdView::updateProgressFile(int p)
{
    if (ui_kxtodvdview_base.lblStatus->text().left(5) == "Encod") {
        ui_kxtodvdview_base.lblStatus->setText("Encoding Video(s)... " + QString::number(p + 1) + "/" + QString::number(m_fileList.count()));
    } else if (ui_kxtodvdview_base.lblStatus->text().left(14) == "Creating DVD S") {
        ui_kxtodvdview_base.lblStatus->setText("Creating DVD Structure... " + QString::number(p + 1) + "/" + QString::number(m_fileList.count()));
    }
}

void KxToDvdView::createDVDStructure()
{
    int i = 0;
    while (i < ui_kxtodvdview_base.listFiles->count()) {
        m_chapterStrings += ui_kxtodvdview_base.listFiles->item(i)->data(32).toString();
        i++;
    }

    QList<bool> pauseList;
    i = 0;
    while (i < ui_kxtodvdview_base.listFiles->count()) {
        pauseList.append(ui_kxtodvdview_base.listFiles->item(i)->data(33).toBool());
        i++;
    }

    ui_kxtodvdview_base.lblStatus->setText("Creating DVD Structure...");

    m_authorer = new AuthorThread(m_fileList, m_chapterStrings, pauseList, m_tmpDir);
    connect(m_authorer, SIGNAL(progressFile(int)), this, SLOT(updateProgressFile(int)));
    connect(m_authorer, SIGNAL(progressMax(int)), this, SLOT(updateProgressMax(int)));
    connect(m_authorer, SIGNAL(progress(int)), this, SLOT(updateProgress(int)));
    connect(m_authorer, SIGNAL(finished()), this, SLOT(createISOImage()));
    m_authorer->run();
}

void KxToDvdView::createISOImage()
{
    ui_kxtodvdview_base.lblStatus->setText("Creating ISO Image: " + m_tmpDir + "/dvd.iso");
    m_mkiso = new MkISOThread(m_tmpDir);
    connect(m_mkiso, SIGNAL(progressMax(int)), this, SLOT(updateProgressMax(int)));
    connect(m_mkiso, SIGNAL(progress(int)), this, SLOT(updateProgress(int)));
    connect(m_mkiso, SIGNAL(finished()), this, SLOT(imageCreated()));
    m_mkiso->run();
}

void KxToDvdView::discBurned()
{
    QMessageBox::information(0, "KxToDvd", "Burning Complete");

    ui_kxtodvdview_base.progressBar->setMaximum(10800);
    ui_kxtodvdview_base.progressBar->setValue(m_currentProjectDuration);
    ui_kxtodvdview_base.btnCreateISO->setEnabled(true);
    ui_kxtodvdview_base.btnBurnDVD->setEnabled(true);
    ui_kxtodvdview_base.btnAdd->setEnabled(true);
    ui_kxtodvdview_base.btnDelete->setEnabled(true);
    ui_kxtodvdview_base.btnMoveUp->setEnabled(true);
    ui_kxtodvdview_base.btnMoveDown->setEnabled(true);
    ui_kxtodvdview_base.listFiles->setEnabled(true);
    toggleConfigButton();

    m_burning = false;

    QProcess p;
    int i = 0;
    while (i < ui_kxtodvdview_base.listFiles->count()) {
        p.start("rm " + m_tmpDir + "/" + ui_kxtodvdview_base.listFiles->item(i)->text().split("\n").at(0) + ".mpg");
        p.waitForFinished();
        i++;
    }
}

void KxToDvdView::imageCreated()
{
    if (!m_burning) {
        QMessageBox::information(0, "KxToDvd", "ISO Image created at: " + m_tmpDir + "/dvd.iso");

        ui_kxtodvdview_base.progressBar->setMaximum(10800);
        ui_kxtodvdview_base.progressBar->setValue(m_currentProjectDuration);
        ui_kxtodvdview_base.lblStatus->setText("KxToDVD");
        ui_kxtodvdview_base.btnCreateISO->setEnabled(true);
        ui_kxtodvdview_base.btnBurnDVD->setEnabled(true);
        ui_kxtodvdview_base.btnAdd->setEnabled(true);
        ui_kxtodvdview_base.btnDelete->setEnabled(true);
        ui_kxtodvdview_base.btnMoveUp->setEnabled(true);
        ui_kxtodvdview_base.btnMoveDown->setEnabled(true);
        ui_kxtodvdview_base.btnConfigure->setEnabled(true);
        ui_kxtodvdview_base.listFiles->setEnabled(true);
        toggleConfigButton();

        QProcess p;
        int i = 0;
        while (i < ui_kxtodvdview_base.listFiles->count()) {
            p.start("rm " + m_tmpDir + "/" + ui_kxtodvdview_base.listFiles->item(i)->text().split("\n").at(0) + ".mpg");
            p.waitForFinished();
            i++;
        }
    } else {
        ui_kxtodvdview_base.lblStatus->setText("Burning disc...");

        m_burner = new BurnThread(m_tmpDir);
        connect(m_burner, SIGNAL(progressMax(int)), this, SLOT(updateProgressMax(int)));
        connect(m_burner, SIGNAL(progress(int)), this, SLOT(updateProgress(int)));
        connect(m_burner, SIGNAL(finished()), this, SLOT(discBurned()));
        m_burner->run();
    }
}

void KxToDvdView::settingsChanged()
{
    m_tmpDir = Settings::tmpdir();
    m_videoMode = "ntsc";
    m_aspectRatio = "4:3";

    if (Settings::pal()) {
        m_videoMode = "pal";
    }

    if (Settings::widescreen()) {
        m_aspectRatio = "16:9";
    }
}

void KxToDvdView::setPauseAfter(bool b)
{
    ui_kxtodvdview_base.listFiles->selectedItems().at(0)->setData(33, b);
}


#include "kxtodvdview.moc"
