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

package cx2x.translator.transformation.openacc;

import cx2x.translator.common.Constant;
import cx2x.xcodeml.exception.IllegalTransformationException;
import cx2x.xcodeml.helper.XelementHelper;
import cx2x.xcodeml.language.AnalyzedPragma;
import cx2x.xcodeml.transformation.Transformation;
import cx2x.xcodeml.transformation.Transformer;
import cx2x.xcodeml.xelement.XcodeProgram;
import cx2x.xcodeml.xelement.Xpragma;

/**
 * <pre>
 * OpenACC line continuation transformation. The XcodeML/F prgama statement
 * representation is an aggrated version of the pragma with all its continuation
 * lines.
 * As thoses directives are not handled by the CLAW XcodeML to XcodeML
 * translator, they must be output in a correct way. This transformation divides
 * the XcodeML representation back to a multi-line pragma definition.
 *
 * Example:
 * The followings OpenACC directives in Fortran code:
 *
 *   !$acc data &amp;
 *   !$acc present (a,b,c,d,e,f,g)
 *
 * are represented in XcodeML with
 *
 * &lt;FpragmaStatement&gt;acc data acc present (a,b,c,d,e,f,g)&lt;/FpragmaStatement&gt;
 *
 * The transofrmation will split it like this:
 *
 * &lt;FpragmaStatement&gt;acc data &amp; &lt;/FpragmaStatement&gt;
 * &lt;FpragmaStatement&gt;acc present (a,b,c,d,e,f,g)&lt;/FpragmaStatement&gt;
 * </pre>
 *
 * @author clementval
 */
public class OpenAccContinuation extends Transformation {

  /**
   * Constructs a new LoopFusion triggered from a specific pragma.
   * @param directive The directive that triggered the loop fusion
   *                  transformation.
   */
  public OpenAccContinuation(AnalyzedPragma directive){
    super(directive);
  }


  /**
   * Loop fusion analysis: find whether the pragma statement is followed by a
   * do statement.
   * @param xcodeml      The XcodeML on which the transformations are applied.
   * @param transformer  The transformer used to applied the transformations.
   * @return True if a do statement is found. False otherwise.
   */
  public boolean analyze(XcodeProgram xcodeml, Transformer transformer) {
    return getDirective().getPragma().getValue().toLowerCase().
        startsWith(Constant.OPENACC_PREFIX);
  }

  @Override
  public boolean canBeTransformedWith(Transformation other) {
    // independent transformation
    return false;
  }

  /**
   * Apply the loop fusion transformation.
   * @param xcodeml         The XcodeML on which the transformations are
   *                        applied.
   * @param transformer     The transformer used to applied the transformations.
   * @param transformation  Not used in this transformation
   * @throws IllegalTransformationException if the transformation cannot be
   * applied.
   */
  @Override
  public void transform(XcodeProgram xcodeml, Transformer transformer,
                        Transformation transformation)
      throws IllegalTransformationException
  {
    String allPragma = getDirective().getPragma().getValue();

    String[] pragmas = allPragma.split(Constant.OPENACC_PREFIX);

    if(pragmas.length != 2) {
      getDirective().getPragma().setValue(Constant.OPENACC_PREFIX + " " +
          pragmas[1] + " " + Constant.CONTINUATION_LINE_SYMBOL);
      Xpragma newlyInserted = getDirective().getPragma();
      for (int i = 2; i < pragmas.length; ++i) {
        Xpragma p = XelementHelper.createEmpty(Xpragma.class, xcodeml);
        p.setFile(getDirective().getPragma().getFile());
        p.setLine(getDirective().getPragma().getLineNo() + (i - 1));
        if (i == pragmas.length - 1) {
          p.setValue(Constant.OPENACC_PREFIX + " " + pragmas[i]);
        } else {
          p.setValue(Constant.OPENACC_PREFIX + " " + pragmas[i] + " " +
              Constant.CONTINUATION_LINE_SYMBOL);
        }
        XelementHelper.insertAfter(newlyInserted, p);
        newlyInserted = p;
      }
    }
  }
}

@@ -500,23 +500,51 @@
 ml.x
-element.Xpragma
+node.Xcode;%0Aimport cx2x.xcodeml.xnode.Xnode
 ;%0A%0A/
@@ -3062,17 +3062,16 @@
 alue();%0A
-%0A
     Stri
@@ -3307,32 +3307,125 @@
     
-Xpragma newlyInserted = 
+// TODO XNODE take directly pragma as Xnode when refactoring is done%0A      Xnode newlyInserted%0A          = new Xnode(
 getD
@@ -3446,16 +3446,34 @@
 Pragma()
+.getBaseElement())
 ;%0A      
@@ -3528,59 +3528,49 @@
    X
-pragma p = XelementHelper.createEmpty(Xpragma.class
+node p = new Xnode(Xcode.FPRAGMASTATEMENT
 , xc
@@ -3577,16 +3577,17 @@
 odeml);%0A
+%0A
         
@@ -3700,24 +3700,25 @@
 + (i - 1));%0A
+%0A
         if (

Move to Xnode abstraction