/*
 * This file is released under terms of BSD license
 * See LICENSE file for more information
 */

package cx2x.xcodeml.xelement;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;

import cx2x.xcodeml.helper.*;

/**
 * The XargumentsTable represents the arguments (7.5.3) element in XcodeML
 * intermediate representation.
 *
 * Elements:
 * - Optional:
 *   - exprModel
 *
 * @author clementval
 */

public class XargumentsTable extends XbaseElement {
  private final Map<String, XexprModel> _table;

  /**
   * Xelement standard ctor. Pass the base element to the base class and read
   * inner information (elements and attributes).
   * @param baseElement The root element of the Xelement
   */
  public XargumentsTable(Element baseElement){
    super(baseElement);
    _table = new Hashtable<>();
    readTable();
  }

  /**
   * Read all the arguments present in the arguments table
   */
  private void readTable(){
    // Read Var element
    NodeList elements = baseElement.getElementsByTagName(XelementName.VAR);
    for (int i = 0; i < elements.getLength(); i++) {
      Node n = elements.item(i);
      if (n.getNodeType() == Node.ELEMENT_NODE) {
        Element el = (Element) n;
        Xvar var = new Xvar(el);
        _table.put(var.getValue(), new XexprModel(var));
      }
    }
  }

  /**
   * Find a specific arguments.
   * @param name Name of the arguments.
   * @return The argument if found. Null otherwise.
   */
  public XexprModel findArgument(String name){
    if(_table.containsKey(name)) {
      return _table.get(name);
    }
    return null;
  }

  /**
   * Replace a var arguments by a array reference.
   * @param var       The var arguments to be replaced.
   * @param arrayRef  The new array reference arguments.
   */
  public void replace(Xvar var, XarrayRef arrayRef){
    if(var != null){
      XelementHelper.insertAfter(var, arrayRef);
      var.delete();
    } else {
      // TODO trigger a critical error
    }
  }

  /**
   * Add an arrayRef to the arguments table.
   * @param arrayRef The arrayRef to be added.
   */
  public void add(XarrayRef arrayRef){
    baseElement.appendChild(arrayRef.cloneNode());
    //_table.put(arrayRef.getVar().getValue(), arrayRef); TODO
  }

  /**
   * Add a var to the arguments table.
   * @param var The var to be added.
   */
  public void add(Xvar var){
    baseElement.appendChild(var.cloneNode());
    _table.put(var.getValue(), new XexprModel(var));
  }


  /**
   * Get number of arguments presnet in the table.
   * @return Number of arguements in the table.
   */
  public int count(){
    return _table.size();
  }

  /**
   * Check if an argument is present in the argument table
   * @param name Name of the argument to be checked.
   * @return True if the argument is present. False otherwise.
   */
  public boolean hasArgument(String name){
    return _table.containsKey(name);
  }

  /**
   * Get an iterator on the arguments table
   * @return An iterator over the arguments table
   */
  public Iterator<Map.Entry<String, XexprModel>> iterator(){
    return _table.entrySet().iterator();
  }
}

@@ -1095,42 +1095,19 @@
 .get
-ElementsByTagName(XelementName.VAR
+ChildNodes(
 );%0A 
@@ -1275,16 +1275,87 @@
 ent) n;%0A
+        switch (el.getTagName())%7B%0A          case XelementName.VAR:%0A    
         
@@ -1379,16 +1379,20 @@
 ar(el);%0A
+    
         
@@ -1436,24 +1436,288 @@
 odel(var));%0A
+            break;%0A          case XelementName.F_INT_CONST:%0A            XintConstant con = new XintConstant(el);%0A            _table.put(con.getValue(), new XexprModel(con));%0A            break;%0A        %7D%0A        // TODO read table differently to have all elements.%0A
       %7D%0A    
@@ -2865,16 +2865,284 @@
 );%0A  %7D%0A%0A
+  /**%0A   * Add a exprModel to the arguments table.%0A   * @param constant The exprModel to be added.%0A   */%0A  public void add(XintConstant constant)%7B%0A    baseElement.appendChild(constant.cloneNode());%0A    _table.put(constant.getValue(), new XexprModel(constant));%0A  %7D%0A%0A%0A%0A
 %0A  /**%0A 

Handle int const