package org.eclipse.stp.sc.common.utils;

import java.io.IOException;
import java.net.URL;
import java.util.StringTokenizer;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceDescription;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.stp.common.logging.LoggingProxy;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.ide.IDE;


public class WorkbenchUtils {

    private static final LoggingProxy LOG = LoggingProxy.getlogger(WorkbenchUtils.class);

    public static Button getDialogButton(Dialog aDialog, String buttonLabel) {
        return getButtonInComposite((Composite)aDialog.buttonBar, buttonLabel);
    }

    public static Button getButtonInComposite(Composite composite, String expectedText) {
        return (Button)getControlInComposite(composite, Button.class.getName(),
            expectedText);
    }

    public static Label getLabelInComposite(Composite composite, String expectedText) {
        return (Label)getControlInComposite(composite, Label.class.getName(),
            expectedText);
    }

    public static Text getTextInComposite(Composite composite, String expectedText) {
        return (Text)getControlInComposite(composite, Text.class.getName(),
            expectedText);
    }

    public static Control getControlInComposite(Composite composite, String className, String expectedText) {
        Control control = null;
        Control[] children = composite.getChildren();
    
        for (int i = 0; i < children.length; i++) {
            Control child = children[i];
    
            if (child instanceof Composite) {
                control = getControlInComposite((Composite)child, className,
                        expectedText);
            } else {
                control = getMatchingTextControl(child, expectedText);
            }
    
            if ((control != null)
                    && control.getClass().getName().equals(className)) {
                //                LOG.debug("Found control with text matching " + expectedText 
                //                                + " in composite " + composite.getClass().getName());
                return control;
            }
        }
    
        //        LOG.debug("Could not find control with text matching " + expectedText 
        //                        + " in composite " + composite.getClass().getName());
        return null;
    }

    private static Control getMatchingTextControl(Control control, String expectedText) {
        String controlText = getControlText(control);
    
        if (isMatchingText(controlText, expectedText)) {
            //            LOG.debug("Found " + control.getClass().getName() + " with text " + controlText
            //                            + " matching " + expectedText);
            return control;
        }
    
        return null;
    }

    public static String getControlText(Control control) {
        if (control instanceof Label) {
            return ((Label)control).getText();
        }
    
        if (control instanceof Button) {
            return ((Button)control).getText();
        }
    
        if (control instanceof Text) {
            return ((Text)control).getText();
        }
    
        return null;
    }

    private static boolean isMatchingText(String currentText, String expectedText) {
        return (currentText != null)
            && (currentText.indexOf(expectedText) != -1);
    }

    public static boolean compareArrays(Object[] arrayOne, Object[] arrayTwo) {
        if ((arrayOne == null) && (arrayTwo != null)) {
            return false;
        }
    
        if ((arrayTwo == null) && (arrayOne != null)) {
            return false;
        }
    
        if ((arrayOne == null) && (arrayTwo == null)) {
            return true;
        }
    
        if (arrayOne.length != arrayTwo.length) {
            return false;
        }
    
        for (int i = 0; i < arrayOne.length; i++) {
            if (!compareObjects(arrayOne[i], arrayTwo[i])) {
                return false;
            }
        }
    
        return true;
    }

    public static boolean compareObjects(Object one, Object two) {
        if ((one == null) && (two != null)) {
            return false;
        }
    
        if ((two == null) && (one != null)) {
            return false;
        }
    
        if ((one == null) && (two == null)) {
            return true;
        }
    
        return one.equals(two);
    }

    /**
     * add a file resource to the project selected and populate it with the content
     * @param project
     * @param localFileName
     * @param resourcePath
     * @return
     * @throws CoreException
     * @throws IOException
     */
    public static IFile addFileResourceToTestProject(IProject project, String localFileName, Class testClass, String resourcePath) throws CoreException, IOException {
        checkFolder(project, localFileName);
        IFile newFile = project.getFile(localFileName);
    
        if (!newFile.exists()) {
            //            LOG.debug((new Object()).getClass().getResource(resourcePath));
            URL resourceWsdl = testClass.getResource(resourcePath);
            newFile.create(resourceWsdl.openStream(), true, null);
        }
    
        return newFile;
    }

    /**
     * create a Celtix project resource on which to base our tests
     * @param projectName
     * @return
     * @throws CoreException
     */
    public static IProject createTestCeltixProject(String projectName) {
        IProject newProject = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
    
        if (!newProject.exists()) {
            newProject = createProject(projectName, null);
        } else {
            try {
                newProject.open(null);
            } catch (Exception e) {
                LOG.error("", e);
                return null;
            }
        }
    
        return newProject;
    }

    /**
     * create a Celtix project
     * @param projectName
     * @param locationPath
     * @return
     */
    public static IProject createProject(String projectName, IPath locationPath) {
        try {
            IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
            IProject theProject = root.getProject(projectName);
            IProjectDescription description = 
                ResourcesPlugin.getWorkspace().newProjectDescription(theProject.getName());
    
            if ((locationPath != null)
                    && !Platform.getLocation().equals(locationPath)) {
                description.setLocation(locationPath);
            }
    
            theProject.create(description, null);
            theProject.open(null);
    
            theProject.setDescription(description, null);
    
            return theProject;
        } catch (Exception e) {
            return null;
        }
    }

    public static IEditorPart openEditor(IWorkbenchWindow window, IFile file) {
        return openEditor(window, file, null);
    }

    public static IEditorPart openEditor(IWorkbenchWindow window, IFile file, String editorId) {
        IEditorPart editor = null;
        IWorkbenchPage page = window.getActivePage();
    
        try {
            if (page != null) {
                if (editorId != null) {
                    editor = IDE.openEditor(page, file, editorId, true);
                } else {
                    editor = IDE.openEditor(page, file, true);
                }
            }
        } catch (PartInitException e) {
            LOG.error("", e);
        }
    
        return editor;
    }

    public static void setWorkspaceAutoBuild(boolean autoBuild) throws CoreException {
        IWorkspace ws = ResourcesPlugin.getWorkspace();
        IWorkspaceDescription desc = ws.getDescription();
        desc.setAutoBuilding(autoBuild);
        ws.setDescription(desc);
    }

    public static void setupBasicJavaProject(IProject project) throws Exception {
        if (!project.hasNature(JavaCore.NATURE_ID)) {
            IProjectDescription description = project.getDescription();
            String[] natures = description.getNatureIds();
            String[] newNatures = new String[natures.length + 1];
            System.arraycopy(natures, 0, newNatures, 0, natures.length);
            newNatures[natures.length] = JavaCore.NATURE_ID;
            description.setNatureIds(newNatures);
            project.setDescription(description, IResource.FORCE, null);

            IJavaProject javaProj = JavaCore.create(project);

            // IClasspathEntry jreEntry = JavaRuntime.getJREVariableEntry();
            IClasspathEntry jreEntry = JavaRuntime
                    .getDefaultJREContainerEntry();
            IFolder srcFolder = project.getFolder("src");
            if (!srcFolder.exists()) {
                srcFolder.create(false, true, null);
            }
            IClasspathEntry srcEntry = JavaCore.newSourceEntry(srcFolder
                    .getFullPath());

            IClasspathEntry[] newEntries = new IClasspathEntry[2];
            newEntries[0] = jreEntry;
            newEntries[1] = srcEntry;
            javaProj.setRawClasspath(newEntries, null);

            javaProj.save(null, true);

            // disable autobuild
        }
    }
    
    public static void checkFolder(IProject project, String path) throws CoreException {
        StringTokenizer token = new StringTokenizer(path, "/");
        int numOfToken = token.countTokens();

        if (numOfToken <= 1) {
            return;
        }

        IFolder folder = null;

        for (int i = 0; i < (numOfToken - 1); i++) {
            String onePath = (String)token.nextElement();
            IFolder childFolder;

            if (folder == null) {
                childFolder = project.getFolder(onePath);
            } else {
                childFolder = folder.getFolder(onePath);
            }

            if (!childFolder.exists()) {
                childFolder.create(true, false, null);
            }

            folder = childFolder;
        }
    }
    
    public WorkbenchUtils() {
        super();
    }

}