/***************************************************************************
                          kfocusdoc.cpp  -  description
                             -------------------
    begin                : Sun Aug 12 08:36:08 PDT 2001
    copyright            : (C) 2001 by Jeffrey Yu
    email                : jeffyu@cs.stanford.edu
 ***************************************************************************/

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

// include files for Qt
#include <qdir.h>
#include <qwidget.h>
#include <qfile.h>
#include <qdom.h>

// include files for KDE
#include <klocale.h>
#include <kmessagebox.h>
#include <kio/job.h>
#include <kio/netaccess.h>
#include <ktempfile.h>

// application specific includes
#include "kfocusdoc.h"
#include "kfocus.h"
#include "kfocusview.h"
#include "kfmproject.h"
#include "kfmprojectlist.h"

QList<KFocusView> *KFocusDoc::pViewList = 0L;

KFocusDoc::KFocusDoc(QWidget *parent, const char *name)
	: QObject(parent, name), projectList_(NULL)
{
  if(!pViewList)
  {
    pViewList = new QList<KFocusView>();
  }

  pViewList->setAutoDelete(true);

	projectList(new KFMProjectList());
	
}


KFocusDoc::~KFocusDoc()
{
	projectList(NULL);
}


void KFocusDoc::projectList(KFMProjectList* projectList){
	if (projectList != projectList_) {
		if (projectList_ != NULL) {
			disconnect(projectList_, 0, this, 0);
			
			delete projectList_;
		}
		
		projectList_ = projectList;
		
		if (projectList_ != NULL) {
			connect(projectList_, SIGNAL( contentsChanged() ), this, SLOT( onComponentChanged() ));
			
			projectList_->currentProject(new KFMProject());
		}
	}
}


void KFocusDoc::addView(KFocusView *view)
{
  pViewList->append(view);
}


void KFocusDoc::removeView(KFocusView *view)
{
  pViewList->remove(view);
}

void KFocusDoc::setModified(bool _m)
{
	if (modified != _m) {
		modified=_m;
		
		modifiedSet(_m);
	}
}

void KFocusDoc::setURL(const KURL &url)
{
  doc_url=url;
}


const KURL& KFocusDoc::URL() const
{
  return doc_url;
}


void KFocusDoc::slotUpdateAllViews(KFocusView *sender)
{
  KFocusView *w;
  if(pViewList)
  {
    for(w=pViewList->first(); w!=0; w=pViewList->next())
    {
      if(w!=sender)
        w->repaint();
    }
  }

}


bool KFocusDoc::saveModified()
{
  bool completed=true;

  if(modified)
  {
    KFocusApp *win=(KFocusApp *) parent();
    int want_save = KMessageBox::warningYesNoCancel(win,
                                         i18n("The current file was modified.\n"
                                              "Do you want to save it?"),
                                         i18n("Warning"));
    switch(want_save)
    {
      case KMessageBox::Yes:
           if (isUntitled())
           {
             win->slotFileSaveAs();
             if (modified) {
								completed = false;
								break;
             }
           }
           else
           {
             saveDocument(URL());
       	   };

       	   deleteContents();
           completed=true;
           break;

      case KMessageBox::No:
           setModified(false);
           deleteContents();
           completed=true;
           break;	

      case KMessageBox::Cancel:
           completed=false;
           break;

      default:
           completed=false;
           break;
    }
  }

  return completed;
}


void KFocusDoc::closeDocument()
{
  deleteContents();
}


bool KFocusDoc::newDocument()
{
  /////////////////////////////////////////////////
  // TODO: Add your document initialization code here
  /////////////////////////////////////////////////
  closeDocument();

	setModified(false);
  doc_url.setFileName(i18n("Untitled"));
	fileLoaded();
  return true;
}


bool KFocusDoc::openDocument(const KURL& url, const char * /* format =0*/)
{
	deleteContents();
	
	// Check for bogus filename
	if (url.isEmpty()) {
		return newDocument();
	}

  QString tmpfile;
  KIO::NetAccess::download( url, tmpfile );
  /////////////////////////////////////////////////
  // TODO: Add your document opening code here
  /////////////////////////////////////////////////
	if (!loadFile(tmpfile)) {
	  KIO::NetAccess::removeTempFile( tmpfile );
		KMessageBox::sorry( (KFocusApp*) parent(), i18n( "The input file you selected\nwas invalid." ));
		return newDocument();
	}
	
  KIO::NetAccess::removeTempFile( tmpfile );
	setURL(url);
  fileLoaded();
	setModified(false);

  return true;
}


bool KFocusDoc::saveDocument(const KURL& url, const char * /*format=0*/)
{
  /////////////////////////////////////////////////
  // TODO: Add your document saving code here
  /////////////////////////////////////////////////
  QDomDocument doc("kfocus");
	
	  QDomElement dElement = doc.createElement("kfocus");
  	dElement.setAttribute("version", "1.0");
	 	
	 	dElement.appendChild(projectList_->domElement(&doc));
	 	
	  doc.appendChild(dElement);

	// Write the document to a temporary file	
  KTempFile tmpFile;
	(*tmpFile.textStream()) << doc.toString() << "\n";
	tmpFile.close();
	
	// Upload the temporary file to the final destination
	KIO::NetAccess::upload( tmpFile.name(), url );
	
	// Delete the temporary file
	tmpFile.unlink();
	
	// Set the document's URL in case it changed (File->SaveAs)
	setURL(url);
	setModified(false);
  return true;
}


void KFocusDoc::deleteContents()
{
  /////////////////////////////////////////////////
  // TODO: Add implementation to delete the document contents
  /////////////////////////////////////////////////

	projectList()->clear();

	emit documentEmpty();
}


KFMProjectList* KFocusDoc::projectList() const{
	return projectList_;
}

/** Load a KFocus data file */
bool KFocusDoc::loadFile(QString filename){

	QString fileContents;
			
		QFile f(filename);
		if (!f.open(IO_ReadOnly))
			return false;

#if 0
		/* DO NOT give the file directly to the dom document.  The
				dom document fails to load non-ascii characters correctly. */
		if (!doc.setContent(&f)) {
			f.close();
			return false;
		}
#endif
		
		/* Read the file contents into a string before giving it to the
				dom document.  The dom document can also take data directly
				from a file, but that doesn't work right if the datafile
				contains characters larger than 127.  We work around that
				by explicitly setting the locale in the textstream used to
				read the file.  This technique contributed by Roman. */
		QTextStream localStream( &f );
			localStream.setEncoding( QTextStream::Locale );
			fileContents = localStream.read();
		
		f.close();

	QDomDocument doc("kfocus");
	if( !doc.setContent( fileContents ) ){
		return false;
	}
			
	QDomElement eDoc = doc.documentElement();
		if (eDoc.isNull())
			return false;
			
		QDomNode n = eDoc.firstChild();
		while (!n.isNull()) {
			QDomElement e = n.toElement();
			if (!e.isNull()) {
				if (e.tagName() == KFMProjectList::xmlTag()) {
					projectList()->domElement(e);
				}
			}
				
			n = n.nextSibling();
		}
			
	return true;
}


/** Test if the document is untitled */
bool KFocusDoc::isUntitled() const{
	return (doc_url.fileName() == i18n("Untitled"));
}


/** Slot for when a document component changes */
void KFocusDoc::onComponentChanged(){
	setModified(true);
}
