/***************************************************************************
                          addcatdialog.cpp  -  description
                             -------------------
    begin                : Sun Mar 3 2002
    copyright            : (C) 2002 by Jason Harris
    email                : kstars@30doradus.org
 ***************************************************************************/

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

#include "addcatdialog.h"

#include <QFrame>
#include <QTextStream>
#include <QDebug>
#include <QDoubleSpinBox>
#include <QTemporaryFile>
#include <QUrl>

#include <KColorButton>
#include <KMessageBox>

#include "kstars.h"
#include "kstarsdata.h"
#include "Options.h"
#include "skycomponents/catalogcomponent.h"
#include "skycomponents/skymapcomposite.h"

AddCatDialogUI::AddCatDialogUI(QWidget *parent) : QFrame(parent)
{
    setupUi(this);
}

AddCatDialog::AddCatDialog(KStars *_ks) : QDialog((QWidget *)_ks)
{
#ifdef Q_OS_OSX
    setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
#endif
    QDir::setCurrent(QDir::homePath());
    acd = new AddCatDialogUI(this);

    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addWidget(acd);
    setLayout(mainLayout);

    setWindowTitle(i18n("Import Catalog"));

    QDialogButtonBox *buttonBox =
        new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
    mainLayout->addWidget(buttonBox);

    connect(acd->DataURL->lineEdit(), SIGNAL(lostFocus()), this, SLOT(slotShowDataFile()));
    connect(acd->DataURL, SIGNAL(urlSelected(const QUrl &)), this, SLOT(slotShowDataFile()));
    connect(acd->PreviewButton, SIGNAL(clicked()), this, SLOT(slotPreviewCatalog()));
    connect(buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(slotCreateCatalog()));
    connect(buttonBox, SIGNAL(rejected()), this, SLOT(close()));
    connect(buttonBox, SIGNAL(helpRequested()), this, SLOT(slotHelp()));

    acd->FieldList->addItem(i18n("ID Number"));
    acd->FieldList->addItem(i18n("Right Ascension"));
    acd->FieldList->addItem(i18n("Declination"));
    acd->FieldList->addItem(i18n("Object Type"));

    acd->FieldPool->addItem(i18n("Common Name"));
    acd->FieldPool->addItem(i18n("Magnitude"));
    acd->FieldPool->addItem(i18n("Flux"));
    acd->FieldPool->addItem(i18n("Major Axis"));
    acd->FieldPool->addItem(i18n("Minor Axis"));
    acd->FieldPool->addItem(i18n("Position Angle"));
    acd->FieldPool->addItem(i18n("Ignore"));
}

AddCatDialog::~AddCatDialog()
{
}

void AddCatDialog::slotHelp()
{
    QString message =
        i18n("A valid custom catalog file has one line per object, "
             "with the following fields in each line:") +
        "\n\t" +
        i18n("1. Type identifier.  Must be one of: 0 (star), 3 (open cluster), 4 (globular cluster), "
             "5 (gaseous nebula), 6 (planetary nebula), 7 (supernova remnant), or 8 (galaxy)") +
        "\n\t" + i18n("2. Right Ascension (floating-point value)") + "\n\t" +
        i18n("3. Declination (floating-point value)") + "\n\t" + i18n("4. Magnitude (floating-point value)") + "\n\t" +
        i18n("5. Integrated Flux (floating-point value); frequency and units are set separately in the catalog file.") +
        "\n\t" + i18n("6. Spectral type (if type=0); otherwise object's catalog name") + "\n\t" +
        i18n("7. Star name (if type=0); otherwise object's common name. [field 7 is optional]") + "\n\n" +

        i18n("The fields should be separated by whitespace.  In addition, the catalog "
             "may contain comment lines beginning with \'#\'.");

    KMessageBox::information(0, message, i18n("Help on custom catalog file format"));
}

/* Attempt to parse the catalog data file specified in the DataURL box.
 * We assume the data file has space-separated fields, and that each line has
 * the data fields listed in the Catalog fields list, in the same order.
 * Each data field is parsed as follows:
 *
 * ID number: integer value
 * Right Ascension: colon-delimited hh:mm:ss.s or floating-point value
 * Declination: colon-delimited dd:mm:ss.s or floating-point value
 * Object type: integer value, one of [ 0,1,2,3,4,5,6,7,8 ]
 * Common name: string value (if it contains a space, it *must* be enclosed in quotes!)
 * Magnitude: floating-point value
 * Major axis: floating-point value (length of major axis in arcmin)
 * Minor axis: floating-point value (length of minor axis in arcmin)
 * Position angle: floating-point value (position angle, in degrees)
 */
bool AddCatDialog::validateDataFile()
{
    //Create the catalog file contents: first the header
    CatalogContents = writeCatalogHeader();

    // Check if the URL is empty
    if (acd->DataURL->url().isEmpty())
        return false;

    //Next, the data lines (fill from user-specified file)
    QFile dataFile(acd->DataURL->url().toLocalFile());
    if (dataFile.open(QIODevice::ReadOnly))
    {
        QTextStream dataStream(&dataFile);
        CatalogContents += dataStream.readAll();

        dataFile.close();
        return true;
    }

    return false;
}

QString AddCatDialog::writeCatalogHeader()
{
    QString name   = (acd->CatalogName->text().isEmpty() ? i18n("Custom") : acd->CatalogName->text());
    QString pre    = (acd->Prefix->text().isEmpty() ? "CC" : acd->Prefix->text());
    char delimiter = (acd->CSVButton->isChecked() ? ',' : ' ');

    QString h = QString("# Delimiter: %1\n").arg(delimiter);
    h += QString("# Name: %1\n").arg(name);
    h += QString("# Prefix: %1\n").arg(pre);
    h += QString("# Color: %1\n").arg(acd->ColorButton->color().name());
    h += QString("# Epoch: %1\n").arg(acd->Epoch->value());
    h += QString("# ");

    for (int i = 0; i < acd->FieldList->count(); ++i)
    {
        QString f = acd->FieldList->item(i)->text();

        if (f == i18n("ID Number"))
        {
            h += "ID  ";
        }
        else if (f == i18n("Right Ascension"))
        {
            h += "RA  ";
        }
        else if (f == i18n("Declination"))
        {
            h += "Dc  ";
        }
        else if (f == i18n("Object Type"))
        {
            h += "Tp  ";
        }
        else if (f == i18n("Common Name"))
        {
            h += "Nm  ";
        }
        else if (f == i18n("Magnitude"))
        {
            h += "Mg  ";
        }
        else if (f == i18n("Flux"))
        {
            h += "Flux  ";
        }
        else if (f == i18n("Major Axis"))
        {
            h += "Mj  ";
        }
        else if (f == i18n("Minor Axis"))
        {
            h += "Mn  ";
        }
        else if (f == i18n("Position Angle"))
        {
            h += "PA  ";
        }
        else if (f == i18n("Ignore"))
        {
            h += "Ig  ";
        }
    }

    h += '\n';

    return h;
}

void AddCatDialog::slotShowDataFile()
{
    QFile dataFile(acd->DataURL->url().toLocalFile());
    if (!acd->DataURL->url().isEmpty() && dataFile.open(QIODevice::ReadOnly))
    {
        acd->DataFileBox->clear();
        QTextStream dataStream(&dataFile);
        acd->DataFileBox->addItems(dataStream.readAll().split('\n'));
        dataFile.close();
    }
}

void AddCatDialog::slotPreviewCatalog()
{
    if (validateDataFile())
    {
        KMessageBox::informationList(0, i18n("Preview of %1", acd->CatalogName->text()), CatalogContents.split('\n'),
                                     i18n("Catalog Preview"));
    }
}

void AddCatDialog::slotCreateCatalog()
{
    if (validateDataFile())
    {
        //CatalogContents now contains the text for the catalog file,
        //and objList contains the parsed objects

        //Warn user if file exists!
        if (QFile::exists(acd->CatalogURL->url().toLocalFile()))
        {
            QUrl u(acd->CatalogURL->url());
            int r = KMessageBox::warningContinueCancel(0,
                                                       i18n("A file named \"%1\" already exists. "
                                                            "Overwrite it?",
                                                            u.fileName()),
                                                       i18n("Overwrite File?"), KStandardGuiItem::overwrite());

            if (r == KMessageBox::Cancel)
                return;
        }

        QFile OutFile(acd->CatalogURL->url().toLocalFile());
        if (!OutFile.open(QIODevice::WriteOnly))
        {
            KMessageBox::sorry(0, i18n("Could not open the file %1 for writing.", acd->CatalogURL->url().toLocalFile()),
                               i18n("Error Opening Output File"));
        }
        else
        {
            QTextStream outStream(&OutFile);
            outStream << CatalogContents;
            OutFile.close();

            KStarsData::Instance()->skyComposite()->addCustomCatalog(OutFile.fileName(), 0);

            emit QDialog::accept();
            close();
        }
    }
}
