package learner;

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

public class Mapper implements Oracle {
	private static final long serialVersionUID = -5409624854115451929L;
	private SutWrapper sutWrapper;
	private MembershipOracle memberOracle;
	private int numEquivQueries = 0;

	public Mapper() {
		sutWrapper = new SutWrapper();
	}

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

		sutWrapper.sendReset();

		String input;
		String output;

		numEquivQueries++;
		System.out.println("Equivalence query number: " + numEquivQueries);

		for (Symbol currentSymbol : query.getSymbolList()) {
			input = currentSymbol.toString();
			System.out.println("Sending: " + input);

			output = sutWrapper.sendInput(input);
			System.out.println("Abstracting: " + output);
			System.out.println("Received: " + output.toString());

			result.addSymbol(new SymbolImpl(output));
		}

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

	public Alphabet generateInputAlphabet() {
		Alphabet result = new AlphabetImpl();

		//result.addSymbol(new SymbolImpl("reset"));
		result.addSymbol(new SymbolImpl("selectApplication"));
		//result.addSymbol(new SymbolImpl("verifyPINPlaintextCorrect"));
		//result.addSymbol(new SymbolImpl("internalAuthenticate"));
		//result.addSymbol(new SymbolImpl("readValidRecord"));
		//result.addSymbol(new SymbolImpl("readInvalidRecord"));
		//result.addSymbol(new SymbolImpl("getValidData"));
		//result.addSymbol(new SymbolImpl("getInvalidData"));
		result.addSymbol(new SymbolImpl("getProcessingOptions"));
		//result.addSymbol(new SymbolImpl("getProcessingOptionsInvalid"));
		result.addSymbol(new SymbolImpl("generateACFirstTC"));
		result.addSymbol(new SymbolImpl("generateACFirstARQC"));
		result.addSymbol(new SymbolImpl("generateACFirstAAC"));
		result.addSymbol(new SymbolImpl("generateACSecondTC"));
		//result.addSymbol(new SymbolImpl("generateACSecondARQC"));
		result.addSymbol(new SymbolImpl("generateACSecondAAC"));
		
		return result;
	}

	public Alphabet generateOutputAlphabet() {
		Alphabet result = new AlphabetImpl();
		
		//result.addSymbol(new SymbolImpl("OK"));
		//result.addSymbol(new SymbolImpl("NOK"));
		result.addSymbol(new SymbolImpl("9000"));
		result.addSymbol(new SymbolImpl("900000"));
		result.addSymbol(new SymbolImpl("900040"));
		result.addSymbol(new SymbolImpl("900080"));
		
		result.addSymbol(new SymbolImpl("6283"));
		result.addSymbol(new SymbolImpl("6300"));
		result.addSymbol(new SymbolImpl("6983"));
		result.addSymbol(new SymbolImpl("6984"));
		result.addSymbol(new SymbolImpl("6985"));
		result.addSymbol(new SymbolImpl("6A81"));
		result.addSymbol(new SymbolImpl("6A83"));
		result.addSymbol(new SymbolImpl("6A88"));
		result.addSymbol(new SymbolImpl("63C0"));
		result.addSymbol(new SymbolImpl("63C1"));
		result.addSymbol(new SymbolImpl("63C2"));
		result.addSymbol(new SymbolImpl("6D00"));
		result.addSymbol(new SymbolImpl("6E00"));
		
		return result;
	}

	public void setMembershipOracle(MembershipOracle memberOracle) {
		this.memberOracle = memberOracle;
	}
	
	public MembershipOracle getMembershipOracle() {
		return memberOracle;
	}
	
	public int getNumEquivQueries() {
		return numEquivQueries;
	}
}
