package org.etsi.mts.ttcn3.part9.popup.actions;

import java.io.ByteArrayInputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IActionDelegate;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;

public class NewTestCase implements IObjectActionDelegate {

	private Shell shell;

	protected String tckind = "Pos";

	protected ISelection selection;
	
	private static final String TTCN_TEMPLATE = "/***************************************************\n"
			+ " ** @author   STF 475\n"
			+ " ** @version  0.0.1\n"
			+ " ** @purpose  9:%1$s, TODO write purpose\n"
			+ " ** @verdict  pass accept, ttcn3verdict:pass\n"
			+ " ***************************************************/\n"
			+ "module %2$s {\n"
			+ "\n"
			+ "    import from schema_%2$s language \"XSD\" all;\n"
			+ "    // TODO specify type for the template\n"
			+ "    template __type__ m_msg := { };\n"
			+ "\n"
			+ "//#TC%3$s\n" 
			+"}\n";
	
	private static final String XSD_TEMPLATE = 
			"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
			+ "<schema xmlns=\"http://www.w3.org/2001/XMLSchema\"\n"
			+ "    targetNamespace=\"schema:%1$s\"\n" 
			+ "    xmlns:ns=\"schema:%1$s\">\n"
			+ "  <!-- TODO Generated Schema stub -->\n"
			+ "</schema>";

	private static final String XML_TEMPLATE = 
			"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
			+ "<!-- xmlns=\"schema:%1$s\" -->\n"
			+ "<!-- TODO Generated XML stub -->\n";

	/**
	 * Constructor for generic action.
	 */
	public NewTestCase(String kind) {
		super();
		this.tckind = kind;
	}

	/**
	 * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
	 */
	public void setActivePart(IAction action, IWorkbenchPart targetPart) {
		shell = targetPart.getSite().getShell();
	}

  public void run(IAction action) {
    createTestCase();
  }
  
  //this has to be called if this is executed as command because only as action the selection and
  //the shell are updated automatically
  public void runAsCommand() {
    IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
    if (window != null) {
      shell = window.getShell();
      selection = window.getSelectionService().getSelection();
    }
    createTestCase();
  }
  
	/**
	 * @see IActionDelegate#run(IAction)
	 */
	private void createTestCase() {
        if (selection == null) {
        	MessageDialog.openError(shell, "New test case", "Unsupported explorer view or no selection");
        	return;
        }

        TreePath[] paths = ((TreeSelection) selection).getPaths();
        TreePath p = paths[0];
        IFolder folder = (IFolder) p.getLastSegment();
        String name = guessTCName(folder);
        if (name == null) {
    		MessageDialog.openInformation(
    				shell,
    				"NewTestCase",
    				"New Action was executed, but the folder is full");
    		return;
        } 
		
		createFiles(folder, name);		
		
	}

	private boolean createFiles(IFolder folder, String name) {
		IFolder tcfolder = folder.getFolder(name);
		NullProgressMonitor pm = new NullProgressMonitor();
		String section = getSectionString(folder.getName());
		try{
			pm.beginTask("New test case", 4);
			tcfolder.create(true, true, new NullProgressMonitor());
			pm.worked(1);
			String tcMacroSuffix = "Neg".equals(tckind) ? "_Neg" : "";
			// TODO get section number
			String ttcn_content = String.format(TTCN_TEMPLATE, section, name, tcMacroSuffix);
			String xsd_content = String.format(XSD_TEMPLATE, name);
			String xml_content = String.format(XML_TEMPLATE, name);
			
			if (pm.isCanceled()) return false;
			createFile(tcfolder, ".ttcn_", ttcn_content, pm);
			
			if (pm.isCanceled()) return false;
			createFile(tcfolder, ".xsd", xsd_content, pm);
			
			if (pm.isCanceled()) return false;
			createFile(tcfolder, ".xml", xml_content, pm);
		} catch (CoreException e) {
			MessageDialog.openError(shell, "New test case", "Failed to create a test case\n"+e.getLocalizedMessage());
			return false;
		} finally {
			pm.done();
		}
		return true;
	}

	private String getSectionString(String name) {
		Pattern regex = Pattern.compile("^([0-9]+)_");
		String section = "0.0.0.";
		Matcher matcher = regex.matcher(name);
		if (matcher.find()) {
			String rawSection = matcher.group(1);
			StringBuilder result = new StringBuilder();
			int start = 0, end = rawSection.length();
			for (; start < end; start += 2) {
				if (start > 0) result.append('.');
				char ch1 = rawSection.charAt(start);
				if (ch1 != '0') {
					result.append(ch1);
				}
				if (start + 1 < end) {
					result.append(rawSection.charAt(start+1));
				}
			}
			section = result.toString();
		}
		return section;
	}

	private String guessTCName(IFolder folder)
	{
		String nameBase = folder.getName();
        String name = null;
        
        for (int i = 1; i < 999; i++) {
        	name = String.format("%s_%s_%03d", this.tckind, nameBase, i);
        	if (null == folder.findMember(name)) return name;
        }
        return null;
	}
	
	private IFile createFile(IFolder tcfolder, String extension,
			String content, NullProgressMonitor pm)
			throws CoreException {
		IFile file = tcfolder.getFile(tcfolder.getName() + extension);
		
		file.create(new ByteArrayInputStream(content.getBytes()), true, pm);
		pm.worked(1);
		return file;
	}

	/**
	 * @see IActionDelegate#selectionChanged(IAction, ISelection)
	 */
	public void selectionChanged(IAction action, ISelection selection) {
		this.selection = selection;
	}

}
