#include "xml-freemind.h"

#include <QDebug>
#include <QMessageBox>

#include "branchitem.h"
#include "version.h"
#include "vymmodel.h"

extern Settings settings;
extern QString vymVersion;

bool parseFreemindHandler::startDocument()  //FIXME-3 import not complete yet
{
    errorProt = "";
    state = StateInit;
    stateStack.clear();
    stateStack.append(StateInit);
    isVymPart=false;
    return true;
}


QString parseFreemindHandler::parseHREF(QString href)
{
    QString type=href.section(":",0,0);
    QString path=href.section(":",1,1);
    if (!tmpDir.endsWith("/"))
	return tmpDir + "/" + path;
    else    
	return tmpDir + path;
}

bool parseFreemindHandler::startElement  ( const QString&, const QString&,
                    const QString& eName, const QXmlAttributes& atts ) 
{
    QColor col;
    /* Testing
    qDebug() << "startElement <"<< qPrintable(eName)
	<<">  state="<<state 
	<<"  stateLast="<<stateStack.last()
	<<"   loadMode="<<loadMode
    //	<<"       line="<<qPrintable (QXmlDefaultHandler::lineNumber())
	;
    */	
    stateStack.append (state);	
    if ( state == StateInit && (eName == "map")  ) 
    {
        state = StateMap;
	if (!atts.value( "version").isEmpty() ) 
	{
	    QString v="0.9.0";
	    if (! versionLowerOrEqual( atts.value("version"),v ) )
		QMessageBox::warning( 0, "Warning: Version Problem" ,
		   "<h3>Freemind map is newer than version " +v +" </h3>"
		   "<p>The map you are just trying to load was "
		   "saved using freemind " +atts.value("version")+". "
		   "Your version of vym can parse freemind " + v +"."); 
	}
	// Create mapcenter
	model->clear();
	mapCenter=model->createMapCenter();
	lastBranch=mapCenter;

	// Create two hidden branches, because Freemind has no relative 
	// positioning for mainbranches
	mainBranchLeft  = model->createBranch (lastBranch);
	mainBranchRight = model->createBranch (lastBranch);

	mainBranchLeft->setRelPos ( QPointF(-200,0));
    mainBranchLeft->setHeadingPlainText ("  ");
	mainBranchRight->setRelPos ( QPointF(200,0));
    mainBranchRight->setHeadingPlainText ("  ");
    } else if ( eName == "attribute_registry" &&  state == StateMap ) 
    {
        state = StateAttributeRegistry;
    } else if ( eName == "attribute_name" &&  state == StateAttributeRegistry) 
    {
        state = StateAttributeName;
    } else if ( eName == "attribute_value" &&  state == StateAttributeName) 
    {
        state = StateAttributeValue;
    } else if ( eName == "node" &&  state == StateMap ) 
    {
	state=StateNode;
	readNodeAttr (atts);
    } else if ( eName == "node" &&  state == StateNode ) 
    {
	lastBranch=model->createBranch(lastBranch);
	state=StateNode;
	readNodeAttr (atts);
    } else if ( eName == "properties" )
    {
    } else if ( eName == "map_styles" )
    {
    } else if ( eName == "font" && state == StateNode) //FIXME-3 not implemented
    {
	state=StateFont;
    } else if ( eName == "edge" && state == StateNode) //FIXME-3 xlink not implemented
    {
	state=StateEdge;
    } else if ( eName == "hook" && state == StateNode) 
    {
	state=StateHook;
    } else if ( eName == "icon" && state == StateNode) 
    {
	state=StateIcon;
	if (!atts.value("BUILTIN").isEmpty() )
	{
	    QString f=atts.value("BUILTIN");
	    QString v;
	    if (f=="help")
		v="questionmark";
	    else if (f=="messagebox_warning")
		v="freemind-warning"; 
	    else if (f=="idea")
		v="lamp"; 
	    else if (f=="button_ok")
		v="hook-green"; 
	    else if (f=="button_cancel")
		v="cross-red"; 
	    else if (f.contains("full-"))
		v=f.replace("full-","freemind-priority-"); 
	    else if (f=="back")
		v="freemind-back"; 
	    else if (f=="forward")
		v="freemind-forward"; 
	    else if (f=="attach")
		v="freemind-attach"; 
	    else if (f=="ksmiletris")
		v="smiley-good"; // 
	    else if (f=="clanbomber")
		v="freemind-clanbomber"; 
	    else if (f=="desktop_new")
		v="freemind-desktopnew"; 
	    else if (f=="flag")
		v="freemind-flag"; 
	    else if (f=="gohome")
		v="freemind-gohome"; 
	    else if (f=="kaddressbook")
		v="freemind-kaddressbook"; 
	    else if (f=="knotify")
		v="freemind-knotify"; 
	    else if (f=="korn")
		v="freemind-korn";
	    else if (f=="Mail")
		v="freemind-mail"; 
	    else if (f=="password")
		v="freemind-password"; 
	    else if (f=="pencil")
		v="freemind-pencil";
	    else if (f=="stop")
		v="freemind-stop"; 
	    else if (f=="wizard")
		v="freemind-wizard";
	    else if (f=="xmag")
		v="freemind-xmag";
	    else if (f=="bell")
		v="freemind-bell";
	    else if (f=="bookmark")
		v="freemind-bookmark"; 
	    else if (f=="penguin")
		v="freemind-penguin"; 
	    else if (f=="licq")
		v="freemind-licq"; 
	    else 
		qWarning()<<"parseFreemindHandler: Unknown icon found: "<<f;

	    lastBranch->activateStandardFlag (v);
	}
    } else if ( eName == "arrowlink" && state == StateNode) 
    {
	state=StateArrowLink;
    } else if ( eName == "cloud" && state == StateNode) 
    {
	state=StateCloud;
    } else if ( eName == "richcontent" && state == StateNode) 
    {
	state=StateRichContent;
	return readRichContentAttr (atts);
    } else if ( eName == "html" && state == StateRichContent) 
    {
	state=StateHtml;
	htmldata="<"+eName;
	readHtmlAttr(atts);
	htmldata+=">";
    } else if ( eName == "text" && state == StateHook) 
    {
	state=StateText;
    } else if ( state == StateHtml ) 
    {
	// accept all while in html mode,
	htmldata+="<"+eName;
	readHtmlAttr(atts);
	htmldata+=">";
    } else 
    {
        // Usually we would return an error here
        // In order to not break with every new element in FreeMind or FreePlane,
        // better ignore the new element for now
        state=StateUnknown;
	qWarning()<<"parseFreemindHandler: Unknown element found and ignoring:: "<<eName;
    }
    return true;
}

bool parseFreemindHandler::endElement  ( const QString &, const QString&, const QString &eName)
{
    /* Testing
    qDebug() << "endElement </" <<qPrintable(eName)
	<<">  state=" <<state 
	<<"  stateStack="<<stateStack.last() 
	;
    */
    switch ( state ) 
    {
	case StateMap:
	    // Freemind does not have the two "extra" mainbranches used here,
	    // so we have to update mapcenter
	    model->emitDataChanged (mapCenter);

	    // Remove helper branches, if not needed
	    if (mainBranchLeft->childCount()==0) model->deleteItem (mainBranchLeft);
	    if (mainBranchRight->childCount()==0) model->deleteItem (mainBranchRight);
	    break;
        case StateNode: 
	    model->emitDataChanged (lastBranch);
	    lastBranch=(BranchItem*)lastBranch->parent();
	    lastBranch->setLastSelectedBranch (0);  
            break;
	case StateRichContent:
	    if (!htmldata.isEmpty()) 
	    {
		if (htmlPurpose==Node)
            lastBranch->setHeadingPlainText (htmldata);  // FIXME-3 probably wrong for RT heading
		else if (htmlPurpose==Note)
		    lastBranch->setNote (htmldata);
	    }	
	    break;
        case StateHtml: 
	    htmldata+="</"+eName+">";
	    if (eName=="html")
	    {
		//state=StateHtmlNote;  
		htmldata.replace ("<br></br>","<br />");
	    }	
	    break;
	default: 
	    break;
    }  
    state=stateStack.takeLast();    
    return true;
}

bool parseFreemindHandler::characters   ( const QString& ch)
{
    //qDebug() << "characters \""<<qPrintable(ch)<<"\"  state="<<state;

    QString ch_org=quotemeta (ch);
    QString ch_simplified=ch.simplified();
    if ( ch_simplified.isEmpty() ) return true;

    switch ( state ) 
    {
        case StateInit: break;
        case StateMap: break; 
        case StateNode: break; 
        case StateCloud: break; 
        case StateEdge: break; 
        case StateIcon: break; 
        case StateArrowLink: break; 
        case StateFont: break; 
        case StateHook: break; 
        case StateText: 
	    lastBranch->setNote (ch_simplified);
	    break; 
        case StateHtml:
	    htmldata+=ch_org;
	    break;
        default: 
	    return false;
    }
    return true;
}

QString parseFreemindHandler::errorString() 
{
    return "the document is not in the Freemind file format";
}

bool parseFreemindHandler::readNodeAttr (const QXmlAttributes& a)  
{
    // Freemind has a different concept for mainbranches
    if (!a.value( "POSITION").isEmpty() )
    {
	if (a.value ("POSITION")=="left")
	    model->relinkBranch (lastBranch, mainBranchLeft);
	else if (a.value ("POSITION")=="right")
	    model->relinkBranch (lastBranch, mainBranchRight);
    } 

    if (a.value( "FOLDED")=="true" )
	lastBranch->toggleScroll();

    if (!a.value( "TEXT").isEmpty() )
    {
    lastBranch->setHeadingPlainText (a.value ("TEXT"));  // FIXME-3 what about RT?
	//model->setHeading (a.value ("TEXT"), lastBranch);
    }

    if (!a.value( "COLOR").isEmpty() )
	lastBranch->setHeadingColor (QColor (a.value ("COLOR")));

    if (!a.value( "LINK").isEmpty() )	
	lastBranch->setURL (a.value ("LINK"));
    return true;    
}


bool parseFreemindHandler::readRichContentAttr (const QXmlAttributes& a)  
{
    if (a.value ("TYPE")=="NODE" )
	htmlPurpose=Node;
    else if (a.value ("TYPE")=="NOTE" )
	htmlPurpose=Note;
    else
    {
	htmlPurpose=Unknown;
	qWarning()<<"parseFreemindHandler: Unknown purpose of richContent found: "<<a.value("TYPE");;
        // FIXME-3 Usually we would stop here, ignore for now
	//return false;
    }	
    return true;
}

