/*******************************************************************************
 * Copyright (c) 2015-2017 ONERA and IRT AESE (IRT Saint Exupéry).
 * Ce logiciel est la propriété de l’ONERA (the French Aerospace Lab) et de
 * l'IRT AESE (IRT Saint Exupéry).
 * Tous droits réservés.
 *
 * Ce programme et les éléments qui l'accompagnent sont mis à disposition
 * aux conditions définies par le contrat de licence logiciel CeCILL-C soumise
 * au droit français et respectant les principes de diffusion des logiciels libres.
 * Vous pouvez utiliser, modifier et/ou redistribuer ce programme
 * sous les conditions de la licence CeCILL-C (http://www.cecill.info).

 * This software is property of ONERA (the French Aerospace Lab) and of
 * the IRT AESE (IRT Saint Exupéry).
 * All rights reserved.
 *
 * This program and the accompanying materials are made available under
 * the terms of the CeCILL-C license under French law and
 * abiding by the rules of distribution of free software.
 * You can  use, modify and/ or redistribute the software under the terms of
 * the CeCILL-C license (http://www.cecill.info).
 *
 * Contributeurs/contributors:
 *     Guillaume Infantes (ONERA - Centre de Toulouse) - initial API and implementation
 *     Alexandre Albore (IRT Saint-Exupéry) - Altarica/Fiacre translation
 *
 *******************************************************************************/

#include "AltaricaInitInfoXML2.hh"
#include "AltaricaModel.hh"
#include "MemberAccess.hh"
#include "EventLaw.hh"
#include "Event.hh"
#include "Node.hh"
#include "Variable.hh"
#include <algorithm>
#include <string>
#include "domains/Domains.hh"
#include "values/ValueBool.hh"
#include "values/ValueInt.hh"
#include "values/ValueSymbol.hh"
#include "values/ValueReal.hh"
#include "expressions/ExpressionREAL.hh"

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/exceptions.hpp>



#include <iostream>


using namespace epoch::altarica;
using boost::property_tree::ptree;
using boost::property_tree::ptree_bad_path;


AltaricaInitInfoXML2::AltaricaInitInfoXML2(std::string initFile, AltaricaModel *am) : AltaricaInitInfo(am) {
    amodel = am;
    ptree pt;
    read_xml (initFile, pt);
    

    processRoot(pt);
    overrideLaws();
}




void AltaricaInitInfoXML2::processRoot(ptree& root) {
  for (auto&v: root.get_child("init")) {       
    if (v.first.compare("node")==0)
      processNode(v.second);       
  }

}

  

void AltaricaInitInfoXML2::processEvent(ptree&  eventattr, std::vector<Node *>  *altNodeVector) {

  std::string lawName;    
  std::string param;
  std::string eventName = eventattr.get<std::string>("name");

  try {    
    lawName = eventattr.get<std::string>("law");
  } catch (ptree_bad_path e) {
  }

  try {
    param = eventattr.get<std::string>("param");
  } catch (ptree_bad_path e) {
    
  }
  
  
  bool expLaw = true;
  bool noParam = false;
  double paramdouble;
    
  if (lawName.compare("dirac") == 0)
    expLaw = false;
  if (param.empty())
    noParam = true;
  else {
    std::istringstream stm;
    stm.str(param);
    stm >>paramdouble;
    } 
  
  MemberAccess tempMA(eventName);
  
  for (auto& altNodeIt : *altNodeVector) {
      
    Event * oldEvent = altNodeIt->findEventByName(&tempMA);
    Expression *oldLaw = NULL;
    if (expLaw && noParam) {
      oldLaw = oldEvent->getLaw()->getParam();
    }
      
    EventLaw * newLaw;
    if (expLaw) {
      if (oldLaw != NULL)
          newLaw = new EventLaw(ALTARICA_EXP,oldLaw);
        else
          newLaw = new EventLaw(ALTARICA_EXP,new ExpressionREAL(paramdouble));
      } else {
        newLaw = new EventLaw(ALTARICA_DIRAC_0,0);
      }
      
      initLaws[oldEvent] = newLaw;
    }
}

void AltaricaInitInfoXML2::processValue(ptree & node, std::vector<Node *>* altNodeVector) {
  for (auto &i: *altNodeVector) {
    Variable * var = i->findStateVariableByName(node.get<std::string>("var"));
    if (var != NULL) {      
      Value * v = getValue(var,node.get<std::string>("val"));
      initValues[var->getIndex()] = v;	
    }
  }    
}



void AltaricaInitInfoXML2::processNode(ptree& pt) {
  
  std::vector<Node *> *altNodeVector = getNodes(pt.get_child("name").data());
  
  for (auto &i :pt)
    if (i.first.compare("laws")==0) {
        for (auto& ii:i.second) {
          if (ii.first.compare("event") == 0)
            processEvent(ii.second.get_child("<xmlattr>"), altNodeVector);    
        }
    }
  
    else if (i.first.compare("values") == 0) {
      for (auto& ii:i.second) {
        if (ii.first.compare("value") == 0)
          processValue(ii.second.get_child("<xmlattr>"), altNodeVector);    
      }
    
    }
  delete altNodeVector;
  
}



