/*
 *  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.
 */
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;
	}

}
