package learner;

import de.ls5.jlearn.abstractclasses.LearningException;
import de.ls5.jlearn.interfaces.Oracle;
import de.ls5.jlearn.interfaces.Symbol;
import de.ls5.jlearn.interfaces.Word;
import de.ls5.jlearn.shared.SymbolImpl;
import de.ls5.jlearn.shared.WordImpl;

public class MembershipOracle implements Oracle {
	private static final long serialVersionUID = -1374892499287788040L;
	private SutWrapper sutWrapper;
	private Mapper mapper;
	private int numMembQueries = 0;
	
	public MembershipOracle(EquivOracle equivOracle) {
		sutWrapper = new SutWrapper();
		/*sutWrapper.sendReset();
		String initCounter = sutWrapper.getATC();
		mapper = new Mapper(new Integer(initCounter), sutWrapper);*/
		mapper = new Mapper(sutWrapper);
	}

	public Word processQuery(Word query) throws LearningException {
		Word result = new WordImpl();
		System.out.println("LearnLib Query: " + query);

		sutWrapper.sendReset();
		/*try {
			Thread.sleep(20000);
			System.out.println("sleep");
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}*/
		//sutWrapper.sendConnect();
		String input;
		String output;
		String abstractedOutput;
		
		numMembQueries++;
		System.out.println("Member query number: " + numMembQueries);

		for (Symbol currentSymbol : query.getSymbolList()) {
			input = currentSymbol.toString();
				
			System.out.println("Sending: " + input);
			output = sutWrapper.sendInput(input);
			abstractedOutput = mapper.abstractCounter(output);
			System.out.println("Received: " + abstractedOutput.toString());
	
			result.addSymbol(new SymbolImpl(abstractedOutput));
		}

		System.out.println("Returning to LearnLib: " + result);
		return result;
	}

	public int getNumMembQueries() {
		int result = numMembQueries;
		numMembQueries = 0;
		return result;
	}
	
	public boolean validateTrace(Word inputs, Word outputs) throws LearningException  {

        /*
        //we do not use the processQuery method here, because we do not want that this query is printed to the queries.txt file
        ArrayList<OutputAction> sutOutputsArray = processQueryArrayListOutputs(inputs, "MembershipOracle.validateSutTrace");
        Word sutOutputs = new WordImpl();
		for (OutputAction output : sutOutputsArray) {
			sutOutputs.addSymbol(new SymbolImpl(output.getAbstractValuesAsString()));
		}
		*/
		
		Word sutOutputs = processQuery(inputs);
		for (int i = 0; i < inputs.size(); i++) {
            Symbol outputSut = sutOutputs.getSymbolByIndex(i);
            Symbol outputCE = outputs.getSymbolByIndex(i);
            if (outputSut.equals(outputCE)) {
                continue;
            }

            System.err.println("Invalid Counterexample at index " + i +  " at input '" + inputs.getSymbolByIndex(i).toString()  
            		+ " different outputs are :  " + outputSut + "(sut) versus " + outputCE + "(ce)");
            return false;
        }
        return true;
    }
	
	public void setATC(){
		sutWrapper.sendReset();
		String initCounter = sutWrapper.getATC();
		mapper.setATC(new Integer(initCounter)); 
	}
}
