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

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Vector;

import org.apache.easyant.core.EasyAntConfiguration;
import org.apache.easyant.core.EasyAntEngine;
import org.apache.easyant.core.EasyAntMagicNames;
import org.apache.easyant.core.descriptor.EasyAntModuleDescriptor;
import org.apache.easyant.core.descriptor.PropertyDescriptor;
import org.apache.easyant.core.factory.EasyantConfigurationFactory;
import org.apache.easyant.core.report.EasyAntReport;
import org.apache.easyant.core.report.PhaseReport;
import org.apache.easyant.core.report.TargetReport;
import org.apache.easyant4e.Activator;
import org.apache.easyant4e.EasyAntConstants;
import org.apache.easyant4e.EasyAntPlugin;
import org.apache.easyant4e.console.EasyAntConsole;
import org.apache.easyant4e.natures.AddEasyAntNatureOperation;
import org.apache.easyant4e.natures.EasyAntNature;
import org.apache.easyant4e.natures.RemoveEasyAntNatureOperation;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IFile;
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.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.IOverwriteQuery;
import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider;
import org.eclipse.ui.wizards.datatransfer.ImportOperation;

import com.google.inject.Inject;

/**
 * 
 * @author <a href="mailto:jerome@benois.fr">Jerome Benois</a>
 */
public class EasyantProjectServiceImpl implements EasyantProjectService{

	private EasyAntConsole console;
	
	private EasyantCoreService easyantCoreService;
	
	private EasyAntEngine easyAntEngine;
	
	@Inject
	public void setEasyAntEngine(EasyAntEngine easyAntEngine){
		this.easyAntEngine = easyAntEngine;
	}

	@Inject
	public void setEasyantCoreService(EasyantCoreService easyantCoreService) {
		this.easyantCoreService = easyantCoreService;
	}

	@Inject 
	public void setEasyAntConsole(EasyAntConsole console) {
		this.console = console;
	}

/*	
	public Ivy getIvyInstance(IProject project) {
		//TODO read workspace and project preference to load good Ivy instance must be used by the given project
		return easyantCoreService.getIvyInstance(project);// by default return the ivy instance used by Easyant core
	}
*/
	public void runBuild(IProject project, String buildTaskName, int logLevel, IProgressMonitor monitor) {
		console.show();
		console.info("\n");
		console.info(project.getName() + "$ easyant " + buildTaskName+"\n");
		
		IFile ivyFile = project.getFile("module.ivy");
		String ivyFilePath = ivyFile.getLocation().toOSString();
		File buildModule = new File(ivyFilePath);
		
		URL easyantIvySettingsUrl = Activator.getDefault().getBundle().getResource(EasyAntConstants.PLUGINS_SETTINGS);
		
		Properties properties = new Properties();
		properties.put("basedir",project.getLocation().toOSString());
		properties.put("build.compiler", "org.eclipse.jdt.core.JDTCompilerAdapter");
		properties.put("easyant.modules.dir", easyantCoreService.getPluginsRepositoryPath());
				
		//junit plugin under eclipse
		//if property is true : Forked Java VM exited abnormally. Please note the time in the report does not reflect the time until the VM exit.
		properties.put("test.run.fork", "false");
		
		EasyAntConfiguration configuration = EasyantConfigurationFactory.getInstance().createDefaultConfiguration();
		configuration.setShowMemoryDetails(true);
		//configuration.setBuildFile(buildFile); //TODO manage module.ant file
		configuration.setBuildModule(buildModule);
		configuration.setDefinedProps(properties);
		configuration.setMsgOutputLevel(logLevel);
		Vector<String> targets = new Vector<String>();
		targets.add(buildTaskName);
		configuration.setTargets(targets);
		configuration.setEasyantIvySettingsUrl(easyantIvySettingsUrl.toString());
		
		PrintStream outStream = getConsoleOutStream();
		configuration.setOut(outStream);
		
		PrintStream errStream = getConsoleErrStream();
		configuration.setErr(errStream);
		
		//TODO lancer cela dans une WorkspaceModifyOperation
		try{
			EasyAntEngine.runBuild(configuration);
		}catch (Exception be) {
			Activator.getEasyAntPlugin().log(IStatus.WARNING, be.getMessage());
		}
		
		outStream.close();
		errStream.close();
		
	}

	private PrintStream getConsoleOutStream(){		
		console.show(true);
		return new PrintStream(new OutputStream(){
			private StringBuffer sb = new StringBuffer();
			@Override
			public void write(int b) throws IOException {
				if(b!=10){
					sb.append((char)b);
				}else{
					String message = sb.toString();
					console.info(message);
					sb = new StringBuffer();
				}				
			}
			
		});
	}

	private PrintStream getConsoleErrStream(){		
		console.show(true);
		return new PrintStream(new OutputStream(){
			private StringBuffer sb = new StringBuffer();
			@Override
			public void write(int b) throws IOException {
				if(b!=10){
					sb.append((char)b);
				}else{
					String message = sb.toString();
					console.error(message);
					sb = new StringBuffer();
				}				
			}
			
		});
	}

	public boolean hasEasyAntNature(IProject project){
		try {
			return project.hasNature(EasyAntNature.NATURE_ID);
		} catch (CoreException e) {
			Activator.getEasyAntPlugin().log(e);
		}
		return false;
	}
	
	public boolean hasEasyAntBuilder(IProject project){
		ICommand[] commands=null;
		try {
			commands = project.getProject().getDescription().getBuildSpec();
		} catch (CoreException e) {
			Activator.getEasyAntPlugin().log(e);
		}		
		boolean found = false;
		if(commands!=null){		
			for (int i = 0; i < commands.length; ++i) {
				if (commands[i].getBuilderName().equals(EasyAntNature.BUILDER_ID)){
					found = true;
				}
			}	
		}	
		return found;
	}
	

	public void addNature(IProject project) {
		addNature(project, null, null);	
	}
	
	private void addNature(IProject project, Shell shell, IProgressMonitor monitor) {

		AddEasyAntNatureOperation addNature = new AddEasyAntNatureOperation(project);
		try {
			if(shell==null && monitor==null){
				PlatformUI.getWorkbench().getProgressService().run(false, false, addNature);
			}else{
				addNature.run(monitor);
			}
		} catch (InvocationTargetException e) {
			Activator.getEasyAntPlugin().log(IStatus.ERROR, "Cannot add EasyAnt nature.", e);
		} catch (InterruptedException e) {
			Activator.getEasyAntPlugin().log(IStatus.CANCEL, "Add EasyAnt nature operation aborted!", e);
		}
		// TODO launch resolve (ask to user)
		// TODO initialize IvyDE classpath container
		// TODO maybe launch the first build ??	
	}
	
	public void removeNature(IProject project) {
		// Remove the nature on the given project
		RemoveEasyAntNatureOperation removeNature = new RemoveEasyAntNatureOperation(project);
		try {
			PlatformUI.getWorkbench().getProgressService().run(false, false, removeNature);
		} catch (InvocationTargetException e) {
			Activator.getEasyAntPlugin().log(IStatus.ERROR, "Cannot remove EasyAnt nature.", e);
		} catch (InterruptedException e) {
			Activator.getEasyAntPlugin().log(IStatus.CANCEL, "Remove EasyAnt nature operation aborted!", e);
		}
		// TODO remove IvyDE classpath container
		
	}

	public IProject importProject(IProjectDescription projectDescription,  Shell messageShell, IProgressMonitor monitor) {
		//String projectName = importProjectDescriptor.getProjectName();
		//IProjectDescription projectDescription = importProjectDescriptor.getDescription();
		String projectName = projectDescription.getName();
		final IWorkspace workspace = ResourcesPlugin.getWorkspace();
		final IProject project = workspace.getRoot().getProject(projectName);
//		if (projectDescription == null) {
//			// error case
//			projectDescription = workspace.newProjectDescription(projectName);
//			IPath locationPath = new Path(importProjectDescriptor.getProjectSystemFile().getAbsolutePath());
//
//			// If it is under the root use the default location
//			if (Platform.getLocation().isPrefixOf(locationPath)) {
//				projectDescription.setLocation(null);
//			} else {
//				projectDescription.setLocation(locationPath);
//			}
//		} else {
//			projectDescription.setName(projectName);
//		}

//		if (importProjectDescriptor.isFromIvyDescription()) {
			// import form Ivy description
			File importSource = new File(projectDescription.getLocationURI());
			IWorkspaceRoot rootWorkspace = workspace.getRoot();
			ImportOperation importOperation = new ImportOperation(rootWorkspace.getFullPath(),importSource,FileSystemStructureProvider.INSTANCE, new IOverwriteQuery(){
					public String queryOverwrite(String pathString) { return ALL; }
			});
			importOperation.setContext(messageShell);
			try {
				//PlatformUI.getWorkbench().getProgressService().run(false, false, importOperation);
				importOperation.run(monitor);
			} catch (InvocationTargetException e) {
				Activator.getEasyAntPlugin().log(IStatus.ERROR, "Cannot import project.", e);
			} catch (InterruptedException e) {
				Activator.getEasyAntPlugin().log(IStatus.ERROR, "Cannot import project.", e);
			}			
//		}

		try {
			monitor.beginTask("Creating project ...", 100);
			project.create(projectDescription, new SubProgressMonitor(monitor, 30));
			project.open(IResource.BACKGROUND_REFRESH, new SubProgressMonitor(monitor, 70));
			// configure project, apply EasyAnt nature
//			if (importProjectDescriptor.isFromIvyDescription()) {
				addNature(project, messageShell, monitor);
//			}
		} catch (CoreException e) {
			Activator.getEasyAntPlugin().log(IStatus.ERROR, "Cannot configure imported project.", e);
			return null;
		} finally {
			monitor.done();		
		}
		return project;
		
	}
	
	public List<PhaseReport> getPhases(IFile ivyFile) {
		EasyAntReport easyAntReport = null;
		try {
			//loadEasyAntIvySettings(ivyFile.getProject());
			File f = new File(ivyFile.getLocation().toPortableString());
			easyAntReport = easyAntEngine.getPluginService().generateEasyAntReport(f);
		} catch (Exception e) {
			Activator.getEasyAntPlugin().log(IStatus.ERROR, e.getMessage(), e);
		}
		if (easyAntReport != null) {
			return easyAntReport.getAvailablePhases();
		}
		return Collections.emptyList();
	}

	//private File getBaseDir(IProject project) {
	//	return project.getLocation().toFile();
	//}
	
	public List<TargetReport> getTargets(IFile ivyFile) {
		EasyAntReport easyAntReport = null;
		try {
			File f = new File(ivyFile.getLocation().toPortableString());
			easyAntReport = easyAntEngine.getPluginService().generateEasyAntReport(f);
		} catch (Exception e) {
			Activator.getEasyAntPlugin().log(IStatus.ERROR, e.getMessage(), e);
		}
		if (easyAntReport != null) {
			return easyAntReport.getUnboundTargets();
		}
		return Collections.emptyList();
	}

	public EasyAntModuleDescriptor getEasyAntModuleDescriptor(File file) {
		EasyAntModuleDescriptor moduleDescriptor=null;
		try {
			moduleDescriptor = easyAntEngine.getPluginService().getEasyAntModuleDescriptor(file);
		} catch (Exception e) {
			Activator.getEasyAntPlugin().log(IStatus.ERROR, e.getMessage(), e);
		}
		return moduleDescriptor;
	}
	
	public Map<String, PropertyDescriptor> getProperties(IProject project){
		IFile ivyFile = project.getFile("module.ivy");
		String ivyFilePath = ivyFile.getLocation().toOSString();
		File moduleDescriptor = new File(ivyFilePath);
		EasyAntReport easyAntReport=null;
		try {
			easyAntReport = easyAntEngine.getPluginService().generateEasyAntReport(moduleDescriptor);			
		} catch (Exception e) {
			Activator.getEasyAntPlugin().log(IStatus.ERROR, e.getMessage(), e);
		}				
		if(easyAntReport!=null){
			return easyAntReport.getAvailableProperties();
		}
		return Collections.emptyMap();
	}
	
	public PropertyDescriptor getProperty(IProject project, String name){
		Map<String, PropertyDescriptor> properties = getProperties(project);
		if(properties.containsKey(name)){
			PropertyDescriptor propertyDescriptor = properties.get(name);			
			return propertyDescriptor;
		}else{
			return null;
		}
	}
	
}
