package dfatool.strategy.elements;

import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import patterns.Observer;
import patterns.Subject;
import dfatool.expressions.Expression;
import dfatool.parser.ExpressionParser;
import dfatool.parser.LanguageUtil;
import dfatool.parser.ParseException;
import dfatool.values.ListValue;
import dfatool.values.SetValue;
import dfatool.values.Value;

public class Context{
	
	private Map<String, List<Value>> channelMap;
	private Map<String,Set<Value>> typeMap;
	private Map<String,Value> varMap;
	
	public Context(Description description) {
		channelMap = new HashMap<String, List<Value>>();
		typeMap = new HashMap<String, Set<Value>>();
		varMap = new HashMap<String, Value>();
		for(Datatype dt : description.getDatatypes()){
			putType(dt);
		}
		for(Var v : description.getVars()){
			putVar(v);
		}
		for(Channel ch : description.getChannels()){
			putChannel(ch);
		}
	}
	
	public Context(Context c) {
		this.channelMap = new HashMap<String,List<Value>>(c.channelMap);
		this.typeMap = new HashMap<String,Set<Value>>(c.typeMap);
		this.varMap = new HashMap<String,Value>(c.varMap);
	}

	public void putChannel(Channel channel){
		Expression exp = LanguageUtil.parseString(channel.getType());
	  	Value v = exp.evaluate(this);
	  	ListValue l = null;
	  	if(v instanceof SetValue){
	  		l = new ListValue();
	  		l.add(v);
	  	}else if(v instanceof ListValue){
	  		l = (ListValue) v;
	  	}
		channelMap.put(channel.getName(), l);
	}
	
	public void putType(Datatype datatype){
		Expression exp = LanguageUtil.parseString(datatype.getType());
		typeMap.put(datatype.getName(), (SetValue) exp.evaluate(this));
	}
	
	public void putVar(Var var){
		Expression exp = LanguageUtil.parseString(var.getValue());
		varMap.put(var.getName(), exp.evaluate(this));
	}
	
	public Map<String, List<Value>> getChannelMap() {
		return channelMap;
	}

	public Map<String, Set<Value>> getTypeMap() {
		return typeMap;
	}

	public Map<String, Value> getVarMap() {
		return varMap;
	}
	
	public void updateContext(){
		Description description = Configuration.getInstance().getDescription();
		for(Datatype dt : description.getDatatypes()){
			putType(dt);
		}
		for(Var v : description.getVars()){
			putVar(v);
		}
		for(Channel ch : description.getChannels()){
			putChannel(ch);
		}
	}

//	private void freshContext(){
//		channelMap = new HashMap<String, List<Value>>();
//		typeMap = new HashMap<String, Set<Value>>();
//		varMap = new HashMap<String, Value>();
//	}
//	
//	private void generateContext(){
//		Description desc = Description.createDescription();
//		freshContext();
//		for(Datatype dt : desc.getDatatypes()){
//			Expression exp = LanguageUtil.parseString(dt.getType());
//			putType(dt.getName(), (SetValue) exp.evaluate(this));
//		}
//		for(Var v : desc.getVars()){
//		  	Expression exp = LanguageUtil.parseString(v.getValue());
//			putVar(v.getName(), exp.evaluate(this));
//		}
//		for(Channel ch : desc.getChannels()){
//		  	Expression exp = LanguageUtil.parseString(ch.getType());
//		  	Value v = exp.evaluate(this);
//		  	ListValue l = null;
//		  	if(v instanceof SetValue){
//		  		l = new ListValue();
//		  		l.add(v);
//		  	}else if(v instanceof ListValue){
//		  		l = (ListValue) v;
//		  	}
//			putChannel(ch.getName(), l);
//		}
//	}
//	
//	
//	public Context test(){
//		Context c = new Context();
//		return c;
//	}
//	
//	@Override
//	public void update() {
//		generateContext();
//		alertAll();
//	}
//	
//	public void dispose(){
//		instance = null;
//	}
	
//	public static void main(java.lang.String[] args) {
//		
//		Map<String,Set> s = new HashMap<String,Set>();
//		s.put("abo", new Set());
//		Context c = new Context(s, new HashMap<String,Set>(), new HashMap<String,Value>());
//		System.out.println(c.channelMap.toString());
//		s.put("abp", new Set());
//		System.out.println(c.channelMap.toString());
//	}

}
