package innovimax.mixthem;

import innovimax.mixthem.arguments.Mode;
import innovimax.mixthem.arguments.ParamValue;
import innovimax.mixthem.arguments.Rule;
import innovimax.mixthem.arguments.RuleParam;
import innovimax.mixthem.io.InputResource;

import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;

import org.junit.Assert;
import org.junit.Test;
import org.junit.experimental.theories.*;
import org.junit.runner.RunWith;

/*
	Created by innovimax
	Generic tests for this application
*/
public class GenericTest {

   @Test
   public final void testCharRules() throws MixException, FileNotFoundException, IOException, NumberFormatException {
	   testRules(Mode.CHAR);
   }

   @Test
   public final void testBytesRules() throws MixException, FileNotFoundException, IOException, NumberFormatException {
	   testRules(Mode.BYTE);
   }

   private final void testRules(final Mode mode) throws MixException, FileNotFoundException, IOException, NumberFormatException {
	   MixThem.setLogging(Level.FINE);
	   int testId = 1;
	   List<String> failed = new ArrayList<String>();
	   boolean result = true;
	   while (true) {
		   MixThem.LOGGER.info("TEST [" + mode.getName().toUpperCase() + "] N° " + testId + "***********************************************************");
		   final String prefix = "test" + String.format("%03d", testId) +"_";
		   final List<URL> urlF = new ArrayList<URL>();
		   int index = 1;
		   while (true) {
			   final URL url = getClass().getResource(prefix + "file" + index + ".txt");
			   if (url != null) {
				   urlF.add(url);
				   index++;
			   } else {
				   break;
			   }
		   }		   		   
		   if( urlF.size() < 2) break;
		   for (int i=0; i < urlF.size(); i++) {
			   MixThem.LOGGER.info("File " + i + ": " + urlF.get(i));
		   }
		   for(Rule rule : Rule.values()) {			   
			   if (rule.isImplemented() && rule.acceptMode(mode)) {
				   String paramsFile = prefix + "params-" + rule.getExtension() + ".txt";
				   URL urlP = getClass().getResource(paramsFile);
				   List<RuleRun> runs = RuleRuns.getRuns(rule, urlP);
				   for (RuleRun run : runs) {
					   String resultFile = prefix + "output-" + rule.getExtension();
					   if (run.hasSuffix()) {
						   resultFile += "-" + run.getSuffix();
					   }
					   resultFile += ".txt";
					   URL urlR = getClass().getResource(resultFile);					   
					   if (urlR != null) {
						   MixThem.LOGGER.info("--------------------------------------------------------------------");
						   if (urlP != null) {
							   MixThem.LOGGER.info("Params file : " + urlP);
						   }
						   MixThem.LOGGER.info("Result file : " + urlR);
						   MixThem.LOGGER.info("--------------------------------------------------------------------");
						   boolean res = check(new File(urlF.get(0).getFile()), new File(urlF.get(1).getFile()), new File(urlR.getFile()), mode, rule, run.getParams());
						   MixThem.LOGGER.info("Run " + (res ? "pass" : "FAIL") + " with params " + run.getParams().toString());
						   result &= res;
						   if (!res) {
							   failed.add(Integer.toString(testId));
						   }
					   }
				   }
			   }
		   }
		   testId++;
	   }
	   MixThem.LOGGER.info("*********************************************************************");
	   MixThem.LOGGER.info("FAILED [" + mode.getName().toUpperCase() + "] TESTS : " + (failed.size() > 0 ? failed.toString() : "None"));
	   MixThem.LOGGER.info("*********************************************************************");
	   Assert.assertTrue(result);
   }	   

   private final static boolean check(final File file1, final File file2, final File expected, final Mode mode, final Rule rule, final Map<RuleParam, ParamValue> params)  throws MixException, FileNotFoundException, IOException  {
	   MixThem.LOGGER.info("Run and check result...");	   
	   List<InputResource> inputs = new ArrayList<InputResource>();
	   inputs.add(InputResource.createFile(file1));
	   inputs.add(InputResource.createFile(file2));
	   ByteArrayOutputStream baos_rule = new ByteArrayOutputStream();
	   MixThem mixThem = new MixThem(inputs, baos_rule);
           mixThem.process(mode, rule, params);
	   MixThem.LOGGER.info("Run and print result...");
	   mixThem = new MixThem(inputs, System.out);
           mixThem.process(mode, rule, params);
	   return checkFileEquals(expected, baos_rule.toByteArray());
   }

	private static boolean checkFileEquals(final File fileExpected, final byte[] result) throws FileNotFoundException, IOException {
	   FileInputStream fisExpected = new FileInputStream(fileExpected);
	   int c;
	   int offset = 0;
	   while ((c = fisExpected.read()) != -1) {
		   if (offset >= result.length) return false;
		   int d = result[offset++];
		   if (c != d) return false;
	   }
	   if (offset > result.length) return false;
	   return true;
	}

}

@@ -1854,17 +1854,21 @@
 ile %22 + 
-i
+(i+1)
  + %22: %22 
@@ -2883,98 +2883,18 @@
 eck(
-new File(urlF.get(0).getFile()), new File(urlF.get(1).getFile()), new File(urlR.getFile())
+urlF, urlR
 , mo
@@ -3610,26 +3610,34 @@
 nal 
-File
+List%3CURL%3E
  file
-1
+sURL
 , final 
 File
@@ -3636,39 +3636,21 @@
 nal 
-File file2, final File expected
+URL resultURL
 , fi
@@ -3838,24 +3838,30 @@
 %22);%09   %0A%09   
+final 
 List%3CInputRe
@@ -3917,57 +3917,40 @@
 %09   
-inputs.add(InputResource.createFile(file1));
+for (URL url : filesURL) %7B
 %0A%09   
+%09
 inpu
@@ -3985,21 +3985,29 @@
 ile(
-file2
+url.getFile()
 ));%0A%09   
 Byte
@@ -4002,16 +4002,28 @@
 ));%0A%09   
+%7D%0A%09   final 
 ByteArra
@@ -4077,24 +4077,30 @@
 ream();%0A%09   
+final 
 MixThem mixT
@@ -4328,24 +4328,79 @@
 e, params);%0A
+%09   final File result = new File(resultURL.getFile());%0A
 %09   return c
@@ -4418,16 +4418,14 @@
 als(
-expected
+result
 , ba

Update GenericTest.java