
#include "kast_part.h"

#include <kinstance.h>
#include <kaction.h>
#include <kstdaction.h>
#include <kfiledialog.h>
#include <kdebug.h>
#include <klocale.h>
#include <kactionclasses.h>
#include <kconfig.h>
#include <kapplication.h>

#include <qfile.h>

// Core
#include "core/mainwindow.h"
#include "core/direktorinstance.h"

// Commands
#include "commands/edeletecommand.h"

// Visitors
#include "visitors/svgexportvisitor.h"

KastPart::KastPart( QWidget *parentWidget, const char *widgetName,
                    QObject *parent, const char *name )
    : KParts::ReadWritePart(parent, name)
{
  // we need an instance
  setInstance( KastPartFactory::self() );

  // this should be your custom internal widget
  m_widget = new MainWindow( parentWidget, widgetName, actionCollection() );

  // notify the part that this is our internal widget
  setWidget(m_widget);

  // create our actions
  KStdAction::open(this, SLOT(fileOpen()), actionCollection());
  KStdAction::saveAs(this, SLOT(fileSaveAs()), actionCollection());
  KStdAction::save(this, SLOT(save()), actionCollection());
  connect( &Kast::self()->cmdHistory(), SIGNAL(commandExecuted()), SLOT(setModified()) );
  connect( &Kast::self()->cmdHistory(), SIGNAL(documentRestored()), SLOT(setUnmodified()) );
  KStdAction::cut(this, SLOT(editCut()), actionCollection());
  //KStdAction::delete(this, SLOT(editDelete()), actionCollection());
  KRecentFilesAction *recent = KStdAction::openRecent(this, SLOT(openURL(const KURL&)), actionCollection());
  //   connect( recent, SIGNAL(urlSelected(const KURL), SLOT(openURL(const KURL)) );
  recent->loadEntries( kapp->config() );  // TODO: move this to some fantastic KConfigXT singleton or whatever

  KToggleAction* view_stroke = new KToggleAction(i18n("&Stroke Dock"), 0, this,
                               SLOT(viewToggleStroke()), actionCollection(), "view_stroke");
  connect( m_widget, SIGNAL(strokeDockToggled(bool)), view_stroke, SLOT(setChecked(bool)) );
  // TODO: Remove the following hack by saving state in config
  view_stroke->setChecked(true);

  (void)new KToggleAction(i18n("&Record Animation"), 0, this, SLOT(animationToggleRecord()),
                          actionCollection(), "animation_togglerecord");

  // set our XML-UI resource file
  setXMLFile("kast_part.rc");

  // we are read-write by default
  setReadWrite(true);

  // we are not modified since we haven't done anything yet
  setModified(false);

  return;
}

KastPart::~KastPart()
{
  KRecentFilesAction *recent;
  recent = (KRecentFilesAction*)actionCollection()->action(KStdAction::stdName(KStdAction::OpenRecent));
  recent->saveEntries( kapp->config() );
}

void KastPart::addRecentFile(const KURL &url)
{
  KRecentFilesAction *recent;
  recent = (KRecentFilesAction*)actionCollection()->action(KStdAction::stdName(KStdAction::OpenRecent));
  recent->addURL(url);
}

void KastPart::setReadWrite(bool rw)
{
  // notify your internal widget of the read-write state
  //   m_widget->setReadOnly(!rw);
  //   if (rw)
  //     connect(m_widget, SIGNAL(textChanged()),
  //             this,     SLOT(setModified()));
  //   else
  //   {
  //     disconnect(m_widget, SIGNAL(textChanged()),
  //                this,     SLOT(setModified()));
  //   }

  ReadWritePart::setReadWrite(rw);
}

void KastPart::setModified(bool modified)
{
  kdDebug() << k_funcinfo << endl;
  // get a handle on our Save action and make sure it is valid
  KAction *save = actionCollection()->action(KStdAction::stdName(KStdAction::Save));
  if (!save)
    return;

  // if so, we either enable or disable it based on the current
  // state
  if (modified)
    save->setEnabled(true);
  else
    save->setEnabled(false);

  // in any event, we want our parent to do it's thing
  ReadWritePart::setModified(modified);
}

bool KastPart::openFile()
{
  kdDebug() << k_funcinfo << endl;
  // m_file is always local so we can use QFile on it
  QFile file(m_file);
  if (file.open(IO_ReadOnly) == false)
    return false;

  // our example widget is text-based, so we use QTextStream instead
  // of a raw QDataStream
  QTextStream stream(&file);
  QString str;
  while (!stream.eof())
    str += stream.readLine() + "\n";

  file.close();

  // now that we have the entire file, display it
  //     m_widget->setText(str);

  // just for fun, set the status bar
  emit setStatusBarText( m_url.prettyURL() );

  return true;
}

bool KastPart::saveFile()
{
  kdDebug() << k_funcinfo << endl;
  // if we aren't read-write, return immediately
  if (isReadWrite() == false)
    return false;
  /*
    // m_file is always local, so we use QFile
    QFile file(m_file);
    if (file.open(IO_WriteOnly) == false)
      return false;

    // use QTextStream to dump the text to the file
    QTextStream stream(&file);
    //     stream << m_widget->text();

    file.close();
  */

  QFile file(m_file);
  SVGExportVisitor *svgExport = new SVGExportVisitor(file);
  delete svgExport;
  return true;
}

void KastPart::fileOpen()
{
  kdDebug() << k_funcinfo << endl;
  // this slot is called whenever the File->Open menu is selected,
  // the Open shortcut is pressed (usually CTRL+O) or the Open toolbar
  // button is clicked
  QString file_name = KFileDialog::getOpenFileName();

  if (file_name.isEmpty() == false)
    openURL(file_name);
}

void KastPart::fileSaveAs()
{
  kdDebug() << k_funcinfo << endl;
  // this slot is called whenever the File->Save As menu is selected,
  QString file_name = KFileDialog::getSaveFileName();
  if (file_name.isEmpty() == false)
    saveAs(file_name);
}

bool KastPart::openURL (const KURL &url)
{
  addRecentFile(url);
  return Kast::self()->openURL(url);
}

void KastPart::editCut()
{
  kdDebug() << k_funcinfo << endl;
  editDelete();
}

void KastPart::editDelete()
{
  kdDebug() << k_funcinfo << endl;
  EDeleteCommand* cmdDel = new EDeleteCommand();
  Kast::self()->addCommand(cmdDel);
}

void KastPart::animationToggleRecord()
{
  kdDebug() << k_funcinfo << endl;
  Kast::self()->toggleRecordAnimation();
}

void KastPart::viewToggleStroke()
{
  kdDebug() << k_funcinfo << endl;
  m_widget->toggleStrokeDock();
}

void KastPart::setUnmodified()
{
  kdDebug() << k_funcinfo << endl;
  setModified(false);
}


// It's usually safe to leave the factory code alone.. with the
// notable exception of the KAboutData data
#include <kaboutdata.h>
#include <klocale.h>

KInstance*  KastPartFactory::s_instance = 0L;
KAboutData* KastPartFactory::s_about = 0L;

KastPartFactory::KastPartFactory()
    : KParts::Factory()
{}

KastPartFactory::~KastPartFactory()
{
  delete s_instance;
  delete s_about;

  s_instance = 0L;
}

KParts::Part* KastPartFactory::createPartObject( QWidget *parentWidget, const char *widgetName,
    QObject *parent, const char *name,
    const char *classname, const QStringList &args )
{
  // Create an instance of our Part
  KastPart* obj = new KastPart( parentWidget, widgetName, parent, name );

  // See if we are to be read-write or not
  if (QCString(classname) == "KParts::ReadOnlyPart")
    obj->setReadWrite(false);

  return obj;
}

KInstance* KastPartFactory::self()
{
  if( !s_instance )
  {
    s_about = new KAboutData("kastpart", I18N_NOOP("kastPart"), "0.1");
    s_about->addAuthor("Hans Oischinger", 0, "oisch@users.berlios.de");
    s_instance = new KInstance(s_about);
  }
  return s_instance;
}

extern "C"
{
  void* init_libkastpart()
  {
    return new KastPartFactory;
  }
};


#include "kast_part.moc"
