/***************************************************************************
                          SIMPLY POWERFUL TOOLKIT (SPTK)
                               DEMO PROGRAMS SET
                          cxml_test1.cpp  -  description
                             -------------------
    begin                : August 10, 2003
    copyright            : (C) 2003-2006 by Alexey S.Parshin
    email                : alexeyp@gmail.com
 ***************************************************************************/

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

#ifdef __BORLANDC__
#include <vcl.h>
#pragma hdrstop
#endif

#include <FL/fl_ask.H>
#include <FL/Fl.h>

#include <sptk3/CDateTime.h>
#include <sptk3/CException.h>
#include <sptk3/CWindow.h>
#include <sptk3/CFileOpenDialog.h>
#include <sptk3/CTreeControl.h>

#include <sptk3/xml/CXml.h>

using namespace std;
using namespace sptk;

void build_tree(CXmlNode *n,CTreeControl *tree,CTreeItem *item) {
   if(!n) return;

   CTreeItem *w=0;
   CTreeItem *newItem=0;
   if (n->size() || n->type() & (CXmlNode::DOM_CDATA_SECTION|CXmlNode::DOM_COMMENT)) {
      // Create a new item group
      if (item)
         newItem = item->addItem("",0L,0L,n);
      else newItem = tree->addItem("",0L,0L,n);
      w = newItem;
      if (n->type() & (CXmlNode::DOM_CDATA_SECTION|CXmlNode::DOM_COMMENT)) {
         w->label(n->name().c_str());
         w = newItem->addItem("",0L,0L,n);
      }
   } else {
      if (item)
         newItem = item->addItem("",0L,0L,n);
      else newItem = tree->addItem("",0L,0L,n);
      w = newItem;
   }

   string label;
   const CXmlAttributes &attr_map = n->attributes;

   switch(n->type()) {
      case CXmlNode::DOM_ELEMENT:
         label = n->name();
         if(n->hasAttributes()) {
            CXmlAttributes::const_iterator it = attr_map.begin();
            for(; it != attr_map.end(); it++)
               label += string(" ") + it->first + string("=*") + it->second + "*";
         }
         break;

      case CXmlNode::DOM_PI:
         label = n->name();
         label += ": ";
         label += n->value();
         break;

      case CXmlNode::DOM_DOCUMENT:
         label = n->name();
         break;

      default:
         label = n->value();
         break;
   };

   w->label(label.c_str());

   CXmlNode::iterator itor = n->begin();
   CXmlNode::iterator iend = n->end();
   for (; itor != iend; itor++) {
      CXmlNode *node = *itor;
      build_tree(node,tree,newItem);
   }
}

CXmlDoc *build_doc() {
   CXmlDoc *doc = new CXmlDoc();

   CXmlNode *rootNode = new CXmlElement(*doc,"MyDocument");
   CXmlNode *hello = new CXmlElement(*rootNode,"HelloTag");
   new CXmlElement(*hello,"Hello all!");

   try {
      CBuffer savebuffer;
      doc->save(savebuffer);
      savebuffer.saveToFile("MyXML2.xml");
   } catch(...) {
      Fl::warning("Error!");
   }

   return doc;
}

int main(int argc, char **argv) {
   string fileName;
   if (argc == 2) {
      fileName = argv[1];
   } else {
      CFileOpenDialog dialog;
      dialog.directory(".");
      dialog.addPattern("XML Files","*.xml");
      dialog.addPattern("HTML Files","*.htm;*.html");
      dialog.addPattern("All Files","*.*");
      dialog.execute();
      fileName = dialog.fullFileName();
   }

   if(fileName.empty()) return -1;

   CBuffer  buffer;
   try {
      buffer.loadFromFile(fileName.c_str());
   }
   catch (exception& e) {
      puts(e.what());
      return 12;
   }

   bool html_mode = (fileName.find(".htm") != string::npos);

   CWindow *window = new CWindow(300,300);
   window->resizable(window);
   window->begin();

   CTreeControl *tree = new CTreeControl("",10,SP_ALIGN_CLIENT);
   window->end();

   try {

      CDateTime start = CDateTime::Now();
      CXmlDoc *doc = new CXmlDoc;
      doc->load(buffer,html_mode);
      CDateTime end = CDateTime::Now();

      char message[128];
      sprintf(message,"XML Test - loaded file in %0.2f sec",((double)end - double(start)) * 24 * 3600);
      window->label(message);
      puts(message);

      build_tree(doc,tree,0L);
      start = CDateTime::Now();
      tree->relayout();
      end = CDateTime::Now();
      printf("XML Test - relayouted tree in %0.2f sec\n",((double)end - double(start)) * 24 * 3600);

      try {
         CDateTime start = CDateTime::Now();
         CBuffer savebuffer;
         doc->save(savebuffer);
         savebuffer.saveToFile("MyXML.xml");
         end = CDateTime::Now();
         printf("XML Test - saved for %0.2f sec\n",((double)end - double(start)) * 24 * 3600);
      } catch(...) {
         Fl::warning("Error!");
      }
      delete doc;
   }
   catch(std::exception &e) {
      puts("");
      puts("------------------------");
      puts(e.what());
      puts("------------------------");
   }
   catch(...) {
      puts("");
      puts("------------------------");
      puts("Unknown error");
      puts("------------------------");
   }

   window->relayout();

   window->show();

   Fl::run();

   return 0;
}
