/*************************************************************************
 *    CompuCell - A software framework for multimodel simulations of     *
 * biocomplexity problems Copyright (C) 2003 University of Notre Dame,   *
 *                             Indiana                                   *
 *                                                                       *
 * This program is free software; IF YOU AGREE TO CITE USE OF CompuCell  *
 *  IN ALL RELATED RESEARCH PUBLICATIONS according to the terms of the   *
 *  CompuCell GNU General Public License RIDER 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.               *
 *                                                                       *
 * This program is distributed in the hope that it will be useful, but   *
 *      WITHOUT ANY WARRANTY; without even the implied warranty of       *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    *
 *             General Public License for more details.                  *
 *                                                                       *
 *  You should have received a copy of the GNU General Public License    *
 *     along with this program; if not, write to the Free Software       *
 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.        *
 *************************************************************************/

#include "Simulator.h"
using namespace CompuCell3D;

#include <BasicUtils/BasicException.h>
#include <BasicUtils/BasicSmartPointer.h>

#include <XMLCereal/XMLPullParser.h>

#include <XercesUtils/XercesStr.h>

#include <xercesc/util/PlatformUtils.hpp>
XERCES_CPP_NAMESPACE_USE;

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

#include <stdlib.h>

#include <config.h>

void Syntax(const string name) {
  cerr << "Syntax: " << name << " <config>" << endl;
  exit(1);
}

int main(int argc, char *argv[]) {



  try {
    // Command line
    if (argc < 2) Syntax(argv[0]);
	
    // Load Plugin Libaries
    // Libaries in COMPUCELL3D_PLUGIN_PATH can override the
    // DEFAULT_PLUGIN_PATH
    char *pluginPath = getenv("COMPUCELL3D_PLUGIN_PATH");
    cerr<<"pluginPath="<<pluginPath<<endl;
    if (pluginPath) Simulator::pluginManager.loadLibraries(pluginPath);
    
   
    
#ifdef DEFAULT_PLUGIN_PATH
    Simulator::pluginManager.loadLibraries(DEFAULT_PLUGIN_PATH);
#endif

    BasicPluginManager<Plugin>::infos_t *infos = 
      &Simulator::pluginManager.getPluginInfos();

    if (!infos->empty()) {
      cout << "Found the following plugins:" << endl;
      BasicPluginManager<Plugin>::infos_t::iterator it; 
      for (it = infos->begin(); it != infos->end(); it++)
	cout << "  " << *(*it) << endl;
      cout << endl;
    }


    // Create Simulator
    Simulator sim;


    // Initialize Xerces
    XMLPlatformUtils::Initialize();
    
    // Create parser
    BasicSmartPointer<XMLPullParser> parser = XMLPullParser::createInstance();

    // Parse config
    try {
      // Start
      parser->initParse(argv[1]);
      parser->match(XMLEventTypes::START_DOCUMENT, -XMLEventTypes::TEXT);

      // Parse
      parser->assertName("CompuCell3D");
      parser->match(XMLEventTypes::START_ELEMENT);
      sim.readXML(*parser);
      parser->match(XMLEventTypes::END_ELEMENT, -XMLEventTypes::TEXT);

      // End
      parser->match(XMLEventTypes::END_DOCUMENT);

    } catch (BasicException e) {
      throw BasicException("While parsing configuration!",
			   parser->getLocation(), e);
    }

    sim.extraInit();///additional initialization after all plugins and steppables have been loaded and preinitialized
    // Run simulation
    sim.start();
    
    
    
    for (unsigned int i = 1; i <= sim.getNumSteps(); i++)
      sim.step(i);
    sim.finish();

    return 0;

  } catch (const XMLException &e) {
    cerr << "ERROR: " << XercesStr(e.getMessage()) << endl;

  } catch (const BasicException &e) {
    cerr << "ERROR: " << e << endl;
  }

  return 1;
}
