/***************************************************************************
   This file is part of LinTV Scheduler
   lintvprogrameditor.cpp
   A dialog for LinTV Scheduler which is used to add or edit a program.

   Author: Jesse L. Zamora <xtremek2009@gmail.com>

   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.
 ***************************************************************************/

#include "lintvprogrameditor.h"
#include "lintvtools.h"

#include <kdebug.h>
#include <kmessagebox.h>

#include <QTime>

LinTVProgramEditor::LinTVProgramEditor(LinTVDevices devices, QWidget *parent)
    : KDialog(parent),
      m_devices(devices)
{
    setCaption(i18n("Add Program"));

    m_mode = LinTVProgramEditor::AddProgram;

    loadUi();
    connectSignalsSlots();

    ui.programNameLineEdit->setText("LinTV_Record");
    ui.oneTimeRadioButton->setChecked(true);

    // Create a new time here...
    QTime time = QTime::currentTime();
    int minute;
    int major = ((time.minute() / 10) * 10);
    minute = time.minute() - major;
    if (minute < 5) {
        time.setHMS(time.hour(), major + 5, 0);
    } else if (minute >= 5) {
        time.setHMS(time.hour(), major + 10, 0);
    }
    ui.startTimeEdit->setTime(time);
    ui.endTimeEdit->setTime(time.addSecs(60 * 30));

    ui.startDateEdit->setDate(QDate::currentDate());
    ui.endDateEdit->setDate(QDate::currentDate().addDays(7));
    setNextRunLabel(ui.startDateEdit->date());
    ui.channelSpinBox->setValue(3);

    loadCommon();
}

LinTVProgramEditor::LinTVProgramEditor(LinTVProgram program, LinTVDevices devices, 
							      QWidget *parent)
    : KDialog(parent),
      m_program(program),
      m_devices(devices)
{
    setCaption(i18n("Edit Program"));

    m_mode = LinTVProgramEditor::EditProgram;

    loadUi();
    connectSignalsSlots();

    ui.programNameLineEdit->setText(m_program.name);
    if (m_program.type == LinTVProgram::OneTimeOnly) {
        ui.oneTimeRadioButton->setChecked(true);
    } else if (m_program.type == LinTVProgram::EveryDay) {
        ui.dailyRadioButton->setChecked(true);
        QStringList days = program.daysToRun;
        if (days.contains(PROGRAM_DAY_SUNDAY)) {
            ui.sundayCheckBox->setChecked(true);
        } else {
            ui.sundayCheckBox->setChecked(false);
        }
        if (days.contains(PROGRAM_DAY_MONDAY)) {
            ui.mondayCheckBox->setChecked(true);
        } else {
            ui.mondayCheckBox->setChecked(false);
        }
        if (days.contains(PROGRAM_DAY_TUESDAY)) {
            ui.tuesdayCheckBox->setChecked(true);
        } else {
            ui.tuesdayCheckBox->setChecked(false);
        }
        if (days.contains(PROGRAM_DAY_WEDNESDAY)) {
            ui.wednesdayCheckBox->setChecked(true);
        } else {
            ui.wednesdayCheckBox->setChecked(false);
        }
        if (days.contains(PROGRAM_DAY_THURSDAY)) {
            ui.thursdayCheckBox->setChecked(true);
        } else {
            ui.thursdayCheckBox->setChecked(false);
        }
        if (days.contains(PROGRAM_DAY_FRIDAY)) {
            ui.fridayCheckBox->setChecked(true);
        } else {
            ui.fridayCheckBox->setChecked(false);
        }
        if (days.contains(PROGRAM_DAY_SATURDAY)) {
            ui.saturdayCheckBox->setChecked(true);
        } else {
            ui.saturdayCheckBox->setChecked(false);
        }
    } else if (m_program.type == LinTVProgram::EveryWeek) {
        ui.weeklyRadioButton->setChecked(true);
    }

    ui.startTimeEdit->setTime(m_program.startDateTime.time());
    ui.endTimeEdit->setTime(m_program.endDateTime.time());
    ui.startDateEdit->setDate(m_program.startDateTime.date());
    ui.endDateEdit->setDate(m_program.endDateTime.date());

    ui.channelSpinBox->setValue(m_program.channel);
    loadCommon();

    for (int i = 0; i < m_devices.size(); i++) {
        if (program.device == m_devices[i].deviceName) {
            ui.deviceComboBox->setCurrentIndex(i);
            break;
        }
    }
    ui.inputComboBox->setCurrentIndex(program.input);
}

void LinTVProgramEditor::loadUi()
{
    programWidget = new QWidget(this);

    ui.setupUi(programWidget);

    setMainWidget(programWidget);
}

void LinTVProgramEditor::connectSignalsSlots()
{
    connect(ui.oneTimeRadioButton, SIGNAL(toggled(bool )),
            this, SLOT(checkDaysToRun(bool )));
    connect(ui.dailyRadioButton, SIGNAL(toggled(bool )),
	    this, SLOT(checkDaysToRun(bool )));
    connect(ui.weeklyRadioButton, SIGNAL(toggled(bool )),
	    this, SLOT(checkDaysToRun(bool )));

    connect(ui.startTimeEdit, SIGNAL(timeChanged(const QTime &)),
	    this, SLOT(startTimeChanged(const QTime &)));
    connect(ui.endTimeEdit, SIGNAL(timeChanged(const QTime &)),
	    this, SLOT(endTimeChanged(const QTime &)));

    connect(ui.startDateEdit, SIGNAL(dateChanged(const QDate &)),
            this, SLOT(startDateChanged(const QDate &)));

    connect(ui.deviceComboBox, SIGNAL(currentIndexChanged(int )),
	    this, SLOT(deviceChanged(int )));
    connect(ui.inputComboBox, SIGNAL(currentIndexChanged(const QString & )),
	    this, SLOT(inputChanged(const QString & )));

    connect(ui.selectAllPushButton, SIGNAL(clicked()),
            this, SLOT(selectAllDays()));
    connect(ui.selectNonePushButton, SIGNAL(clicked()),
            this, SLOT(deselectAllDays()));
}

void LinTVProgramEditor::loadCommon()
{
    for (int i = 0; i < m_devices.size(); i++) {
        ui.deviceComboBox->addItem(m_devices[i].deviceName);
    }
    ui.startDateEdit->setCalendarPopup(true);
    ui.endDateEdit->setCalendarPopup(true);
}

bool LinTVProgramEditor::checkProgram()
{
    QString errors;
    QTime startTime = ui.startTimeEdit->time();
    QTime endTime = ui.endTimeEdit->time();
    QDate startDate = ui.startDateEdit->date();
    QDate endDate = ui.endDateEdit->date();
    QTime currentTime = QTime::currentTime();
    QDate currentDate = QDate::currentDate();


    // Check the time...
    if (startTime <= QTime::currentTime() && startDate <= QDate::currentDate()) {
        if (startTime != m_program.startDateTime.time()) {
            errors.append(i18n("&nbsp; - You set the start time to <b>%1</b>, "
                               "but the current time is <b>%2</b>.<br>",
                                          startTime.toString("h':'mm A"), 
                                          currentTime.toString("h':'mm A"))); 
        }
    }

    if (endTime <= startTime) {
        errors.append(i18n("&nbsp; - Cannot record for <b>%1</b>.<br>",      
                            LinTVTools::duration(startTime, endTime)));
    }

    if (startDate < currentDate) {
        if (startDate != m_program.startDateTime.date()) {
            errors.append(i18n("&nbsp; - Today is <b>%1</b>, but you set the"
                             " date to start recording to <b>%2</b>.<br>",
                            currentDate.toString(LinTVProgramHandler::dateFormat()),
                            startDate.toString(LinTVProgramHandler::dateFormat())));
        }
    }

    if (endDate < startDate && !ui.oneTimeRadioButton->isChecked()) {
        errors.append(i18n("&nbsp; - You set the end time (<b>%1</b>)"
                           " before the start time (<b>%2</b>).<br>",
                           startTime.toString("h':'mm A"), endTime.toString("h':'mm A")));
    }

    if (errors.size() > 1) {
        KMessageBox::error(this, i18n("Errors saving program:<br>") + errors, 
                                                        i18n("Scheduling Errors"));
        return false;
    } else {
        return true;
    }
}

LinTVProgram LinTVProgramEditor::program()
{
    // return a LinTVProgram for the stuff on the dialog
    LinTVProgram program;

    program.name = ui.programNameLineEdit->text();
    if (ui.oneTimeRadioButton->isChecked()) {
        program.type = LinTVProgram::OneTimeOnly;
    } else if (ui.dailyRadioButton->isChecked()) {
        program.type = LinTVProgram::EveryDay;
        // Make a QStringList of the enabled days!
        QStringList days;

        if (ui.sundayCheckBox->isChecked()) {
            days << PROGRAM_DAY_SUNDAY;
        }
        if (ui.mondayCheckBox->isChecked()) {
            days << PROGRAM_DAY_MONDAY;
        }
        if (ui.tuesdayCheckBox->isChecked()) {
            days << PROGRAM_DAY_TUESDAY;
        }
        if (ui.wednesdayCheckBox->isChecked()) {
            days << PROGRAM_DAY_WEDNESDAY;
        }
        if (ui.thursdayCheckBox->isChecked()) {
            days << PROGRAM_DAY_THURSDAY;
        }
        if (ui.fridayCheckBox->isChecked()) {
            days << PROGRAM_DAY_FRIDAY;
        }
        if (ui.saturdayCheckBox->isChecked()) {
            days << PROGRAM_DAY_SATURDAY;
        }
        program.daysToRun = days;

    } else if (ui.weeklyRadioButton->isChecked()) {
        program.type = LinTVProgram::EveryWeek;

        program.daysToRun << LinTVProgramHandler::dayToString(ui.startDateEdit->date().dayOfWeek());
    }

    program.startDateTime = QDateTime(ui.startDateEdit->date(), 
				      ui.startTimeEdit->time());
    program.endDateTime = QDateTime(ui.endDateEdit->date(),
				    ui.endTimeEdit->time());

    program.device = ui.deviceComboBox->currentText();
    program.input = ui.inputComboBox->currentIndex();
    program.channel = ui.channelSpinBox->value();
   
    if (m_mode == LinTVProgramEditor::EditProgram) {
        program.recNumber = m_program.recNumber;
    } else {
        program.recNumber = 1;
    }

    program.status = LinTVProgram::Queued;

    return program;
}

void LinTVProgramEditor::setProgramName(const QString & name)
{
    ui.programNameLineEdit->setText(name);
}

void LinTVProgramEditor::checkDaysToRun(bool )
{
    if (ui.oneTimeRadioButton->isChecked()) {
        ui.daysToRunGroupBox->setEnabled(false);
        ui.endDateEdit->setEnabled(false);
    } else if (ui.dailyRadioButton->isChecked()) {
        ui.daysToRunGroupBox->setEnabled(true);
        ui.endDateEdit->setEnabled(true);
    } else if (ui.weeklyRadioButton->isChecked()) {
        ui.daysToRunGroupBox->setEnabled(false);
        ui.endDateEdit->setEnabled(true);
    }
}

void LinTVProgramEditor::deviceChanged(int index)
{
    ui.inputComboBox->clear();
    ui.inputComboBox->addItems(m_devices[index].deviceInputs);
}

void LinTVProgramEditor::inputChanged(const QString & text)
{
    if (text.contains("Television") || text.contains("Tuner")) {
        ui.channelSpinBox->setEnabled(true);
    } else {
        ui.channelSpinBox->setEnabled(false);
    }
}

void LinTVProgramEditor::startTimeChanged(const QTime &)
{
    /*QTime endTime = ui.endTimeEdit->time();
    if (time.hour() > endTime.hour()) {
        QTime tmpTime = time;
        tmpTime.setHMS(endTime.hour(), time.minute(), 0);
        ui.startTimeEdit->setTime(tmpTime);
    }

    if (time.minute() >= endTime.minute() && time.hour() >= endTime.hour()) {
        QTime tmpTime = time;
        tmpTime.setHMS(time.hour(), endTime.minute() - 1, 0);
        ui.startTimeEdit->setTime(tmpTime);
    }

    QTime minimumTime = ui.startTimeEdit->time();
    minimumTime.setHMS(minimumTime.hour(), minimumTime.minute() + 1, 0);
    ui.endTimeEdit->setMinimumTime(minimumTime);*/

    setRunTimeLabel(ui.startTimeEdit->time().secsTo(ui.endTimeEdit->time()));
}

void LinTVProgramEditor::endTimeChanged(const QTime &)
{
    /*QTime startTime = ui.startTimeEdit->time();
    if (time.hour() < startTime.hour()) {
        QTime tmpTime = time;
        tmpTime.setHMS(startTime.hour(), time.minute(), 0);
        ui.endTimeEdit->setTime(tmpTime);
    }

    if (time.minute() <= startTime.minute() && time.hour() <= startTime.hour()) {
        QTime tmpTime = time;
        tmpTime.setHMS(time.hour(), startTime.minute() + 1, 0);
        ui.endTimeEdit->setTime(tmpTime);
    }

    QTime endTime = ui.endTimeEdit->time();
    endTime.setHMS(endTime.hour(), endTime.minute() - 1, 0);

    if (ui.startDateEdit->date() == QDate::currentDate()) {
        QTime currentTime = QTime::currentTime();
        currentTime.setHMS(currentTime.hour(), currentTime.minute() + 1, 0);
        ui.startTimeEdit->setTimeRange(currentTime, endTime);
    } else {
        ui.startTimeEdit->clearMinimumTime();
        ui.startTimeEdit->setMaximumTime(endTime);
    }*/

    setRunTimeLabel(ui.startTimeEdit->time().secsTo(ui.endTimeEdit->time()));
}

void LinTVProgramEditor::startDateChanged(const QDate &date)
{
    setNextRunLabel(date);
}

void LinTVProgramEditor::setNextRunLabel(const QDate & date)
{
    QString nextDateStr = date.toString(LinTVProgramHandler::dateFormat());
    ui.nextRunDateLabel->setText(i18n("<b>Next Run Date: %1</b>", nextDateStr));
}

void LinTVProgramEditor::setRunTimeLabel(int )
{
    ui.runTimeLabel->setText(i18n("<b>Run Time: %1</b>", 
                                  LinTVTools::duration(ui.startTimeEdit->time(),
                                                       ui.endTimeEdit->time())));
}

void LinTVProgramEditor::selectAllDays()
{
    ui.sundayCheckBox->setChecked(true);
    ui.mondayCheckBox->setChecked(true);
    ui.tuesdayCheckBox->setChecked(true);
    ui.wednesdayCheckBox->setChecked(true);
    ui.thursdayCheckBox->setChecked(true);
    ui.fridayCheckBox->setChecked(true);
    ui.saturdayCheckBox->setChecked(true);
}

void LinTVProgramEditor::deselectAllDays()
{
    ui.sundayCheckBox->setChecked(false);
    ui.mondayCheckBox->setChecked(false);
    ui.tuesdayCheckBox->setChecked(false);
    ui.wednesdayCheckBox->setChecked(false);
    ui.thursdayCheckBox->setChecked(false);
    ui.fridayCheckBox->setChecked(false);
    ui.saturdayCheckBox->setChecked(false);
}

void LinTVProgramEditor::slotButtonClicked(int button)
{
    if (button == KDialog::Ok) {
        if (checkProgram()) {
            accept();
        }
    } else if (button == KDialog::Cancel) {
        reject();
    }
}

#include "lintvprogrameditor.moc"
