/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */
package com.redhat.ceylon.eclipse.core.cpcontainer;

import static com.redhat.ceylon.eclipse.imp.builder.CeylonBuilder.getJdtClassesEnabled;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.LinkedHashSet;

import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.JavaCore;

import com.redhat.ceylon.compiler.typechecker.TypeChecker;
import com.redhat.ceylon.compiler.typechecker.context.PhasedUnits;
import com.redhat.ceylon.eclipse.core.model.loader.model.JDTModuleManager;
import com.redhat.ceylon.eclipse.imp.builder.CeylonBuilder;
import com.redhat.ceylon.eclipse.ui.CeylonPlugin;

/**
 * Eclipse classpath container that will contain the ceylon resolved entries.
 */
public class CeylonResolveJob extends Job {

    private final CeylonClasspathContainer container;
    private IStatus status;
    
    private void setStatus(IStatus status) {
        this.status = status;
    }

    public CeylonResolveJob(CeylonClasspathContainer container) {
        super("Ceylon resolve job for project " + container.getJavaProject().getElementName());
        this.container = container;
    }

    protected IStatus run(IProgressMonitor monitor) {
        try {
            final Collection<IClasspathEntry> paths = new LinkedHashSet<IClasspathEntry>();
            final IWorkspace workspace = ResourcesPlugin.getWorkspace();
            final IWorkspaceRunnable buildJob = new IWorkspaceRunnable() {
            	//The following code requires a lock on the workspace to
            	//avoid concurrent access to the model
                @Override
                public void run(IProgressMonitor monitor) {
                    try {
                        CeylonBuilder.parseCeylonModel(container.getJavaProject().getProject(), monitor);
                        IProject project = container.getJavaProject().getProject();
                        final TypeChecker typeChecker = CeylonBuilder.getProjectTypeChecker(project);
                        if (typeChecker != null) {
                            final PhasedUnits phasedUnits = typeChecker.getPhasedUnits();
                            final JDTModuleManager moduleManager = (JDTModuleManager) phasedUnits.getModuleManager();
                            for (File archive : moduleManager.getClasspath()) {
                                if (archive.exists()) {
                                    Path classpathArtifact = new Path(archive.getCanonicalPath());
                                    IPath srcArtifact = classpathArtifact.removeFileExtension().addFileExtension("src");
                                    paths.add(JavaCore.newLibraryEntry(classpathArtifact, srcArtifact, null));
                                }
                            }
                            if (getJdtClassesEnabled(project)) {
                            	IFolder outputFolder = project.getFolder("JDTClasses");
                            	IPath ceylonOutputDirectory = outputFolder.getFullPath();
                            	IPath ceylonSourceDirectory = project.getFolder("source").getFullPath();
                            	paths.add(JavaCore.newLibraryEntry(ceylonOutputDirectory, ceylonSourceDirectory, null, true));
                            }
                            setStatus(Status.OK_STATUS);
                        }
                        else {
                            setStatus(new Status(IStatus.ERROR, CeylonPlugin.PLUGIN_ID, "Job '" + getName() + "' failed"));
                        }
                    } catch (CoreException e) {
                        setStatus(new Status(IStatus.ERROR, CeylonPlugin.PLUGIN_ID, "Job '" + getName() + "' failed", e));
                    } catch (IOException e) {
                        setStatus(new Status(IStatus.ERROR, CeylonPlugin.PLUGIN_ID, "Job '" + getName() + "' failed", e));
                    }
                }
            };
            try {
                workspace.run(buildJob, monitor);
            } catch (CoreException e) {
                setStatus(new Status(IStatus.ERROR, CeylonPlugin.PLUGIN_ID, "Job '" + getName() + "' failed", e));
            }
                        
            if (status == Status.OK_STATUS) {
                container.updateClasspathEntries(paths.toArray(new IClasspathEntry[paths.size()]));
            }
            setResolveStatus(status);
            return status;
        } finally {
            container.resetJob();
            CeylonPlugin.log(IStatus.INFO, "resolved dependencies of project " + container.getJavaProject().getElementName(), null);
        }
    }

    private void setResolveStatus(IStatus status) {
        if (FakeProjectManager.isFake(container.getJavaProject())) {
            return;
        }
        try {
            if (status == Status.OK_STATUS) {
                return;
            }
        } catch (Exception e) {
            CeylonPlugin.log(e);
        }
    }

}

@@ -950,16 +950,87 @@
 Enabled;
+%0Aimport static org.eclipse.core.resources.ResourcesPlugin.getWorkspace;
 %0A%0Aimport
@@ -1225,54 +1225,8 @@
 ct;%0A
-import org.eclipse.core.resources.IWorkspace;%0A
 impo
@@ -1279,59 +1279,8 @@
 le;%0A
-import org.eclipse.core.resources.ResourcesPlugin;%0A
 impo
@@ -2637,81 +2637,8 @@
 ();%0A
-            final IWorkspace workspace = ResourcesPlugin.getWorkspace();%0A
     
@@ -4509,32 +4509,202 @@
               %7D%0A
+                            %0A                            container.updateClasspathEntries(paths.toArray(new IClasspathEntry%5Bpaths.size()%5D));%0A                            %0A
                 
@@ -5380,25 +5380,28 @@
         
-w
+getW
 orkspace
 .run(bui
@@ -5392,16 +5392,18 @@
 orkspace
+()
 .run(bui
@@ -5617,168 +5617,8 @@
    %0A
-            if (status == Status.OK_STATUS) %7B%0A                container.updateClasspathEntries(paths.toArray(new IClasspathEntry%5Bpaths.size()%5D));%0A            %7D%0A
     
@@ -5651,16 +5651,29 @@
 tatus);%0A
+            %0A
         

update the classpath inside the lock