/*******************************************************************************
 * Copyright 2000-2014 JetBrains s.r.o.
 *
 * Licensed 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 org.jetbrains.kotlin.core.launch;

import java.io.IOException;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.IStatusHandler;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jdt.launching.JavaLaunchDelegate;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.kotlin.core.Activator;
import org.jetbrains.kotlin.core.builder.KotlinPsiManager;
import org.jetbrains.kotlin.core.compiler.KotlinCompiler;
import org.jetbrains.kotlin.core.compiler.KotlinCompiler.KotlinCompilerResult;
import org.jetbrains.kotlin.core.log.KotlinLogger;
import org.jetbrains.kotlin.core.utils.ProjectUtils;

public class KotlinLaunchDelegate extends JavaLaunchDelegate {
    
    public final static String KT_JDK_ANNOTATIONS_PATH = ProjectUtils.buildLibPath("kotlin-jdk-annotations");
    
    @Override
    public boolean buildForLaunch(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor)
            throws CoreException {
        List<IFile> projectFiles = KotlinPsiManager.INSTANCE.getFilesByProject(getJavaProjectName(configuration));
        
        try {
            IJavaProject javaProject = getJavaProject(configuration);
            KotlinCompilerResult compilerResult = KotlinCompiler.INSTANCE.compileKotlinFiles(
                    projectFiles, 
                    javaProject, 
                    ProjectUtils.getOutputFolder(javaProject).getFullPath().toOSString());
            
            if (!compilerResult.compiledCorrectly()) {
                IStatus status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, 1, "", null);
                IStatusHandler handler = DebugPlugin.getDefault().getStatusHandler(status);
                
                if (handler != null) {
                    handler.handleStatus(status, compilerResult.getCompilerOutput());
                }
                
                abort("Build failed", null, 0);
            }
        } catch (InterruptedException | IOException e) {
            abort("Build error", null, 0);
        }
        
        return super.buildForLaunch(configuration, mode, monitor);
    }
    
    @NotNull
    @Override
    public String getJavaProjectName(ILaunchConfiguration configuration) throws CoreException {
        String result = super.getJavaProjectName(configuration);
        
        if (result != null) {
            return result;
        } else {
            abort("Project name is invalid: " + result, null, IJavaLaunchConfigurationConstants.ERR_UNSPECIFIED_PROJECT);
        }
        
        throw new IllegalStateException();
    }
    
    @Override
    public String[] getClasspath(ILaunchConfiguration configuration) throws CoreException {
        String[] oldClasspath = super.getClasspath(configuration);
        String[] newClasspath = new String[oldClasspath.length + 1];
        System.arraycopy(oldClasspath, 0, newClasspath, 0, oldClasspath.length);
        
        newClasspath[oldClasspath.length] = KT_JDK_ANNOTATIONS_PATH;
        
        return newClasspath;
    }
    
    @NotNull
    @Override
    public String verifyMainTypeName(ILaunchConfiguration configuration) throws CoreException {
        try {
            return getPackageClassName(configuration).toString();
        } catch (IllegalArgumentException e) {
            abort("File with main method not defined", null, IJavaLaunchConfigurationConstants.ERR_UNSPECIFIED_MAIN_TYPE);
        }
        
        throw new IllegalStateException();
    }
    
    @NotNull
    @Override
    public String getMainTypeName(ILaunchConfiguration configuration) throws CoreException {
        String result = super.getMainTypeName(configuration);
        
        if (result != null) {
            return result;
        } else {
            abort("Main type name is null", null, 0);
        }
        
        throw new IllegalStateException();
    }
    
    @NotNull
    private FqName getPackageClassName(ILaunchConfiguration configuration) {
        try {
            FqName mainClassName = new FqName(getMainTypeName(configuration));
            for (IFile file : KotlinPsiManager.INSTANCE.getFilesByProject(getJavaProjectName(configuration))) {
                if (ProjectUtils.hasMain(file) && ProjectUtils.createPackageClassName(file).equalsTo(mainClassName)) {
                    return mainClassName;
                }
            }
        } catch (CoreException e) {
            KotlinLogger.logError(e);
        }
        
        throw new IllegalArgumentException();
    }
}
@@ -827,31 +827,8 @@
 ion;
-%0Aimport java.util.List;
 %0A%0Aim
@@ -2131,132 +2131,8 @@
 n %7B%0A
-        List%3CIFile%3E projectFiles = KotlinPsiManager.INSTANCE.getFilesByProject(getJavaProjectName(configuration));%0A        %0A
     
@@ -2329,20 +2329,77 @@
     
-projectFiles
+KotlinPsiManager.INSTANCE.getFilesByProject(javaProject.getProject())
 , %0A 
@@ -2500,16 +2500,16 @@
 .get
-FullPath
+Location
 ().t
@@ -3246,30 +3246,36 @@
 %0A    public 
-String
+IJavaProject
  getJavaProj
@@ -3277,20 +3277,16 @@
 aProject
-Name
 (ILaunch
@@ -3341,36 +3341,47 @@
 n %7B%0A        
-String resul
+IJavaProject javaProjec
 t = super.ge
@@ -3384,36 +3384,32 @@
 r.getJavaProject
-Name
 (configuration);
@@ -3422,37 +3422,42 @@
    %0A        if (
-resul
+javaProjec
 t != null) %7B%0A   
@@ -3464,37 +3464,42 @@
          return 
-resul
+javaProjec
 t;%0A        %7D els
@@ -3521,24 +3521,28 @@
  abort(%22
+Java
 Project 
 name is 
@@ -3537,35 +3537,16 @@
 ect 
-name is invalid: %22 + result
+is null%22
 , nu
@@ -5241,20 +5241,16 @@
 aProject
-Name
 (configu
@@ -5256,16 +5256,29 @@
 uration)
+.getProject()
 )) %7B%0A   

use more abstract object then String