package de.hsadmin.core.qserv;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.lang.CharEncoding;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

import de.hsadmin.mods.dom.Domain;
import de.hsadmin.mods.pac.BasePac;
import de.hsadmin.mods.pac.Hive;
import de.hsadmin.mods.pac.INetAddress;
import de.hsadmin.mods.pac.Pac;

public class VelocityProcessor extends AbstractProcessor {

	private static final long serialVersionUID = 1L;
	
	static {
		Properties props = new Properties();
		props.getProperty("resource.loader", "file");
		props.setProperty("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
		Velocity.init(props);
	}
	
	private String content;
	private String targetPath;
	private boolean overwriteTarget;

	public VelocityProcessor(String templateName, Hive hive, String targetPath, boolean overwriteTarget) {
		this.targetPath = targetPath;
		this.overwriteTarget = overwriteTarget;
		VelocityContext context = new VelocityContext();
		context.put("hive", hive);
		mergeTemplate(templateName, context);
	}

	public VelocityProcessor(String templateName, Pac pac, String targetPath, boolean overwriteTarget) {
		this.targetPath = targetPath;
		this.overwriteTarget = overwriteTarget;
		VelocityContext context = new VelocityContext();
		context.put("pac", pac);
		context.put("hive", pac.getHive());
		mergeTemplate(templateName, context);
	}
	
	public VelocityProcessor(String templateName, Domain dom, String targetPath, boolean overwriteTarget) {
		this.targetPath = targetPath;
		this.overwriteTarget = overwriteTarget;
		VelocityContext context = new VelocityContext();
		context.put("dom", dom);
		Pac pac = dom.getUser().getPac();
		context.put("pac", pac);
		context.put("hive", pac.getHive());
		mergeTemplate(templateName, context);
	}

	public VelocityProcessor(String templateName, Map<String, Object> templateVars, Domain dom, String targetPath, boolean overwriteTarget) {
		this.targetPath = targetPath;
		this.overwriteTarget = overwriteTarget;
		VelocityContext context = new VelocityContext();
		context.put("dom", dom);
		Pac pac = dom.getUser().getPac();
		context.put("pac", pac);
		context.put("hive", pac.getHive());
		for (String key : templateVars.keySet()) {
			context.put(key, templateVars.get(key));
		}
		mergeTemplate(templateName, context);
	}

	public VelocityProcessor(String templateName, HashMap<String, Object> templateVars, 
			String targetPath, boolean overwriteTarget) {
		this.targetPath = targetPath;
		this.overwriteTarget = overwriteTarget;
		VelocityContext context = new VelocityContext();
		for (String key : templateVars.keySet()) {
			context.put(key, templateVars.get(key));
		}
		mergeTemplate(templateName, context);
	}

	private void mergeTemplate(String templateName, VelocityContext context) {
		StringWriter writer = new StringWriter();
		Velocity.mergeTemplate(templateName, CharEncoding.UTF_8, context, writer);
		this.content = writer.toString();
	}
	
	@Override
	public Object process() throws ProcessorException {
		try {
			File file = new File(targetPath);
			if (file.exists() && !overwriteTarget) {
				return "did not overwrite existing file " + targetPath;
			}
			if (!file.exists() || file.canWrite()) {
				BufferedWriter writer = new BufferedWriter(new FileWriter(file));
				writer.append(content);
				writer.close();
			} else {
				throw new ProcessorException("could not write file " + targetPath);
			}
			return "wrote file " + targetPath;
		} catch (IOException e) {
			throw new ProcessorException(e);
		}
	}

	public static void main(String[] args) {
		Hive h = new Hive("h01", new INetAddress("192.168.1.100"));
		HashSet<Pac> pacsSet = new HashSet<Pac>();
		h.setPacs(pacsSet);
		Pac p1 = new Pac("pac01", null, new BasePac(), h);
		pacsSet.add(p1);
		Pac p2 = new Pac("pac02", null, new BasePac(), h);
		pacsSet.add(p2);
		p1.setCurINetAddr(new INetAddress("192.168.2.11"));
		p2.setCurINetAddr(new INetAddress("192.168.2.12"));
		VelocityProcessor procHosts = new VelocityProcessor("/de/hsadmin/mods/pac/hosts.vm", h, "/tmp/etc-hosts", true);
		VelocityProcessor procVirtual = new VelocityProcessor("/de/hsadmin/mods/pac/httpd-virtual.vm", h, "/tmp/httpd-virtual.conf", true);
		VelocityProcessor procInterfaces = new VelocityProcessor("/de/hsadmin/mods/pac/interfaces.vm", h, "/tmp/net-interfaces", true);
		VelocityProcessor procProFtpd = new VelocityProcessor("/de/hsadmin/mods/pac/proftpd-conf.vm", h, "/tmp/proftpd.conf", true);
		VelocityProcessor procSudoers = new VelocityProcessor("/de/hsadmin/mods/pac/sudoers.vm", h, "/tmp/sudoers", true);
		try {
			System.out.println(procHosts.process());
			System.out.println(procVirtual.process());
			System.out.println(procInterfaces.process());
			System.out.println(procProFtpd.process());
			System.out.println(procSudoers.process());
		} catch (ProcessorException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
