/*******************************************************************************
 * Copyright (c) 2015, 2016 QNX Software Systems and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/
package org.eclipse.cdt.internal.qt.core.build;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.cdt.core.ConsoleOutputStream;
import org.eclipse.cdt.core.ErrorParserManager;
import org.eclipse.cdt.core.IConsoleParser;
import org.eclipse.cdt.core.build.CBuildConfiguration;
import org.eclipse.cdt.core.build.ICBuildConfiguration;
import org.eclipse.cdt.core.build.IToolChain;
import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
import org.eclipse.cdt.core.model.ICModelMarker;
import org.eclipse.cdt.core.parser.ExtendedScannerInfo;
import org.eclipse.cdt.core.parser.IExtendedScannerInfo;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.core.resources.IConsole;
import org.eclipse.cdt.internal.qt.core.Activator;
import org.eclipse.cdt.qt.core.IQtBuildConfiguration;
import org.eclipse.cdt.qt.core.IQtInstall;
import org.eclipse.cdt.qt.core.IQtInstallListener;
import org.eclipse.cdt.qt.core.IQtInstallManager;
import org.eclipse.cdt.qt.core.QtInstallEvent;
import org.eclipse.core.resources.IBuildConfiguration;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;

public class QtBuildConfiguration extends CBuildConfiguration
		implements ICBuildConfiguration, IQtBuildConfiguration, IQtInstallListener {

	private static final String QTINSTALL_NAME = "cdt.qt.install.name"; //$NON-NLS-1$
	private static final String QTINSTALL_SPEC = "cdt.qt.install.spec"; //$NON-NLS-1$
	private static final String LAUNCH_MODE = "cdt.qt.launchMode"; //$NON-NLS-1$

	private final String qtInstallSpec;
	private IQtInstall qtInstall;
	private Map<String, String> properties;

	public QtBuildConfiguration(IBuildConfiguration config, String name) throws CoreException {
		super(config, name);

		IQtInstallManager manager = Activator.getService(IQtInstallManager.class);
		manager.addListener(this);

		Preferences settings = getSettings();
		String installName = settings.get(QTINSTALL_NAME, ""); //$NON-NLS-1$
		qtInstallSpec = settings.get(QTINSTALL_SPEC, ""); //$NON-NLS-1$
		if (!installName.isEmpty()) {
			qtInstall = manager.getInstall(Paths.get(installName));
			if (qtInstallSpec.isEmpty()) {
				// save the spec if it wasn't set
				settings.put(QTINSTALL_SPEC, qtInstall.getSpec());
				try {
					settings.flush();
				} catch (BackingStoreException e) {
					Activator.log(e);
				}
			}
		}

		if (getQtInstall() == null) {
			throw new CoreException(
					Activator.error(String.format("Qt Install for build configuration %s not found.", name)));
		}

		String oldLaunchMode = settings.get(LAUNCH_MODE, null);
		if (oldLaunchMode != null) {
			setLaunchMode(oldLaunchMode);
			settings.remove(LAUNCH_MODE);
			try {
				settings.flush();
			} catch (BackingStoreException e) {
				Activator.log(e);
			}
		}
	}

	QtBuildConfiguration(IBuildConfiguration config, String name, IToolChain toolChain, IQtInstall qtInstall,
			String launchMode) throws CoreException {
		super(config, name, toolChain, launchMode);
		this.qtInstall = qtInstall;
		this.qtInstallSpec = qtInstall.getSpec();

		IQtInstallManager manager = Activator.getService(IQtInstallManager.class);
		manager.addListener(this);

		Preferences settings = getSettings();
		settings.put(QTINSTALL_NAME, qtInstall.getQmakePath().toString());
		settings.put(QTINSTALL_SPEC, qtInstallSpec);
		if (launchMode != null) {
			settings.put(LAUNCH_MODE, launchMode);
		}
		try {
			settings.flush();
		} catch (BackingStoreException e) {
			Activator.log(e);
		}
	}

	public IQtInstall getQtInstall() {
		if (qtInstall == null && !qtInstallSpec.isEmpty()) {
			// find one that matches the spec
			IQtInstallManager manager = Activator.getService(IQtInstallManager.class);
			Collection<IQtInstall> candidates = manager.getInstall(qtInstallSpec);
			if (!candidates.isEmpty()) {
				qtInstall = candidates.iterator().next();
			}
		}
		return qtInstall;
	}

	@Override
	public void installChanged(QtInstallEvent event) {
		if (event.getType() == QtInstallEvent.REMOVED && event.getInstall().equals(qtInstall)) {
			// clear the cache so we refetch later
			qtInstall = null;
		}
	}

	@Override
	public Path getQmakeCommand() {
		return getQtInstall().getQmakePath();
	}

	@Override
	public String[] getQmakeConfig() {
		String launchMode = getLaunchMode();
		if (launchMode != null) {
			switch (launchMode) {
			case "run": //$NON-NLS-1$
				return new String[] { "CONFIG-=debug_and_release", "CONFIG+=release" }; //$NON-NLS-1$ //$NON-NLS-2$
			case "debug": //$NON-NLS-1$
				return new String[] { "CONFIG-=debug_and_release", "CONFIG+=debug" }; //$NON-NLS-1$ //$NON-NLS-2$
			default:
				return new String[] { "CONFIG-=debug_and_release", "CONFIG+=launch_mode_" + launchMode }; //$NON-NLS-1$ //$NON-NLS-2$
			}
		}
		return new String[] { "CONFIG+=debug_and_release", "CONFIG+=launch_modeall" }; //$NON-NLS-1$ //$NON-NLS-2$
	}

	public Path getProjectFile() {
		File projectDir = getProject().getLocation().toFile();
		File[] proFiles = projectDir.listFiles((dir, name) -> name.endsWith(".pro")); //$NON-NLS-1$
		if (proFiles.length > 0) {
			// TODO what if there are more than one.
			return proFiles[0].toPath();
		} else {
			return null;
		}
	}

	@Deprecated
	@Override
	public Path getProgramPath() throws CoreException {
		// TODO get the app name from the .pro file.
		String projectName = getProject().getName();
		switch (Platform.getOS()) {
		case Platform.OS_MACOSX:
			Path appFolder = getBuildDirectory().resolve(projectName + ".app"); //$NON-NLS-1$
			Path contentsFolder = appFolder.resolve("Contents"); //$NON-NLS-1$
			Path macosFolder = contentsFolder.resolve("MacOS"); //$NON-NLS-1$
			return macosFolder.resolve(projectName);
		case Platform.OS_WIN32:
			return getBuildDirectory().resolve(projectName + ".exe"); //$NON-NLS-1$
		case Platform.OS_LINUX:
			return getBuildDirectory().resolve(projectName);
		default:
			Path releaseFolder = getBuildDirectory().resolve("release"); //$NON-NLS-1$
			return releaseFolder.resolve(projectName);
		}
	}

	public String getProperty(String key) {
		if (properties == null) {
			List<String> cmd = new ArrayList<>();
			cmd.add(getQmakeCommand().toString());
			cmd.add("-E"); //$NON-NLS-1$

			String[] config = getQmakeConfig();
			if (config != null) {
				for (String str : config) {
					cmd.add(str);
				}
			}

			cmd.add(getProjectFile().toString());

			try {
				ProcessBuilder processBuilder = new ProcessBuilder(cmd)
						.directory(getProjectFile().getParent().toFile());
				setBuildEnvironment(processBuilder.environment());
				Process proc = processBuilder.start();
				try (BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()))) {
					properties = new HashMap<>();
					for (String line = reader.readLine(); line != null; line = reader.readLine()) {
						int i = line.indexOf('=');
						if (i >= 0) {
							String k = line.substring(0, i);
							String v = line.substring(i + 1);
							properties.put(k.trim(), v.trim());
						}
					}
				}
			} catch (IOException e) {
				Activator.log(e);
			}
		}

		return properties != null ? properties.get(key) : null;
	}

	@Override
	public IEnvironmentVariable getVariable(String name) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public IEnvironmentVariable[] getVariables() {
		// TODO
		return new IEnvironmentVariable[0];
	}

	@Override
	public IScannerInfo getScannerInformation(IResource resource) {
		IQtInstall qtInstall = getQtInstall();

		String cxx = getProperty("QMAKE_CXX"); //$NON-NLS-1$
		if (cxx == null) {
			Activator.log("No QMAKE_CXX for " + qtInstall.getSpec()); //$NON-NLS-1$
			return null;
		}
		String[] cxxSplit = cxx.split(" "); //$NON-NLS-1$
		Path command = Paths.get(cxxSplit[0]);

		List<String> args = new ArrayList<>();
		for (int i = 1; i < cxxSplit.length; ++i) {
			args.add(cxxSplit[i]);
		}
		args.addAll(Arrays.asList(getProperty("QMAKE_CXXFLAGS").split(" "))); //$NON-NLS-1$ //$NON-NLS-2$
		args.add("-o"); //$NON-NLS-1$
		args.add("-"); //$NON-NLS-1$

		String srcFile;
		if (resource instanceof IFile) {
			srcFile = resource.getLocation().toOSString();
			// Only add file if it's an IFile
			args.add(srcFile);
		} else {
			// Doesn't matter, the toolchain will create a tmp file for this
			srcFile = "scannerInfo.cpp"; //$NON-NLS-1$
		}

		String[] includePaths = getProperty("INCLUDEPATH").split(" "); //$NON-NLS-1$ //$NON-NLS-2$
		for (int i = 0; i < includePaths.length; ++i) {
			Path path = Paths.get(includePaths[i]);
			if (!path.isAbsolute()) {
				Path projectDir = getProjectFile().getParent();
				includePaths[i] = projectDir.resolve(path).toString();
			}
		}

		IExtendedScannerInfo baseScannerInfo = new ExtendedScannerInfo(null, includePaths);
		try {
			return getToolChain().getScannerInfo(getBuildConfiguration(), command,
					args.toArray(new String[args.size()]), baseScannerInfo, resource,
					getBuildContainer().getLocationURI());
		} catch (CoreException e) {
			Activator.log(e);
			return null;
		}
	}

	@Override
	public IProject[] build(int kind, Map<String, String> args, IConsole console, IProgressMonitor monitor)
			throws CoreException {
		IProject project = getProject();
		try {
			project.deleteMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);

			ConsoleOutputStream errStream = console.getErrorStream();
			ConsoleOutputStream outStream = console.getOutputStream();

			Path makeCommand = getMakeCommand();
			if (makeCommand == null) {
				errStream.write("'make' not found.\n");
				return null;
			}

			Path buildDir = getBuildDirectory();

			if (!buildDir.resolve("Makefile").toFile().exists()) { //$NON-NLS-1$
				// Need to run qmake
				List<String> command = new ArrayList<>();
				command.add(getQmakeCommand().toString());

				String[] config = getQmakeConfig();
				if (config != null) {
					for (String str : config) {
						command.add(str);
					}
				}

				IFile projectFile = project.getFile(project.getName() + ".pro"); //$NON-NLS-1$
				command.add(projectFile.getLocation().toOSString());

				ProcessBuilder processBuilder = new ProcessBuilder(command).directory(getBuildDirectory().toFile());
				setBuildEnvironment(processBuilder.environment());
				Process process = processBuilder.start();

				StringBuffer msg = new StringBuffer();
				for (String arg : command) {
					msg.append(arg).append(' ');
				}
				msg.append('\n');
				outStream.write(msg.toString());

				// TODO qmake error parser
				watchProcess(process, new IConsoleParser[0], console);
			}

			try (ErrorParserManager epm = new ErrorParserManager(project, getBuildDirectoryURI(), this,
					getToolChain().getErrorParserIds())) {
				// run make
				ProcessBuilder processBuilder = new ProcessBuilder(makeCommand.toString(), "all") //$NON-NLS-1$
						.directory(buildDir.toFile());
				setBuildEnvironment(processBuilder.environment());
				Process process = processBuilder.start();
				outStream.write(makeCommand.toString() + '\n');
				watchProcess(process, new IConsoleParser[] { epm }, console);
			}

			getProject().refreshLocal(IResource.DEPTH_INFINITE, monitor);
			return new IProject[] { project };
		} catch (IOException e) {
			throw new CoreException(new Status(IStatus.ERROR, Activator.ID, "Building " + project.getName(), e)); //$NON-NLS-1$
		}
	}

	@Override
	public void clean(IConsole console, IProgressMonitor monitor) throws CoreException {
		IProject project = getProject();
		try {
			project.deleteMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);

			ConsoleOutputStream errStream = console.getErrorStream();
			ConsoleOutputStream outStream = console.getOutputStream();

			Path makeCommand = getMakeCommand();
			if (makeCommand == null) {
				errStream.write("'make' not found.\n");
				return;
			}

			Path buildDir = getBuildDirectory();

			try (ErrorParserManager epm = new ErrorParserManager(project, getBuildDirectoryURI(), this,
					getToolChain().getErrorParserIds())) {
				// run make
				ProcessBuilder processBuilder = new ProcessBuilder(makeCommand.toString(), "clean") //$NON-NLS-1$
						.directory(buildDir.toFile());
				setBuildEnvironment(processBuilder.environment());
				Process process = processBuilder.start();
				outStream.write(makeCommand.toString() + "clean\n"); //$NON-NLS-1$
				watchProcess(process, new IConsoleParser[] { epm }, console);
			}

			project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
		} catch (IOException e) {
			throw new CoreException(new Status(IStatus.ERROR, Activator.ID, "Cleaning " + project.getName(), e)); //$NON-NLS-1$
		}
	}

	public Path getMakeCommand() {
		Path makeCommand = findCommand("make"); //$NON-NLS-1$
		if (makeCommand == null) {
			makeCommand = findCommand("mingw32-make"); //$NON-NLS-1$
		}
		return makeCommand;
	}

}
