/***************************************************************************
                          dub.cpp  -  description
                             -------------------
    begin                : Tue Oct 23 01:44:51 EEST 2001
    copyright            : (C) 2001 by Eray Ozkural (exa)
    email                : erayo@cs.bilkent.edu.tr
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 files for QT
#include <qdir.h>
#include <qprinter.h>
#include <qpainter.h>

// include files for KDE
#include <kiconloader.h>
#include <kdebug.h>
#include <kfiledialog.h>
#include <kmenubar.h>
#include <kstatusbar.h>
#include <klocale.h>
#include <kconfig.h>
#include <kstdaction.h>
#include <noatun/playlist.h>

// application specific includes
#include "dub.h"
#include "dub.moc"
#include "dubview.h"
#include "dubdoc.h"
#include "dubplaylist.h"
#include "dubprefs.h"

#define ID_STATUS_MSG 1


// plugin interface
extern "C" Plugin *create_plugin()
{
  KGlobal::locale()->insertCatalogue("dub");
  DubPlaylist* dub = new DubPlaylist;
  return dub;
}

DubApp::DubApp(QWidget* parent, DubPlaylist* plist, const char* name)
  : KMainWindow(parent, name)
  , activeFile(0)
  , playlist(*plist)
{
  kdDebug() << "cons dubapp" << endl;
  config=kapp->config();

  ///////////////////////////////////////////////////////////////////
  // call inits to invoke all other construction parts
  initStatusBar();
  initActions();
  initDocument();
  initView();
	
  //readOptions();

  ///////////////////////////////////////////////////////////////////
  // disable actions at startup
  fileSave->setEnabled(false);
  fileSaveAs->setEnabled(false);
  filePrint->setEnabled(false);
  //editCut->setEnabled(false);
  //editCopy->setEnabled(false);
  //editPaste->setEnabled(false);
  connect( view->dirOperator(),
           SIGNAL(fileSelected(const KFileItem*)),
           this,
           SLOT(fileSelected(const KFileItem*)));

}

DubApp::~DubApp()
{
  kdDebug() << "destruct dubapp" << endl;
}

void DubApp::initActions()
{
  fileNewWindow = new KAction(i18n("New &Window"), QString::null, 0, this, SLOT(slotFileNewWindow()), actionCollection(),"file_new_window");
  fileNew = KStdAction::openNew(this, SLOT(slotFileNew()), actionCollection());
  fileOpen = KStdAction::open(this, SLOT(slotFileOpen()), actionCollection());
  fileOpenRecent = KStdAction::openRecent(this, SLOT(slotFileOpenRecent(const KURL&)), actionCollection());
  fileSave = KStdAction::save(this, SLOT(slotFileSave()), actionCollection());
  fileSaveAs = KStdAction::saveAs(this, SLOT(slotFileSaveAs()), actionCollection());
  fileClose = KStdAction::close(this, SLOT(slotFileClose()), actionCollection());
  filePrint = KStdAction::print(this, SLOT(slotFilePrint()), actionCollection());
  //fileQuit = KStdAction::quit(this, SLOT(slotFileQuit()), actionCollection());
  //editCut = KStdAction::cut(this, SLOT(slotEditCut()), actionCollection());
  //editCopy = KStdAction::copy(this, SLOT(slotEditCopy()), actionCollection());
  //editPaste = KStdAction::paste(this, SLOT(slotEditPaste()), actionCollection());
  viewToolBar = KStdAction::showToolbar(this, SLOT(slotViewToolBar()), actionCollection());
  viewStatusBar = KStdAction::showStatusbar(this, SLOT(slotViewStatusBar()), actionCollection());
  preferences = KStdAction::preferences(this, SLOT(slotPreferences()), actionCollection());

  fileNewWindow->setStatusText(i18n("Opens a new application window"));
  fileNew->setStatusText(i18n("Creates a new document"));
  fileOpen->setStatusText(i18n("Opens an existing document"));
  fileOpenRecent->setStatusText(i18n("Opens a recently used file"));
  fileSave->setStatusText(i18n("Saves the actual document"));
  fileSaveAs->setStatusText(i18n("Saves the actual document as..."));
  fileClose->setStatusText(i18n("Closes the actual document"));
  filePrint ->setStatusText(i18n("Prints out the actual document"));
  //fileQuit->setStatusText(i18n("Quits the application"));
  //editCut->setStatusText(i18n("Cuts the selected section and puts it to the clipboard"));
  //editCopy->setStatusText(i18n("Copies the selected section to the clipboard"));
  //editPaste->setStatusText(i18n("Pastes the clipboard contents to actual position"));
  viewToolBar->setStatusText(i18n("Enables/disables the toolbar"));
  viewStatusBar->setStatusText(i18n("Enables/disables the statusbar"));
  preferences ->setStatusText(i18n("Dub preferences"));

  // use the absolute path to your dubui.rc file for testing purpose in createGUI();
  createGUI();

}


void DubApp::initStatusBar()
{
  ///////////////////////////////////////////////////////////////////
  // STATUSBAR
  // TODO: add your own items you need for displaying current application status.
//  statusBar()->insertItem(i18n("Ready."), ID_STATUS_MSG);
}

void DubApp::initDocument()
{
  doc = new DubDoc(this);
  doc->newDocument();
}

void DubApp::initView()
{ 
  ////////////////////////////////////////////////////////////////////
  // create the main widget here that is managed by KTMainWindow's view-region and
  // connect the widget to your document to display document contents.

  view = new DubView(this);
  doc->addView(view);
  setCentralWidget(view);	
  setCaption(doc->URL().fileName(),false);

}

void DubApp::newDocument()
{
  slotStatusMsg(i18n("Opening new document..."));

  doc->openDocument( KURL() );
  slotStatusMsg(i18n("Ready."));
}

void DubApp::openDocumentFile(const KURL& url)
{
  slotStatusMsg(i18n("Opening file..."));

  doc->openDocument( url);
  fileOpenRecent->addURL( url );
  slotStatusMsg(i18n("Ready."));
}


DubDoc *DubApp::getDocument() const
{
  return doc;
}

void DubApp::saveOptions()
{	
  config->setGroup("General Options");
  config->writeEntry("Geometry", size());
  config->writeEntry("Show Toolbar", viewToolBar->isChecked());
  config->writeEntry("Show Statusbar",viewStatusBar->isChecked());
  config->writeEntry("ToolBarPos", (int) toolBar("mainToolBar")->barPos());
  config->writeEntry("Media Directory", mediaDirectory);
  fileOpenRecent->saveEntries(config,"Recent Files");
}


void DubApp::readOptions()
{
  config->setGroup("General Options");

  // bar status settings
  bool bViewToolbar = config->readBoolEntry("Show Toolbar", true);
  viewToolBar->setChecked(bViewToolbar);
  slotViewToolBar();

  bool bViewStatusbar = config->readBoolEntry("Show Statusbar", true);
  viewStatusBar->setChecked(bViewStatusbar);
  slotViewStatusBar();

  // bar position settings
  KToolBar::BarPosition toolBarPos;
  toolBarPos=(KToolBar::BarPosition) config->readNumEntry("ToolBarPos", KToolBar::Top);
  toolBar("mainToolBar")->setBarPos(toolBarPos);
	
  // initialize the recent file list
  fileOpenRecent->loadEntries(config,"Recent Files");

  QSize size=config->readSizeEntry("Geometry");
  if(!size.isEmpty())
  {
    resize(size);
  }

  mediaDirectory = config->readEntry("Media Directory", "~/");
}

void DubApp::saveProperties(KConfig *_cfg)
{
  if(doc->URL().fileName()!=i18n("Untitled") && !doc->isModified())
  {
    // saving to tempfile not necessary

  }
  else
  {
    KURL url=doc->URL();	
    _cfg->writeEntry("filename", url.url());
    _cfg->writeEntry("modified", doc->isModified());
    QString tempname = kapp->tempSaveName(url.url());
    QString tempurl= KURL::encode_string(tempname);
    KURL _url(tempurl);
    doc->saveDocument(_url);
  }
}


void DubApp::readProperties(KConfig* _cfg)
{
  QString filename = _cfg->readEntry("filename", "");
  KURL url(filename);
  bool modified = _cfg->readBoolEntry("modified", false);
  if(modified)
  {
    bool canRecover;
    QString tempname = kapp->checkRecoverFile(filename, canRecover);
    KURL _url(tempname);
  	
    if(canRecover)
    {
      doc->openDocument(_url);
      doc->setModified();
      setCaption(_url.fileName(),true);
      QFile::remove(tempname);
    }
  }
  else
  {
    if(!filename.isEmpty())
    {
      doc->openDocument(url);
      setCaption(url.fileName(),false);
    }
  }
}		

bool DubApp::queryClose()
{
  return doc->saveModified();
}

bool DubApp::queryExit()
{
  saveOptions();
  return true;
}

/////////////////////////////////////////////////////////////////////
// SLOT IMPLEMENTATION
/////////////////////////////////////////////////////////////////////

void DubApp::slotFileNewWindow()
{
  slotStatusMsg(i18n("Opening a new application window..."));
	
//  DubApp *new_window= new DubApp();
//  new_window->show();

  slotStatusMsg(i18n("Ready."));
}

void DubApp::slotFileNew()
{
  slotStatusMsg(i18n("Creating new document..."));

  if(!doc->saveModified())
  {
     // here saving wasn't successful

  }
  else
  {	
    doc->newDocument();		
    setCaption(doc->URL().fileName(), false);
  }

  slotStatusMsg(i18n("Ready."));
}

void DubApp::slotFileOpen()
{
  slotStatusMsg(i18n("Opening file..."));
	
  if(!doc->saveModified())
  {
     // here saving wasn't successful

  }
  else
  {	
    KURL url=KFileDialog::getOpenURL(QString::null,
        i18n("*|All files"), this, i18n("Open File"));
    if(!url.isEmpty())
    {
      doc->openDocument(url);
      setCaption(url.fileName(), false);
      fileOpenRecent->addURL( url );
    }
  }
  slotStatusMsg(i18n("Ready."));
}

void DubApp::slotFileOpenRecent(const KURL& url)
{
  slotStatusMsg(i18n("Opening file..."));
	
  if(!doc->saveModified())
  {
     // here saving wasn't successful
  }
  else
  {
    doc->openDocument(url);
    setCaption(url.fileName(), false);
  }

  slotStatusMsg(i18n("Ready."));
}

void DubApp::slotFileSave()
{
  slotStatusMsg(i18n("Saving file..."));
	
  doc->saveDocument(doc->URL());

  slotStatusMsg(i18n("Ready."));
}

void DubApp::slotFileSaveAs()
{
  slotStatusMsg(i18n("Saving file with a new filename..."));

  KURL url=KFileDialog::getSaveURL(QDir::currentDirPath(),
        i18n("*|All files"), this, i18n("Save As"));
  if(!url.isEmpty())
  {
    doc->saveDocument(url);
    fileOpenRecent->addURL(url);
    setCaption(url.fileName(),doc->isModified());
  }

  slotStatusMsg(i18n("Ready."));
}

void DubApp::slotFileClose()
{
//  slotStatusMsg(i18n("Closing plugin window..."));
//  slotStatusMsg(i18n("Closing file..."));
//	
//  close();
//
//  slotStatusMsg(i18n("Ready."));
}

void DubApp::slotFilePrint()
{
  slotStatusMsg(i18n("Printing..."));

  QPrinter printer;
  if (printer.setup(this))
  {
    view->print(&printer);
  }

  slotStatusMsg(i18n("Ready."));
}

void DubApp::slotFileQuit()
{
  slotStatusMsg(i18n("Exiting..."));
  saveOptions();
  // close the first window, the list makes the next one the first again.
  // This ensures that queryClose() is called on each window to ask for closing
  KMainWindow* w;
  if(memberList)
  {
    for(w=memberList->first(); w!=0; w=memberList->first())
    {
      // only close the window if the closeEvent is accepted. If the user presses Cancel on the saveModified() dialog,
      // the window and the application stay open.
      if(!w->close())
	break;
    }
  }	
}

void DubApp::slotEditCut()
{
  slotStatusMsg(i18n("Cutting selection..."));

  slotStatusMsg(i18n("Ready."));
}

void DubApp::slotEditCopy()
{
  slotStatusMsg(i18n("Copying selection to clipboard..."));

  slotStatusMsg(i18n("Ready."));
}

void DubApp::slotEditPaste()
{
  slotStatusMsg(i18n("Inserting clipboard contents..."));

  slotStatusMsg(i18n("Ready."));
}

void DubApp::slotViewToolBar()
{
  slotStatusMsg(i18n("Toggling toolbar..."));
  ///////////////////////////////////////////////////////////////////
  // turn Toolbar on or off
  if(!viewToolBar->isChecked())
  {
    toolBar("mainToolBar")->hide();
  }
  else
  {
    toolBar("mainToolBar")->show();
  }		

  slotStatusMsg(i18n("Ready."));
}

void DubApp::slotViewStatusBar()
{
  slotStatusMsg(i18n("Toggle the statusbar..."));
  ///////////////////////////////////////////////////////////////////
  //turn Statusbar on or off
  if(!viewStatusBar->isChecked())
  {
//    statusBar()->hide();
  }
  else
  {
//    statusBar()->show();
  }

  slotStatusMsg(i18n("Ready."));
}


void DubApp::slotStatusMsg(const QString &text)
{
  ///////////////////////////////////////////////////////////////////
  // change status message permanently
  statusBar()->clear();
  statusBar()->changeItem(text, ID_STATUS_MSG);
}

/** File selected */
void DubApp::fileSelected(const KFileItem * file) {
  kdDebug() << "file selected" << endl;
  activeFile = const_cast<KFileItem *>(file);
  playlist.setCurrent(file, true);
}

/** changes the active file to the next item in the view
 */
void DubApp::selectNextFile() {
  if (activeFile) {
    // fetch the list of items
    QPtrList<KFileItem> & items = view->items();
    // locate current item
    if (items.findRef(activeFile) != -1) {
      KFileItem* next = items.next();
      if (next && next->isFile())
        activeFile = next;
        view->selectFile(activeFile);
    }
  }
}

/** First file in the directory */
const KFileItem* DubApp::queryFirstFile() {
  // find first file
  KFileItem* firstFile = 0;
  QPtrList<KFileItem> & items = view->items();
  for (KFileItem* item = items.first(); item; item = items.next() ) {
    if (item->isFile()) {
      firstFile = item;
      break;
    }
  }
  return firstFile;
}
/** No descriptions */
KFileItem* DubApp::queryRoot() {
  return view->dirOperator()->dirLister()->rootItem();
}
/** Select previous file */
void DubApp::selectPreviousFile() {
  if (activeFile) {
    // fetch the list of items
    QPtrList<KFileItem> & items = view->items();
    // locate current item
    if (items.findRef(activeFile) != -1) {
      KFileItem* prev = items.prev();
      if (prev && prev->isFile())
        activeFile = prev;
        view->selectFile(activeFile);
    }
  }
}
/** Dub preferences */
void DubApp::slotPreferences() {
  kdDebug() << "Preferences dqialog here" << endl;
  DubPrefs prefs(view, "Preferences", true);
  prefs.exec();
}
