/**Copyright or (C) or Copr. GET / ENST, Telecom-Paris, Ludovic Apvrille
 *
 * ludovic.apvrille AT enst.fr
 *
 * This software is a computer program whose purpose is to allow the
 * edition of TURTLE analysis, design and deployment diagrams, to
 * allow the generation of RT-LOTOS or Java code from this diagram,
 * and at last to allow the analysis of formal validation traces
 * obtained from external tools, e.g. RTL from LAAS-CNRS and CADP
 * from INRIA Rhone-Alpes.
 *
 * This software is governed by the CeCILL  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
 * license as circulated by CEA, CNRS and INRIA at the following URL
 * "http://www.cecill.info".
 *
 * As a counterpart to the access to the source code and  rights to copy,
 * modify and redistribute granted by the license, users are provided only
 * with a limited warranty  and the software's author,  the holder of the
 * economic rights,  and the successive licensors  have only  limited
 * liability.
 *
 * In this respect, the user's attention is drawn to the risks associated
 * with loading,  using,  modifying and/or developing or reproducing the
 * software by the user in light of its specific status of free software,
 * that may mean  that it is complicated to manipulate,  and  that  also
 * therefore means  that it is reserved for developers  and  experienced
 * professionals having in-depth computer knowledge. Users are therefore
 * encouraged to load and test the software's suitability as regards their
 * requirements in conditions enabling the security of their systems and/or
 * data to be ensured and,  more generally, to use and operate it in the
 * same conditions as regards security.
 *
 * The fact that you are presently reading this means that you have had
 * knowledge of the CeCILL license and that you accept its terms.
 *
 * /**
 * Class AvatarPragma
 * Creation: 20/05/2010
 * @version 1.1 01/07/2014
 * @author Ludovic APVRILLE, Raja GATGOUT
 * @see
 */

package cli;

import avatartranslator.AvatarSpecification;
import avatartranslator.tosysmlv2.AvatarFromSysML;
import avatartranslator.tosysmlv2.AvatarFromSysMLError;
import graph.AUTGraph;
import graph.AUTTransition;
import myutil.TraceManager;
import org.junit.Test;
import test.AbstractTest;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;


public class CLIAvatar2SysMLV2Test extends AbstractTest implements InterpreterOutputInterface {

    final static String PATH_TO_TEST_FILE = "cli/input/";
    final static String PATH_TO_EXPECTED_FILE = "cli/expected/";
    final static String PATH_TO_MODELS = "cli/models/";
    private final String[] toThenFrom = {"CoffeeMachine_Avatar", "avSysML_mixedexample", "PressureController"}; //
    private final String[] okFrom = {"avSysML_withTimer"}; //
    private final int[] okFromStates = {8};
    private final int[] okFromTrans = {8};
    private final String[] errorFrom =
            {"avSysML_syntaxErr1", "avSysML_syntaxErr2", "avSysML_missingBlockErr3", "avSysML_badFieldNameErr4",
                    "avSysML_missingSignalBindingErr5","avSysML_missingAttrDeclErr6"}; //
    private final String[] errorFromMsg = {
            "ERROR (l17,c112): parser: syntax error for input symbol \"SEMICOLON\". Lexeme: ;",
            "ERROR (l35,c22): parser: syntax error for input symbol \"SEMICOLON\". Lexeme: ;",
            "WARNING : blocs of relation @SYN0:B0-B1 unspecified, recovered from channel @syn:B0.in0<B1.out1",
            "ERROR (l34,c9): Field x of out-message is associated to a field (a) in in-message that does not exist (c.f. l25,c5)",
            "ERROR (l53,c5): Channel @syn:B0.out0>B1.in1 of in-message associated to out-message has only one associated signal" +
                    " (missing binding?) (c.f. l40,c5)",
            "ERROR (l120,c26): ident b is used but not declared in block B0"
    }; //
    private final boolean[] errorFromNull = {true,true,false,true,true,true};
    private StringBuilder outputResult;


    public CLIAvatar2SysMLV2Test() {
        //
    }


    public void exit(int reason) {
        System.out.println("Exit reason=" + reason);
        assertTrue(reason == 0);
    }
    public void printError(String error) {
        System.out.println("Error=" + error);
    }

    public void print(String s) {
        System.out.println("info from interpreter:" + s);
        outputResult.append(s);
    }

    @Test
    public void testToThenFrom() {
        String filePath = getBaseResourcesDir() + PATH_TO_TEST_FILE + "scriptavsysml_tothenfrom";
        String script;

        outputResult = new StringBuilder();

        File f = new File(filePath);
        assertTrue(myutil.FileUtils.checkFileForOpen(f));

        script = myutil.FileUtils.loadFileData(f);

        assertTrue(script.length() > 0);
        String header = "print dir\n set model resources/test/cli/models/";

        boolean show = false;
        for(String model : toThenFrom) {
            System.out.println("Testing Model " + model + ".................................");
            String modelScript = header + model + ".xml\n" + script;
            Interpreter interpret = new Interpreter(modelScript, this, show);
            interpret.clearAvatarSpecification();
            interpret.interpret();

            // Must now load the graph
            filePath = "avsysml_ori.aut";
            f = new File(filePath);
            assertTrue(myutil.FileUtils.checkFileForOpen(f));
            String data = myutil.FileUtils.loadFileData(f);

            assertTrue(data.length() > 0);
            AUTGraph graph = new AUTGraph();
            graph.buildGraph(data);
            graph.computeStates();
            int oristates = graph.getNbOfStates();
            int oritrans = graph.getNbOfTransitions();

            filePath = "avsysml_tgt.aut";
            f = new File(filePath);
            assertTrue(myutil.FileUtils.checkFileForOpen(f));
            data = myutil.FileUtils.loadFileData(f);

            assertTrue(data.length() > 0);
            graph = new AUTGraph();
            graph.buildGraph(data);
            graph.computeStates();
            int tgtstates = graph.getNbOfStates();
            int tgttrans = graph.getNbOfTransitions();


            System.out.println("states=" + oristates + ", " + tgtstates + " -- transitions=" + oritrans + ", " + tgttrans);
            assertTrue(oristates == tgtstates);
            assertTrue(oritrans == tgttrans);
        }
    }
    @Test
    public void okFrom() {
        String filePath = getBaseResourcesDir() + PATH_TO_TEST_FILE + "scriptavsysml_okfrom";
        String script;

        outputResult = new StringBuilder();

        File f = new File(filePath);
        assertTrue(myutil.FileUtils.checkFileForOpen(f));

        script = myutil.FileUtils.loadFileData(f);

        assertTrue(script.length() > 0);
        String header = "print dir\n set model resources/test/cli/models/";

        boolean show = false;
        int size = okFrom.length;
        for(int i = 0; i < size; i++) {
            String model = okFrom[i];
            System.out.println("Testing Model " + model + ".................................");
            String modelScript = header + model + ".sysml\n" + script;
            Interpreter interpret = new Interpreter(modelScript, this, show);
            interpret.clearAvatarSpecification();
            String error = interpret.interpretUntilError();
            assertTrue(error == null || error.equals(""));
            // Must now load the graph
            filePath = "avsysml_tgt.aut";
            f = new File(filePath);
            assertTrue(myutil.FileUtils.checkFileForOpen(f));
            String data = myutil.FileUtils.loadFileData(f);

            assertTrue(data.length() > 0);
            AUTGraph graph = new AUTGraph();
            graph.buildGraph(data);
            graph.computeStates();
            int tgtstates = graph.getNbOfStates();
            int tgttrans = graph.getNbOfTransitions();
            int oristates = okFromStates[i];
            int oritrans = okFromTrans[i];

            System.out.println("states=" + oristates + ", " + tgtstates + " -- transitions=" + oritrans + ", " + tgttrans);
            assertTrue(oristates == tgtstates);
            assertTrue(oritrans == tgttrans);
        }
    }
    @Test
    public void errFrom() {
        outputResult = new StringBuilder();

        String modelsDir = "resources/test/cli/models/";

        int size = errorFrom.length;
        for(int i = 0; i < size; i++) {
            String model = modelsDir + errorFrom[i] + ".sysml";

            System.out.println("Testing Model " + model + ".................................");
            AvatarFromSysML builder = new AvatarFromSysML();
            AvatarSpecification as = builder.sysMLtoSpec(model);
            System.out.println("Testing if null return value: (expected:" + errorFromNull[i] + ", obtained:" + (as == null) + ")");
            // expected return value ?
            assertTrue( (as == null ? errorFromNull[i] : !errorFromNull[i]));
            List<AvatarFromSysMLError> errors = builder.getErrors();
            System.out.println("Testing if errors: (expected:" + !(errorFromMsg[i] == null || errorFromMsg[i].equals("")) +
                    ", obtained:" + !(errors== null || errors.size() == 0) + ")");
            assertTrue( (errorFromMsg[i] == null || errorFromMsg[i].equals("") ? errors== null || errors.size() == 0 :
                    errors!= null && errors.size() > 0 ) );
            if (errors.size() > 0) {
                String err = errors.get(0).toString();
                System.out.println("Compare " + errorFromMsg[i] + " with " + err);
                assertTrue(errorFromMsg[i].equals(err));
            }
            else  System.out.println(" : none");
            System.out.println("Test of Model " + model + "is OK ................");
        }
    }
}