package com.irt.ingequip.fiacre.simulator.popup.actions;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import org.eclipse.core.resources.IFile;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.resource.EObjectAtOffsetHelper;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.ui.editor.IURIEditorOpener;
import org.eclipse.xtext.ui.editor.XtextEditor;
import org.eclipse.xtext.ui.editor.model.XtextDocument;
import org.eclipse.xtext.ui.editor.utils.EditorUtils;
import org.eclipse.xtext.ui.resource.XtextResourceSetProvider;
//import org.xtext.example.mydsl.ui.internal.MyDslActivator;
import org.eclipse.xtext.util.TextRegion;
import org.eclipse.xtext.validation.AbstractDeclarativeValidator;
import org.eclipse.xtext.validation.AbstractDeclarativeValidator.StateAccess;
import org.eclipse.xtext.validation.ValidationMessageAcceptor;

import com.google.inject.Injector;

import fr.irit.fiacre.xtext.fiacre.BlockStatement;
import fr.irit.fiacre.xtext.fiacre.CaseStatement;
import fr.irit.fiacre.xtext.fiacre.ConditionalStatement;
import fr.irit.fiacre.xtext.fiacre.ExtendedConditionalStatement;
import fr.irit.fiacre.xtext.fiacre.ForeachStatement;
import fr.irit.fiacre.xtext.fiacre.SelectStatement;
import fr.irit.fiacre.xtext.fiacre.Statement;
import fr.irit.fiacre.xtext.fiacre.StatementChoice;
import fr.irit.fiacre.xtext.fiacre.StatementSequence;
import fr.irit.fiacre.xtext.fiacre.UnlessStatement;
import fr.irit.fiacre.xtext.fiacre.WhileStatement;
import fr.irit.fiacre.xtext.ui.internal.FiacreActivator;
import fr.irit.fiacre.xtext.validation.FiacreValidator;

public class Simulate implements IObjectActionDelegate {

	private Shell shell;
	// added selection attribute
	private ISelection selection;

	/**
	 * Constructor for Action1.
	 */
	public Simulate() {
		super();
	}

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

	/**
	 * @see IActionDelegate#run(IAction)
	 */
	public void run(IAction action) {
		IFile file = getFile();
		Injector injector = FiacreActivator.getInstance().getInjector("fr.irit.fiacre.xtext.Fiacre"); 
		XtextResourceSetProvider provider = injector.getInstance(XtextResourceSetProvider.class);
		ResourceSet resourceSet = provider.get(file.getProject());

		URI xtextURI = URI.createPlatformResourceURI(file.getFullPath().toString(), true);

		XtextResource xtextResource = (XtextResource) resourceSet.getResource(xtextURI, true);

		System.out.println("resource" + xtextResource);

		IURIEditorOpener editorOpener = injector.getInstance(IURIEditorOpener.class);
		final XtextEditor xtextEditor = (XtextEditor) editorOpener.open(xtextURI, true);
		System.out.println("editor 2" + xtextEditor);
		XtextDocument xtextDocument = (XtextDocument) xtextEditor.getDocument();
		System.out.println("document " + xtextDocument);
		for (int i = 0; i < xtextDocument.getNumberOfLines(); i++) {
			try {
				System.out.println("getLineLength " + i + " " + xtextDocument.getLineLength(i));
				System.out.println("getLineOffset " + i + " " + xtextDocument.getLineOffset(i));
			} catch (BadLocationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		EObjectAtOffsetHelper eObjectAtOffsetHelper = injector.getInstance(EObjectAtOffsetHelper.class);
		for (int i = 0; i < xtextDocument.getLength(); i++) {
			try {
				EObject object = eObjectAtOffsetHelper.resolveElementAt(xtextResource, i);
				EObject object2 = eObjectAtOffsetHelper.resolveContainedElementAt(xtextResource, i);
				EObject object3 = eObjectAtOffsetHelper.resolveCrossReferencedElementAt(xtextResource, i);
				INode object4 = eObjectAtOffsetHelper.getCrossReferenceNode(xtextResource, new TextRegion(i, 1));
				
				int line = xtextDocument.getLineOfOffset(i);
				int column = (i - xtextDocument.getLineOffset(xtextDocument.getLineOfOffset(i)));

				System.out.println("----- ");
				System.out.print("o " + i);
				System.out.print(" (l " + line + " ");
				System.out.print("c " + column + ") ");
				System.out.print("(el = " + (line + 1) + ", ");
				System.out.print("ec = " + (column + 1) + ") ");
				System.out.println("calculated offset " + getOffset(xtextDocument, line , column));
				System.out.println("object " + object);
				System.out.println("cross " + object3);
				System.out.println("contained " + object2);
				System.out.println("containerStatement " + getStatement(object2));
				System.out.println("object4 " + object4);
				
			} catch (BadLocationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		FiacreValidator validator = injector.getInstance(FiacreValidator.class);
		System.out.println("validator " + validator);
		System.out.println("getmsgacceptor " + validator.getMessageAcceptor() + this);
		
//		StateAccess access = new StateAccess((AbstractDeclarativeValidator) validator.getMessageAcceptor());
//		validator.getMessageAcceptor().acceptError("Assigning any value not allowed in a function ",eObjectAtOffsetHelper.resolveElementAt(xtextResource, 14773),null,ValidationMessageAcceptor.INSIGNIFICANT_INDEX, null);
//		validator.state.get().hasErrors = true;
		// try {
		// BufferedReader bufferRead = new BufferedReader(new
		// InputStreamReader(System.in));
		// String s = bufferRead.readLine();
		// int x = Integer.parseInt(s);
		// String r = bufferRead.readLine();
		// int y = Integer.parseInt(r);
		//
		// //EObjectAtOffsetHelper eObjectAtOffsetHelper = new
		// EObjectAtOffsetHelper();
		// EObject object3 =
		// eObjectAtOffsetHelper.resolveElementAt(xtextResource,
		// getOffset(xtextDocument, x, y));
		// System.out.println("object3 " + object3);
		// try {
		// System.out.println("line of offset " +
		// xtextDocument.getLineOfOffset(getOffset(xtextDocument, x, y)));
		// } catch (BadLocationException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// }
		//
		//
		// } catch (IOException e) {
		// e.printStackTrace();
		// }
	}

	// added getFile() method
	private IFile getFile() {
		return (IFile) ((IStructuredSelection) selection).getFirstElement();
	}

	/**
	 * @see IActionDelegate#selectionChanged(IAction, ISelection)
	 */
	public void selectionChanged(IAction action, ISelection selection) {
		// Don't forget this line.
		// It is the most important line.
		this.selection = selection;
	}

	public int getOffset(XtextDocument xtextDocument, int x, int y) {
		int offset = 0;

		for (int i = 0; i < x; i++) {
			try {
				offset += xtextDocument.getLineLength(i);
			} catch (BadLocationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		offset += y;
		System.out.println("offset" + offset);
		return offset;

	}

	public EObject eContainer(EObject root, Class<?> type) {
		EObject current = root;
		while (current != null) {
			if (type.isInstance(current)) {
				return current;
			} else {
				current = current.eContainer();
			}
		}
		return null;
	}

	public EObject eContainerStatement(EObject root) {
		EObject current = root;
		while (current != null) {
			if (StatementSequence.class.isInstance(current.eContainer())) {
				return current;
			} else {
				current = current.eContainer();
			}
		}
		return null;
	}

	public EObject getStatement(EObject root) {
		EObject current = root;
		while (current != null) {
			if (!(isAtomicStatement(current.eContainer()))) {
				return current;
			} else {
				current = current.eContainer();
			}
		}
		return null;
	}

	public boolean isAtomicStatement(EObject root) {
		if (eContainer(root, Statement.class) != null) {
			if (UnlessStatement.class.isInstance(root) || StatementChoice.class.isInstance(root)
					|| StatementSequence.class.isInstance(root) || ConditionalStatement.class.isInstance(root)
					|| ExtendedConditionalStatement.class.isInstance(root) || SelectStatement.class.isInstance(root)
					|| WhileStatement.class.isInstance(root) || ForeachStatement.class.isInstance(root)
					|| CaseStatement.class.isInstance(root) || BlockStatement.class.isInstance(root)
			) {
				return false;
			} else {
				return true;
			}

		} else {
			return false;
		}

	}

}
