/***************************************************************************
                          keducabuilder.cpp  -  description
                             -------------------
    begin                : Sat May 26 2001
    copyright            : (C) 2001 by Javier Campos
    email                : javi@asyris.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 "keducabuilder.h"
#include "keducabuilder.moc"

#include "kcontroladdedit.h"
#include "kcontrolheader.h"
#include "keducaeditorstartdialog.h"
#include "../libkeduca/kgallerydialog.h"

#include <kiconloader.h>
#include <tdelocale.h>
#include <tdefiledialog.h>
#include <kedittoolbar.h>
#include <kdebug.h>
#include <tdeio/netaccess.h>
#include <tdemessagebox.h>
#include <kprinter.h>

#include <tqlayout.h>
#include <tqcheckbox.h>
#include <tqpaintdevicemetrics.h>
#include <tqpainter.h>

static const char* const keducabuilder_data[] = {
    "15 16 4 1",
    "a c #0000ff",
    "# c #008183",
    "b c #c5c2c5",
    ". c #ffffff",
    "...............",
    ".#############.",
    ".#...........#.",
    ".#...aaaa....#.",
    ".#..aa.baa...#.",
    ".#......aa...#.",
    ".#.....aab...#.",
    ".#....aab....#.",
    ".#....aab....#.",
    ".#.....b.....#.",
    ".#....aa.....#.",
    ".#....aa.....#.",
    ".#...........#.",
    ".#...........#.",
    ".#############.",
    "..............."};

KEducaBuilder::KEducaBuilder(TQWidget* parent, const char *name, WFlags f )
    : TDEMainWindow(parent,name,f),
      _nativeFormat("application/x-edu")
{
    _keducaFile = new FileRead();
    initMenuBar();
    init();
    configRead();
    setIcon( TDEGlobal::iconLoader()->loadIcon("control.png",
                                                   TDEIcon::Small) );
    _isOpenFile = false;
}

KEducaBuilder::~KEducaBuilder()
{
    delete _keducaFile;
}

/** Init graphical interface */
void KEducaBuilder::init()
{
    TQWidget *mainView = new TQWidget(this, "mainview");

    TQVBoxLayout *form2Layout = new TQVBoxLayout( mainView );
    form2Layout->setSpacing( 2 );
    form2Layout->setMargin( 0 );

    _split = new TQSplitter( mainView );
    _split->setOrientation( Qt::Vertical );

    _listAnswer = new TDEListBox( _split, "_listAnswer" );
    _listAnswer->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)7, (TQSizePolicy::SizeType)7, _listAnswer->sizePolicy().hasHeightForWidth() ) );
    connect( _listAnswer,  TQT_SIGNAL( highlighted(TQListBoxItem *) ), TQT_TQOBJECT(this), TQT_SLOT( slotPreview(TQListBoxItem *) ) );
    connect( _listAnswer,  TQT_SIGNAL( doubleClicked(TQListBoxItem *) ), TQT_TQOBJECT(this), TQT_SLOT( slotEditbyList(TQListBoxItem *) ) );

    _preview = new TQTextView( _split, "_preview" );
    _preview->setFrameShape( TQTextView::NoFrame );
    _preview->setLineWidth( 1 );

    form2Layout->addWidget( _split );

    setCentralWidget( mainView );
    if (!initialGeometrySet())
       resize( TQSize(500, 400).expandedTo(minimumSizeHint()));
    setupGUI( ToolBar | Keys | StatusBar | Create, "keducabuilderui.rc" );
    setAutoSaveSettings();
}

/** Init menu bar settings */
void KEducaBuilder::initMenuBar()
{
    KStdAction::openNew(TQT_TQOBJECT(this), TQT_SLOT( slotFileOpenNew() ), actionCollection());
    KStdAction::open   (TQT_TQOBJECT(this), TQT_SLOT( slotFileOpen() ), actionCollection());
    (void)new TDEAction(i18n("Open &Gallery..."), 0, 0, TQT_TQOBJECT(this), TQT_SLOT( slotGallery() ), actionCollection(), "open_gallery");
    _recentFiles = KStdAction::openRecent(TQT_TQOBJECT(this), TQT_SLOT ( slotFileOpenURL(const KURL &)), actionCollection());
    KStdAction::save   (TQT_TQOBJECT(this), TQT_SLOT( slotFileSave() ), actionCollection());
    KStdAction::saveAs (TQT_TQOBJECT(this), TQT_SLOT( slotFileSaveAs() ), actionCollection());
    KStdAction::print  (TQT_TQOBJECT(this), TQT_SLOT( slotFilePrint() ), actionCollection());
    (void)new TDEAction(i18n("Document Info"), "application-vnd.tde.info", 0, TQT_TQOBJECT(this), TQT_SLOT( slotHeader() ), actionCollection(), "info_doc");
    KStdAction::quit(TQT_TQOBJECT(this), TQT_SLOT( close() ), actionCollection());

    (void)new TDEAction(i18n("&Add..."), "addquestion", 0, TQT_TQOBJECT(this), TQT_SLOT( slotAdd() ), actionCollection(), "question_add");
    (void)new TDEAction(i18n("&Edit..."), "editquestion", 0, TQT_TQOBJECT(this), TQT_SLOT( slotEdit() ), actionCollection(), "question_edit");
    (void)new TDEAction(i18n("&Remove"), "delquestion", 0, TQT_TQOBJECT(this), TQT_SLOT( slotRemove() ), actionCollection(), "question_remove");
    (void)new TDEAction(i18n("&Up"), "go-up", 0, TQT_TQOBJECT(this), TQT_SLOT( slotUp() ), actionCollection(), "question_up");
    (void)new TDEAction(i18n("&Down"), "go-down", 0, TQT_TQOBJECT(this), TQT_SLOT( slotDown() ), actionCollection(), "question_down");
}

/** Delete current document and start new */
void KEducaBuilder::slotFileOpenNew()
{
    if (!currentFileMayBeReplaced())
        return;

    if( _keducaFile ) delete _keducaFile;
    _listAnswer->clear();
    _preview->setText("<qt><br><center><h1>"+i18n("Welcome To KEduca!")+"</h1>"+
                      i18n("Add a new Question by using the Edit Menu or by choosing one of the icons above.")+
                      "</center></qt>");
    _keducaFile = new FileRead();
    _isOpenFile = false;
    // ask for meta information
    slotHeader();
}

/** Open new document. */
void KEducaBuilder::slotFileOpen()
{
    KURL url = KFileDialog::getOpenURL( TQString(), _nativeFormat, this,  i18n("Open Educa File") );

    if( !url.isEmpty() )
        slotFileOpenURL( url );
}

/** Open new file */
void KEducaBuilder::slotFileOpenURL( const KURL &url )
{
    if (!currentFileMayBeReplaced())
        return;

    TQPixmap image0( ( const char** ) keducabuilder_data );
    delete _keducaFile;
    _keducaFile = new FileRead();
    if( !_keducaFile->openFile(url) ) { return; }
    _recentFiles->addURL( url );
    _listAnswer->clear();
    _isOpenFile = true;

    _keducaFile->recordFirst();
    while( !_keducaFile->recordEOF() )
    {
        _listAnswer->insertItem( image0, _keducaFile->getQuestion( FileRead::TQF_TEXT ) );
        _keducaFile->recordNext();
    }
}

/** Item select */
void KEducaBuilder::slotPreview( TQListBoxItem *item )
{
//    bool match = false;
    TQString tmpListanswer;

    // FIND THE SELECT RECORD
    if( !item ) return;

//    kdDebug() << "Item : " << _listAnswer->currentItem() <<endl;
    _keducaFile->recordAt( _listAnswer->currentItem() );

    // START THE PREVIEW VALUES
    tmpListanswer = "<p><b>" + i18n("Answers") + "</b></p><hr>";
    tmpListanswer += "<p>";

    tmpListanswer +="<TABLE WIDTH=98%>";
    _keducaFile->recordAnswerFirst();
    while( !_keducaFile->recordAnswerEOF() )
    {
        tmpListanswer += "<TR>";
        tmpListanswer += "<TD WIDTH=3% BGCOLOR=";
        _keducaFile->getAnswerValue() ? tmpListanswer += "#006b6b>" : tmpListanswer += "#b84747>";
        if( _keducaFile->getQuestionInt( FileRead::TQF_TYPE ) == 3 )
        {
            tmpListanswer += "<FONT COLOR=#ffffff><b>"
                          + _keducaFile->getAnswer( FileRead::AF_POINT )
                          + "</b></FONT>";
        }
        tmpListanswer += "</TD>";
        tmpListanswer += "<TD WIDTH=95% BGCOLOR=";
        _keducaFile->getAnswerValue() ? tmpListanswer += "#daeaea>" : tmpListanswer += "#eadada>";
        tmpListanswer += "<span style=\"color:black;\">"+_keducaFile->getAnswer( FileRead::AF_TEXT )+"</span>";
        tmpListanswer += "</TD></TR>";
        _keducaFile->recordAnswerNext();
    };
    tmpListanswer += "</TABLE>";

    if( !_keducaFile->getQuestion( FileRead::TQF_PICTURE ).isEmpty() )
    {
        tmpListanswer += "<table><tr><td><img src=";
        tmpListanswer += _keducaFile->getPicture();
        tmpListanswer += "></td>";
        tmpListanswer += "<td align=right><b>" + i18n("Question Image") + "</b><hr>";
        tmpListanswer += _keducaFile->getQuestion( FileRead::TQF_PICTURE ) + "</td></tr></table>";
    };

    if( _keducaFile->getQuestionInt( FileRead::TQF_POINTS ) > 0 )
    {
        tmpListanswer += "<p><b>" + i18n("Question point") + ":</b> ";
        tmpListanswer += _keducaFile->getQuestion( FileRead::TQF_POINTS );
    }

    if( _keducaFile->getQuestionInt( FileRead::TQF_TIME ) > 0 )
    {
        tmpListanswer += "<p><b>"+i18n("Time")+":</b> ";
        tmpListanswer += _keducaFile->getQuestion( FileRead::TQF_TIME );
        tmpListanswer += i18n(" seconds</p>");
    }

    if( !_keducaFile->getQuestion( FileRead::TQF_TIP ).isEmpty() )
    {
        tmpListanswer += "<p><b>" + i18n("Tip") +":</b> ";
        tmpListanswer += _keducaFile->getQuestion( FileRead::TQF_TIP );
        tmpListanswer += "</p>";
    }

    if( !_keducaFile->getQuestion( FileRead::TQF_EXPLAIN ).isEmpty() )
    {
        tmpListanswer += "<p><b>"
                      + i18n("Explain") + ":</b>"
                      + _keducaFile->getQuestion( FileRead::TQF_EXPLAIN )
                      + "</p>";
    }

    _preview->setText( tmpListanswer );
}

/** Read config data */
void KEducaBuilder::configRead()
{
    TDEConfig *config = TDEGlobal::config();

    config->setGroup( "keducacontrol" );
    applyMainWindowSettings( config, "keducacontrol" );
    _split->setSizes( config->readIntListEntry("Splitter_size") );
    _recentFiles->loadEntries(config);
}

/** Write settings */
void KEducaBuilder::configWrite()
{
    TDEConfig *config = TDEGlobal::config();

    config->setGroup( "keducacontrol" );
    saveMainWindowSettings( config, "keducacontrol" );
    config->writeEntry("Splitter_size", _split->sizes() );
    _recentFiles->saveEntries(config);
    config->sync();
}

bool KEducaBuilder::currentFileMayBeReplaced()
{
    if (_keducaFile->changed())
    {
        int res = KMessageBox::warningYesNoCancel( widget(),
            // ask the user to save
            i18n( "The document \"%1\" has been modified.\n"
                  "Do you want to save it?" ).arg( _keducaFile->getCurrentURL().fileName() ),
            i18n( "Save Document?" ), KStdGuiItem::save(), KStdGuiItem::discard() );
        switch (res)
        {
        case KMessageBox::Yes:
            // If the saving was successful, then the file may be replaced
            return fileSave();
            break;
        case KMessageBox::Cancel:
            // User cancels operation, do not replace the file
            return false;
            break;
        default: ;
        }
    }

    // file was not changed, it may be replaced
    return true;
}

/** Close the window */
bool KEducaBuilder::queryClose ()
{
    if (_keducaFile) {
        if (!currentFileMayBeReplaced())
            return false;
    }
    configWrite();
    return( TRUE );
}

/** Add question */
void KEducaBuilder::slotAdd()
{
    TQPixmap image0( ( const char** ) keducabuilder_data );

    KControlAddEdit edit(this);
    edit.init( _keducaFile, false );
    if( !edit.exec() ) return;

    _listAnswer->insertItem( image0, _keducaFile->getQuestion( FileRead::TQF_TEXT ) );
    _listAnswer->setCurrentItem( _listAnswer->count()-1 );
    slotPreview( _listAnswer->item(_listAnswer->currentItem()) );
}

/** Edit question */
void KEducaBuilder::slotEdit()
{
    if( _listAnswer->currentItem() == -1 ) return;

    TQPixmap image0( ( const char** ) keducabuilder_data );

    KControlAddEdit edit(this);
    edit.init( _keducaFile, true );
    if( edit.exec() )
    {
        _listAnswer->changeItem( image0, _keducaFile->getQuestion( FileRead::TQF_TEXT ), _listAnswer->currentItem() );
        slotPreview( _listAnswer->item(_listAnswer->currentItem()) );
    }
}

/** Edit question */
void KEducaBuilder::slotRemove()
{
    if( _listAnswer->currentItem() == -1 ) return;
    _keducaFile->recordDelete();
    _listAnswer->removeItem( _listAnswer->currentItem() );
}

/** Up record */
void KEducaBuilder::slotUp()
{
    int current = _listAnswer->currentItem();

    if( current < 1 ) return;
    TQPixmap image0( ( const char** ) keducabuilder_data );

    _keducaFile->recordSwap( true );
    TQString tmpString = _listAnswer->text( current-1 );
    _listAnswer->changeItem( image0, _listAnswer->text( current ), current-1 );
    _listAnswer->changeItem( image0, tmpString, current );
    _listAnswer->setCurrentItem( current-1 );
}

/** Down record */
void KEducaBuilder::slotDown()
{
    int current = _listAnswer->currentItem();

    if( current == -1 || current == (signed)(_listAnswer->count()-1) ) return;
    TQPixmap image0( ( const char** ) keducabuilder_data );

    _keducaFile->recordSwap( true );
    TQString tmpString = _listAnswer->text( current+1 );
    _listAnswer->changeItem( image0, _listAnswer->text( current ), current+1 );
    _listAnswer->changeItem( image0, tmpString, current );
    _listAnswer->setCurrentItem( current+1 );
}

/** Save file */
void KEducaBuilder::slotFileSave()
{
    fileSave();
}
bool KEducaBuilder::fileSave()
{
    if( !_isOpenFile )	{ return fileSaveAs();  }

    if( checkSave() ) return _keducaFile->saveFile();
    return false;
}

/** Save As... */
void KEducaBuilder::slotFileSaveAs()
{
    fileSaveAs();
}

bool KEducaBuilder::fileSaveAs()
{
    if( !checkSave() ) return false;

    TQCheckBox *saveCompressedCheckBox = new TQCheckBox( i18n( "Compress the file" ), 0 );
    saveCompressedCheckBox->setChecked( true );

    KFileDialog *dialog=new KFileDialog(TQString(), TQString(), this, "file dialog", true, saveCompressedCheckBox);
    dialog->setCaption( i18n("Save Document As") );
    dialog->setKeepLocation( true );
    dialog->setOperationMode( KFileDialog::Saving );
    TQStringList mimeFilter(_nativeFormat);
    dialog->setMimeFilter( mimeFilter, _nativeFormat );
    KURL newURL;
    TQString outputFormat (_nativeFormat);

    bool bOk;
    do {
        bOk=true;
        if(dialog->exec()==TQDialog::Accepted) {
            newURL=dialog->selectedURL();
            outputFormat=dialog->currentMimeFilter();
        }
        else
        {
            bOk = false;
            break;
        }
        kdDebug()<<"Requested saving to file "<<newURL.prettyURL() <<endl;
        if ( newURL.isEmpty() )
        {
            bOk = false;
            break;
        }

        if ( TQFileInfo( newURL.path() ).extension().isEmpty() ) {
            // No more extensions in filters. We need to get it from the mimetype.
            KMimeType::Ptr mime = KMimeType::mimeType( outputFormat );
            TQString extension = mime->property( "X-TDE-NativeExtension" ).toString();
            kdDebug() << "KEducaBuilder::slotFileSaveAs outputFormat=" << outputFormat << " extension=" << extension << endl;
            newURL.setPath( newURL.path() + extension );
        }

        if ( TDEIO::NetAccess::exists( newURL, false, this ) ) { // this file exists => ask for confirmation
            bOk = KMessageBox::warningContinueCancel( this,
                                              i18n("A document with this name already exists.\n"\
                                                   "Do you want to overwrite it?"),
                                              i18n("Warning"), i18n("Overwrite") ) == KMessageBox::Continue;
        }
    } while ( !bOk );

    bool saveCompressed = saveCompressedCheckBox->isChecked();

    delete dialog;

    if (bOk) {
        bool copyImages = KMessageBox::questionYesNo( this,
                            i18n("If you want to share this document, it is better to copy the images to the same folder as the document.\n"\
                            "Do you want to copy images?"),
                            i18n("Warning"), i18n("Copy Images"), i18n("Do Not Copy") ) == KMessageBox::Yes;
        if (_keducaFile->saveFile( newURL, copyImages, saveCompressed ) ) {
            _recentFiles->addURL(newURL);
            // we saved the file, so the internal representation is now present as a file
            _isOpenFile=true;
            return true;
        }else {
            kdDebug()<< "saving of file failed" <<endl;
            return false;
        }
    }else {
        kdDebug()<< "KEducaBuilder: no valid filename selected" <<endl;
        return false;
    }
}

/** Print file */
void KEducaBuilder::slotFilePrint()
{
    KPrinter *printer = new KPrinter();

    TQString file = _keducaFile->getCurrentURL().fileName();
    if (file.isEmpty())
	file = i18n("Test");
    if(printer->setup(this, i18n("Print %1").arg(file)))
    {
        TQPaintDeviceMetrics metrics(printer);
        TQPainter p;

        const int margin=20;
        int yPos=0;
        TQString text;

        p.begin(printer);
        p.setFont( TQFont(font().family(), 12, TQFont::Bold) );
        TQFontMetrics fm = p.fontMetrics();

        _keducaFile->recordFirst();
        while(!_keducaFile->recordEOF())
        {
            p.drawText( 10, yPos+margin,  metrics.width(), fm.lineSpacing(),
                        ExpandTabs | DontClip, _keducaFile->getQuestion(FileRead::TQF_TEXT) );
            yPos += fm.lineSpacing();

            p.drawLine(10, yPos+margin, metrics.width(), yPos+margin);
            yPos += 2*fm.lineSpacing();

            _keducaFile->recordNext();
        }

        p.end();
    }

    delete printer;

}

/** Header info */
int KEducaBuilder::slotHeader() {
    KControlHeader infoDoc(_keducaFile);
    return infoDoc.exec();
}

/** Check if the current document can save */
bool KEducaBuilder::checkSave()
{
    if( _keducaFile->getHeader("title").isEmpty() 		||
        _keducaFile->getHeader("category").isEmpty() ||
        _keducaFile->getHeader("type").isEmpty() 		||
        _keducaFile->getHeader("level").isEmpty()		||
        _keducaFile->getHeader("language").isEmpty() )
    {
        if (KMessageBox::warningContinueCancel(this, i18n("Unable to save file.\n\nYou must complete the Document Info\n(Only the description is necessary)"), TQString(), i18n("Complete Document Info..."))
            == KMessageBox::Continue) {
            if (slotHeader()!=KControlHeader::Accepted)
                return false;
        }else
            return false;
    }

    if( _listAnswer->count() < 1 )
    {
        if (KMessageBox::warningContinueCancel(this, i18n("Unable to save file.\n\nYou must insert a question."),
                                               TQString(), i18n("Insert Question"))==KMessageBox::Continue)
            slotAdd();
        else
            return false;
    }

    return true;
}

bool KEducaBuilder::startChooser() {
    KEducaEditorStartDialog startDialog(this, "KEducaEditorStartDialog", true);

    switch (startDialog.exec()) {
    case KEducaEditorStartDialog::OpenDoc:
    case KEducaEditorStartDialog::OpenRecentDoc:
        slotFileOpenURL(startDialog.getURL());
        break;
    case KEducaEditorStartDialog::NewDoc:
        slotFileOpenNew();
        break;
    case KEducaEditorStartDialog::Gallery:
        initGallery();
        break;
    default:
        close();
        break;
    }

    return true;
}
/** Init Internet Gallery Servers */
void KEducaBuilder::initGallery(const KURL &urlFile)
{
    KGalleryDialog galleries;

    if( !urlFile.url().isEmpty() )
      galleries.putURL( urlFile );

    if( galleries.exec() == TQDialog::Accepted )
      slotFileOpenURL( galleries.getURL() );
}

/** Init Gallery */
void KEducaBuilder::slotGallery()
{
  initGallery();
}

/** Double click in list, edit question */
void KEducaBuilder::slotEditbyList(TQListBoxItem *item)
{
  if( item )
    slotEdit();
}
