package dfatool.strategy.verification.fdr2;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.nio.file.CopyOption;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.osgi.framework.Bundle;

import dfatool.parser.ParseException;
import dfatool.strategy.elements.Channel;
import dfatool.strategy.elements.Configuration;
import dfatool.strategy.elements.ConfigurationConstants;
import dfatool.strategy.elements.Context;
import dfatool.strategy.elements.Description;
import dfatool.strategy.elements.Network;
import dfatool.strategy.elements.patterns.ResourceAllocationDescription;
import dfatool.strategy.verification.IFileGeneration;
import dfatool.strategy.verification.elements.EssentialComponent;

public class FileGeneration implements IFileGeneration{

	private VelocityEngine ve;
	private URL rootURL;
	
	public static final String ModelFileName = "Model.csp";

	public FileGeneration() {
		Bundle bundle = Platform.getBundle("DFATool");
		try {
			rootURL = FileLocator.resolve(bundle.getEntry("/"));
//			rootURL = new URL("file:/home/pedino/Dropbox/PhD/MyPapers/SCP2015/workspace/DFATool/");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		String velocityTemplatesPath = FDRConfiguration.getTemplatesPath();
		ve = new VelocityEngine();
		System.out.println(rootURL.getPath() + velocityTemplatesPath);
		ve.setProperty("file.resource.loader.path", rootURL.getPath() + velocityTemplatesPath);
		ve.init();
	}
	
	@Override
	public void generateModel() {
		Description desc = Configuration.getInstance().getDescription();
		Network net = Configuration.getInstance().getNetwork();
		VelocityContext vc = new VelocityContext();
		vc.put("channels", desc.getChannels());
		vc.put("vars", desc.getVars());
		vc.put("datatypes", desc.getDatatypes());
		vc.put("atoms", desc.getAtoms());
		vc.put("networkElements", net.getList());
		Template modelTemplate = ve.getTemplate("Model.vm");
		try {
			FileWriter fw = new FileWriter(Configuration.getInstance().getProjectRoot()+ConfigurationConstants.SCRIPTS_PATH+ ModelFileName);
			modelTemplate.merge(vc, fw);
			fw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		copyDefaultFile(FDRConstants.NetworkDefaultFileName);
		
	}
	
	private void copyDefaultFile(String fileName) {
		File sourceFile = new File(rootURL.getPath()+FDRConfiguration.getDefaultFilesPath() + fileName);
		File targetFile = new File(Configuration.getInstance().getProjectRoot()+ConfigurationConstants.SCRIPTS_PATH + fileName);
		try {
			Files.copy(sourceFile.toPath(),targetFile.toPath());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void generateConflictVerification(String pid1, String pid2) {
		VelocityContext vc = new VelocityContext();
		vc.put("pid1", pid1);
		vc.put("pid2", pid2);
		Template modelTemplate = ve.getTemplate("Conflict.vm");
		try {
			System.out.println("Gen: "+Configuration.getInstance().getProjectRoot()+ConfigurationConstants.SCRIPTS_PATH+ getConflictName(pid1, pid2));
			FileWriter fw = new FileWriter(Configuration.getInstance().getProjectRoot()+ConfigurationConstants.SCRIPTS_PATH+ getConflictName(pid1, pid2));
			modelTemplate.merge(vc, fw);
			fw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		copyDefaultFile(FDRConstants.ConflictFreedomVerificationDefaultFileName);
	}
	
	public String getConflictName(String pid1, String pid2){
		return "Conflict_"+pid1+"_"+pid2+".csp";
	}


	@Override
	public void generateResourceAllocationVerification(EssentialComponent essentialComponent, ResourceAllocationDescription rad) {
		VelocityContext vc = new VelocityContext();
		vc.put("Users", rad.getUsers());
		vc.put("essentialComponent", essentialComponent);
		vc.put("Resources", rad.getResources());
		Template modelTemplate = ve.getTemplate("ResourceAllocationVerification.vm");
		try {
			FileWriter fw = new FileWriter(Configuration.getInstance().getProjectRoot()+ConfigurationConstants.SCRIPTS_PATH+ "ResourceAllocationVerification"+essentialComponent.getName()+".csp");
			modelTemplate.merge(vc, fw);
			fw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		copyDefaultFile("ResourceAllocationPattern.csp");
	}
	
	public static void main(String[] args) {
		try {
			FileWriter fw = new FileWriter("/Users/pedroribeiro/Dropbox/Mestrado/runtime-EclipseApplication/Na/FDR_Scripts/Model.csp");
			fw.write("Oi!");
			fw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void generateEssentialComponentAndResourceAllocationDescription(EssentialComponent essentialComponent, ResourceAllocationDescription rad) {
		VelocityContext vc = new VelocityContext();
		vc.put("Resources", rad.getUsers());
		vc.put("Users", rad.getResources());
		vc.put("funUsers", rad.getFunUser());
		vc.put("funResources", rad.getFunResources());
		vc.put("funAcquire", rad.getAcquireFunc());
		vc.put("essentialComponent", essentialComponent);
		vc.put("funRelease", rad.getReleaseFunc());
		Template modelTemplate = ve.getTemplate("ResourceAllocationDescription.vm");
		try {
			FileWriter fw = new FileWriter(Configuration.getInstance().getProjectRoot()+ConfigurationConstants.SCRIPTS_PATH+ "ResourceAllocationDescription"+essentialComponent.getName()+".csp");
			modelTemplate.merge(vc, fw);
			fw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


}
