// ** This file was generated with DemFGen (vers:4/15/2011)

package nwf.avatar;

import edu.neu.ccs.demeterf.lib.*;
import edu.neu.ccs.demeterf.lib.*;
import scg.*;
import scg.protocol.*;
import nwf.*;
import java.util.Random;
import java.lang.reflect.Method;





/** Representation of NWFAvatar */
public class NWFAvatar implements AvatarI{

    /** Construct a(n) NWFAvatar Instance */
    public NWFAvatar(){
    }
    /** Is the given object Equal to this NWFAvatar? */
    public boolean equals(Object o){
        if(!(o instanceof NWFAvatar))return false;
        if(o == this)return true;
        NWFAvatar oo = (NWFAvatar)o;
        return true;
    }
    /** Parse an instance of NWFAvatar from the given String */
    public static NWFAvatar parse(String inpt) throws nwf.avatar.ParseException{
        return new nwf.avatar.TheParser(new java.io.StringReader(inpt)).parse_NWFAvatar();
    }
    /** Parse an instance of NWFAvatar from the given Stream */
    public static NWFAvatar parse(java.io.InputStream inpt) throws nwf.avatar.ParseException{
        return new nwf.avatar.TheParser(inpt).parse_NWFAvatar();
    }
    /** Parse an instance of NWFAvatar from the given Reader */
    public static NWFAvatar parse(java.io.Reader inpt) throws nwf.avatar.ParseException{
        return new nwf.avatar.TheParser(inpt).parse_NWFAvatar();
    }

	
	private Config config;
	
	/** Constructor to be called during registration where you supply config */
	public NWFAvatar(Config cfg){
		config = cfg;
	}
	
	/** proposing random unique claims which are not in the forbidden list */
	public List<Claim> propose(List<Claim> forbiddenClaims){
		List<Claim> claims = List.create();
		SCGConfig scg_cfg = config.getScgCfg();
		int maxProposals = scg_cfg.getMaxProposals() - 1;
		Claim claim = null;
		
		for (int i = 0; i < maxProposals; i++) {
			claim = generateRandomClaim();
			
			while (forbiddenClaims.contains(claim)
					|| claims.contains(claim)) {
				claim = generateRandomClaim();
			}
			
			claims = claims.append(claim);
		}
		
		return claims;
	}
	
	/** 
	 * Generates random claim 
	 */
	private Claim generateRandomClaim() {
		Random rand = new Random();
		
		NWFConfig nwf_cfg = (NWFConfig)config.getDomainConfig();
		int maxN = nwf_cfg.getMaxN();
		
		// c1, c2, c3 are in [1, maxN]
		
		int c1 = rand.nextInt(maxN) + 1;
		int c2 = rand.nextInt(maxN) + 1;
		int c3 = rand.nextInt(maxN) + 1;
		
	    String inpt = "instance " +
				      "\"s\" successors (\"1\" c " + c1 + " f 0) " +
				      "\"1\" successors (\"t\" c " + c2 + " f 0) " +
				      "\"2\" successors (\"t\" c " + c3 + " f 0) " +
				      "\"t\" successors () " +
				      "source \"s\" " +
				      "sink \"t\"";
		
		NWFInstance singleton = null;
		
		try {
			singleton = NWFInstance.parse(inpt);
		} catch (nwf.ParseException e) {
			e.printStackTrace();
		}
		
		NWFInstanceSet instanceSet = new NWFInstanceSet(singleton);
		
		// To Change: The protocol instance must be one of the
		// allowed protocols mentioned in SCGConfig
		Cons<FullyQualifiedClassName> protocolsAllowed = config.getScgCfg().getProtocols();
		ProtocolI protocol = generateRandomAllowedProtocol(protocolsAllowed );		
		
		return new Claim(instanceSet, protocol, 0.5, 0.5);
	}
		
	/** generates a random protocol instance from the given protocolsAllowed */
	private ProtocolI generateRandomAllowedProtocol(Cons<FullyQualifiedClassName> protocolsAllowed){
		Random rand = new Random();
		FullyQualifiedClassName randProtocol = protocolsAllowed.lookup(rand.nextInt(protocolsAllowed.length()));
		ProtocolI protocol = null;
		try{
		Class<?> protocolClass = Class.forName(randProtocol.print().trim());
		Method instance = protocolClass.getMethod("parse", String.class);
		protocol = (ProtocolI) instance.invoke(null, randProtocol.print().trim());
		}catch(Exception ex){
			ex.printStackTrace();
		}
		return protocol;
	}
	
	
	/** Random oppose method - randomly agrees, refutes or strengthens */
	public List<OpposeAction> oppose(List<Claim> claimsToBeOpposed){
		
		
		return claimsToBeOpposed.map(new List.Map<Claim, OpposeAction>() {
			public OpposeAction map(Claim claim){
				Random rand = new Random();
				int randOppose = rand.nextInt(3);
				if(randOppose == 0)
					return new Agreement();
				else if(randOppose == 1){
					double q = claim.getQuality();
					SCGConfig scg_cfg = config.getScgCfg();
					
					if (claim.getProtocol() instanceof ForAllExists){
						if (q > scg_cfg.getMinStrengthening())
							return new Strengthening(claim.getQuality() - scg_cfg.getMinStrengthening());
						else
							return new Refuting();
					}else{
						if (q < scg_cfg.getMinStrengthening()) {
							return new Strengthening(claim.getQuality() + scg_cfg.getMinStrengthening());
						} else {
							return new Refuting();
						}
					}
						 
				}else 
					return new Refuting();
            }
		});
	}
	
	/** providing instance method - provides symmetric Instance of given instanceSet */
	public InstanceI provide(Claim claimToBeProvided){
		NWFInstanceSet nwfInstanceSet = (NWFInstanceSet)claimToBeProvided.getInstanceSet();
		NWFInstance nwfInstance = new NWFInstance(nwfInstanceSet.getSingleton().getG(),
				nwfInstanceSet.getSingleton().getSource(), 
				nwfInstanceSet.getSingleton().getSink());
		
		return nwfInstance;
	}
	
	/** */
	public SolutionI solve(SolveRequest solveRequest){
		NWFInstance nwfInstance = (NWFInstance)solveRequest.getInstance();
		NWFSolution solution = solve(nwfInstance);
		
		return solution;
	}
	
	/**
     * solve function
	 */
    private NWFSolution solve(NWFInstance nwfInstance) {

        return new NWFSolution(nwfInstance.getG(), 
    			        nwfInstance.getSource(), 
    			        nwfInstance.getSink());
	}

    /** DGP method from Class Display */
    public String display(){ return nwf.avatar.Display.DisplayM(this); }
    /** DGP method from Class Print */
    public String print(){ return nwf.avatar.Print.PrintM(this); }
    /** DGP method from Class ToStr */
    public String toStr(){ return nwf.avatar.ToStr.ToStrM(this); }
    /** DGP method from Class PrintToString */
    public String toString(){ return nwf.avatar.PrintToString.PrintToStringM(this); }
    /** DGP method from Class HashCode */
    public int hashCode(){ return nwf.avatar.HashCode.HashCodeM(this); }

}


