/*
 *  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 org.apache.easyant4e.natures;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.easyant.core.descriptor.PropertyDescriptor;
import org.apache.easyant4e.Activator;
import org.apache.easyant4e.services.EasyantProjectService;
import org.apache.ivyde.eclipse.cpcontainer.IvyClasspathContainer;
import org.apache.ivyde.eclipse.cpcontainer.IvyClasspathUtil;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IProjectNature;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.launching.JavaRuntime;

import com.google.inject.Inject;

/**
 * The EastAnt nature.
 * 
 * @author <a href="mailto:jerome@benois.fr">Jerome Benois</a>
 */
public class EasyAntNature implements IProjectNature {

	public static final String NATURE_ID = "org.apache.easyant4e.EasyAntNature";

	public static final String BUILDER_ID = "org.apache.easyant4e.EasyAntBuilder";

	public EasyAntNature(){
		Activator.getEasyAntPlugin().injectMembers(this);
	}
	
	/**
	 * The project to which this project nature applies.
	 */
	private IProject project = null;
	
	private EasyantProjectService easyantProjectService;
	
	@Inject
	public void setEasyantProjectService(EasyantProjectService easyantProjectService){
		this.easyantProjectService = easyantProjectService;
	}
	

	public void configure() throws CoreException {
		//TODO maybe add an extension point to delegate this step for java, scala, ...
		//Configurer.configure(IProject, EasyAntModuleDescriptor);		
		//Add Java Nature
		//TODO add checkbox or list of configurer (reuse by skeleton) in import and new project wizard to add JavaNature, ScalaNature, GroovyNature ...
		//or use a dedicated eclipse plugin ?
		if (!project.hasNature(JavaCore.NATURE_ID)) {			
			IProjectDescription desc = project.getDescription();
			List<String> natures = new ArrayList<String>();
			natures.addAll(Arrays.asList(desc.getNatureIds()));
			natures.add(JavaCore.NATURE_ID);			
			desc.setNatureIds(natures.toArray(new String[natures.size()]));
			project.setDescription(desc, null);
		}
		
		if (project.hasNature(JavaCore.NATURE_ID)) {	
			IJavaProject javaProject = (IJavaProject)project.getNature(JavaCore.NATURE_ID);
			//flush classpath
			javaProject.setRawClasspath(new IClasspathEntry[0], null);						
			addSourceFolders(javaProject);
			addDefaultJREContainer(javaProject);
			addIvyClasspathContainer();
			addBuilder(BUILDER_ID);
		}
	}
	
	private void addIvyClasspathContainer() {
		/*
		IPath projectRelativePath = new Path("module.ivy");
		IJavaProject javaProject = JavaCore.create(project);
		IClasspathEntry newEntry = JavaCore.newContainerEntry(new Path(
        IvyClasspathContainer.CONTAINER_ID).append(projectRelativePath).append(confs));
		*/
		IJavaProject javaProject = JavaCore.create(project);    
	    //Configure project preferences
	    StringBuffer projectConf = new StringBuffer();
	    //TODO search *.ivy file
	    projectConf.append("?ivyXmlPath=module.ivy");
	    try {
	    	appendConfProp(projectConf, "confs", "*");
			appendConfProp(projectConf, "resolveInWorkspace", Boolean.TRUE.toString());
			String projectIvySettings = easyantProjectService.getProperty(javaProject.getProject(), "project.ivy.settings.url").getValue();
		    if(projectIvySettings==null){
		    	projectIvySettings = easyantProjectService.getProperty(javaProject.getProject(), "project.ivy.settings.file").getValue();
		    	if(projectIvySettings!=null){
		    		projectIvySettings = "file://"+resolveRelativePath(projectIvySettings);
		    	}
		    }
		    if(projectIvySettings!=null){
		    	appendConfProp(projectConf, "ivySettingsPath", projectIvySettings);
		    }
		} catch (UnsupportedEncodingException e) {
			Activator.getEasyAntPlugin().log(IStatus.ERROR, e.getMessage(), e);
		}
	    
	    // add the classpath entry
		IPath path = new Path(IvyClasspathContainer.CONTAINER_ID).append(projectConf.toString());
	    IClasspathEntry newEntry = JavaCore.newContainerEntry(path);
	    addClassPathEntry(javaProject, newEntry);
	}
	
	private String resolveRelativePath(String path){
		if(path!=null && path.startsWith(".")){
			String projectPath = project.getLocation().toPortableString();
			path= new File(projectPath+"/"+path).getAbsolutePath();
		}
		return path;
	}
	
	private void appendConfProp(StringBuffer path, String name, String value) throws UnsupportedEncodingException {
		 path.append('&');
		 path.append(name);
		 path.append('=');
		 path.append(URLEncoder.encode(value, "UTF-8"));
	}

	//FIXME with scala project or others
	private void addSourceFolders(IJavaProject javaProject)throws CoreException {		
		PropertyDescriptor srcMainJavaProp = easyantProjectService.getProperty(project, "src.main.java");
		String srcMainJava = removeBaseDirVar(srcMainJavaProp.getValue());
		PropertyDescriptor srcMainResourcesProp = easyantProjectService.getProperty(project, "src.main.resources");
		String srcMainResources = removeBaseDirVar(srcMainResourcesProp.getValue());
		PropertyDescriptor srcTestJavaProp = easyantProjectService.getProperty(project, "src.test.java");
		String srcTestJava = removeBaseDirVar(srcTestJavaProp.getValue());
		PropertyDescriptor srcTestResourcesProp = easyantProjectService.getProperty(project, "src.test.resources");
		String srcTestResources = removeBaseDirVar(srcTestResourcesProp.getValue());
		addSourceFolders(javaProject, srcMainJava,srcMainResources, srcTestJava, srcTestResources);
	}
	
	private String removeBaseDirVar(String s){
		String baseDirVar = "${basedir}";
		if(s!=null && s.contains(baseDirVar)){
			return s.substring(s.indexOf(baseDirVar)+baseDirVar.length()+1);
		}else{
			return s;
		}
	}
	
	public void deconfigure() throws CoreException {
		if (project.hasNature(JavaCore.NATURE_ID)) {	
			removeBuilder(BUILDER_ID);
			removeIvyClasspathContainer();
		}
	}

	public IProject getProject() {
		return project;
	}

	public void setProject(IProject project) {
		this.project = project;

	}
	
	private void addDefaultJREContainer(IJavaProject javaProject) throws JavaModelException{		
		List<IClasspathEntry> entries = new ArrayList<IClasspathEntry>();
		entries.addAll(Arrays.asList(javaProject.getRawClasspath()));
		entries.add(JavaRuntime.getDefaultJREContainerEntry());
		javaProject.setRawClasspath(entries.toArray(new IClasspathEntry[entries.size()]), null);

	}
	
	private void addSourceFolders(IJavaProject javaProject, String...path) throws JavaModelException{		
		List<IClasspathEntry> entries = new ArrayList<IClasspathEntry>();
		entries.addAll(Arrays.asList(javaProject.getRawClasspath()));
		IResource outputLocation = javaProject.getProject().findMember("target");
		if(outputLocation==null){
			outputLocation = createSourceFolder(javaProject.getProject(), "target");
		}
		javaProject.setOutputLocation(outputLocation.getFullPath(), null);
		for(String p : path){	
			IResource sourceFolder = javaProject.getProject().findMember(p);
			if(sourceFolder==null){
				sourceFolder = createSourceFolder(javaProject.getProject(), p);
			}
			if(sourceFolder!=null){
				IPath[] exclusionPatterns = new IPath[] { outputLocation.getFullPath() };
				IClasspathEntry srcEntry = JavaCore.newSourceEntry(sourceFolder.getFullPath(),exclusionPatterns, outputLocation.getFullPath());				
				entries.add(srcEntry);
			}
		}
		javaProject.setRawClasspath(entries.toArray(new IClasspathEntry[entries.size()]), null);
	}
	
	 private IResource createSourceFolder( IProject project, String sourcefolder ){
	        IPath path = new Path(sourcefolder);
	        IContainer container = project;
	        try {
	            for (int i = 1; i <= path.segmentCount(); i++) {
	                IFolder newSourceFolder = project.getFolder( path.uptoSegment( i ) );
	                if (!newSourceFolder.exists()) {
	                	newSourceFolder.create( true, true, null );
	                }
	                container = newSourceFolder;
	            }
	            return container;
	        } catch (CoreException e) {
	            Activator.getEasyAntPlugin().log(e);
	            return null;
	        }
	    }
	
	private void addClassPathEntry(IJavaProject javaProject, IClasspathEntry newEntry){
		try {
        	IClasspathEntry[] entries = javaProject.getRawClasspath();
            List newEntries = new ArrayList(Arrays.asList(entries));
            newEntries.add(newEntry);
            entries = (IClasspathEntry[]) newEntries.toArray(new IClasspathEntry[newEntries.size()]);

            javaProject.setRawClasspath(entries, javaProject.getOutputLocation(), null);
        } catch (CoreException e) {
            // unless there are issues with the JDT, this should never happen
            Activator.getEasyAntPlugin().log(IStatus.ERROR, "Cannot add ClassPath entry", e);
        }
	}
	
	private void removeIvyClasspathContainer() {
		IJavaProject javaProject = JavaCore.create(project);
		ArrayList<IClasspathEntry> newEntries = new ArrayList<IClasspathEntry>();
		//FIXME call IvyDE command
		try {
			IClasspathEntry[] entries = javaProject.getRawClasspath();
			for (int i = 0; i < entries.length; i++) {
				IClasspathEntry entry = entries[i];
				if (entry != null && entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
					IPath path = entry.getPath();
					if (IvyClasspathUtil.isIvyClasspathContainer(path)) {
						continue;
					}
				}
				newEntries.add(entry);
			}
			// TODO add progress monitor
			IClasspathEntry[] newClasspathEntries = newEntries.toArray(new IClasspathEntry[newEntries.size()]);
			javaProject.setRawClasspath(newClasspathEntries, null);
		} catch (JavaModelException e) {
			Activator.getEasyAntPlugin().log(IStatus.ERROR, "Cannot remove Ivy ClassPath container", e);
		}
	}

	private void addBuilder(String builderID) throws CoreException {
		if (!isBuilderApplied(builderID)) {
			IProjectDescription description = getProject().getDescription();
			ICommand[] commands = description.getBuildSpec();
			ICommand command = description.newCommand();
			command.setBuilderName(builderID);
			ICommand[] newCommands = new ICommand[commands.length + 1];
			System.arraycopy(commands, 0, newCommands, 0, commands.length);
			newCommands[commands.length] = command;
			description.setBuildSpec(newCommands);
			getProject().setDescription(description, null);
		}
	}

	private void removeBuilder(String builderID) throws CoreException {
		if (isBuilderApplied(builderID)) {
			IProjectDescription description = getProject().getDescription();
			ICommand[] commands = description.getBuildSpec();
			ICommand[] newCommands = new ICommand[commands.length - 1];
			int i = 0;
			for (ICommand command : commands) {
				if (command.getBuilderName().equals(builderID)) {
					// Remove the given builder
				} else {
					newCommands[i] = command;
					i++;
				}
			}
			description.setBuildSpec(newCommands);
			getProject().setDescription(description, null);
		}
	}

	private boolean isBuilderApplied(String builderID) throws CoreException {
		IProjectDescription description = getProject().getDescription();
		for (ICommand cmd : description.getBuildSpec()) {
			if (cmd.getBuilderName().equals(builderID)) {
				return true;
			}
		}
		return false;
	}

}
