/*******************************************************************************
 * Copyright (c) 2014 Bruno Medeiros and other Contributors.
 * 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
 *
 * Contributors:
 *     Bruno Medeiros - initial API and implementation
 *******************************************************************************/
package com.googlecode.goclipse.core;

import static melnorme.lang.ide.core.utils.ResourceUtils.loc;
import static melnorme.utilbox.misc.StringUtil.emptyAsNull;
import static melnorme.utilbox.misc.StringUtil.nullAsEmpty;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;

import com.googlecode.goclipse.tooling.GoPackageName;
import com.googlecode.goclipse.tooling.env.GoArch;
import com.googlecode.goclipse.tooling.env.GoEnvironment;
import com.googlecode.goclipse.tooling.env.GoEnvironmentConstants;
import com.googlecode.goclipse.tooling.env.GoOs;
import com.googlecode.goclipse.tooling.env.GoPath;
import com.googlecode.goclipse.tooling.env.GoRoot;
import com.googlecode.goclipse.tooling.env.GoWorkspaceLocation;

import melnorme.lang.ide.core.utils.ResourceUtils;
import melnorme.lang.ide.core.utils.prefs.StringPreference;
import melnorme.utilbox.collections.ArrayList2;
import melnorme.utilbox.core.CommonException;
import melnorme.utilbox.misc.Location;

public class GoProjectEnvironment implements GoEnvironmentConstants {
	
	public static GoRoot getEffectiveGoRoot(IProject project) {
		return new GoRoot(getEffectiveValue_NonNull(GoEnvironmentPrefs.GO_ROOT, project, GOROOT));
	}
	
	public static GoArch getEffectiveGoArch(IProject project) {
		String strValue = emptyAsNull(getEffectiveValue(GoEnvironmentPrefs.GO_ARCH, project, GOARCH));
		return strValue == null ? null : new GoArch(strValue);
	}
	
	public static GoOs getEffectiveGoOs(IProject project) {
		String strValue = emptyAsNull(getEffectiveValue(GoEnvironmentPrefs.GO_OS, project, GOOS));
		return strValue == null ? null : new GoOs(strValue);
	}
	
	public static GoPath getEffectiveGoPath(IProject project) {
		String goPathPref = getEffectiveValue_NonNull(GoEnvironmentPrefs.GO_PATH, project, GOPATH);
		GoPath rawGoPath = new GoPath(goPathPref);
		if(project == null) {
			return rawGoPath;
		}
		
		Location projectLoc = ResourceUtils.getResourceLocation(project);
		if(projectLoc == null) {
			return rawGoPath;
		}
		
		GoWorkspaceLocation goPathEntry = rawGoPath.findGoPathEntryForSourcePath(projectLoc);
		if(goPathEntry != null) {
			// GOPATH already contains project location
			return rawGoPath;
		}
		
		// Implicitly add project location to GOPATH
		ArrayList2<String> newGoPathEntries = new ArrayList2<>(projectLoc.toPathString());
		newGoPathEntries.addAll(rawGoPath.getGoPathEntries());
		return new GoPath(newGoPathEntries);
	}
	
	public static boolean isProjectInsideGoPathSourceFolder(IProject project) throws CommonException {
		GoPath goPath = getEffectiveGoPath(project);
		return isProjectInsideGoPathSourceFolder(project, goPath);
	}
	
	public static boolean isProjectInsideGoPathSourceFolder(IProject project, GoPath goPath) throws CommonException {
		return goPath.findGoPathEntryForSourcePath(ResourceUtils.getProjectLocation2(project)) != null;
	}
	
	protected static String getEffectiveValue_NonNull(StringPreference stringPref, IProject project, 
			String envAlternative) {
		return nullAsEmpty(getEffectiveValue(stringPref, project, envAlternative));
	}
	
	protected static String getEffectiveValue(StringPreference stringPref, IProject project, String envAlternative) {
		String prefValue = stringPref.getProjectPreference().getEffectiveValue(project);
		if(prefValue == null || prefValue.isEmpty()) {
			return System.getenv(envAlternative);
		}
		return prefValue;
	}
	
	public static GoEnvironment getGoEnvironmentFromLocation(Location fileLocation) {
		IProject project = ResourceUtils.getProject(fileLocation);
		return getGoEnvironment(project);
	}
	
	/**
	 * @return {@link GoEnvironment} for given project.
	 * @param project - can be null.
	 */
	public static GoEnvironment getGoEnvironment(IProject project) {
		GoRoot goRoot = getEffectiveGoRoot(project);
		GoArch goArch = getEffectiveGoArch(project);
		GoOs goOs = getEffectiveGoOs(project);
		GoPath goPath = getEffectiveGoPath(project);
		return new GoEnvironment(goRoot, goArch, goOs, goPath);
	}

	public static boolean isValid(IProject project) {
		return getGoEnvironment(project).isValid();
	}
	
	public static GoEnvironment getValidatedGoEnvironment(final IProject project) throws CommonException {
		GoEnvironment goEnv = getGoEnvironment(project);
		goEnv.validate();
		return goEnv;
	}
	
	public static ArrayList2<GoPackageName> findSourcePackages(IProject project, GoEnvironment goEnvironment)
			throws CoreException {
		return goEnvironment.getGoPath().findGoSourcePackages(ResourceUtils.getProjectLocation(project));
	}
	
	public static Location getBinFolderLocation(IProject project) throws CommonException {
		GoEnvironment goEnv = getGoEnvironment(project);
		return goEnv.getBinFolderLocationForSubLocation(loc(project.getLocation()));
	}
	
}
@@ -1746,32 +1746,31 @@
 fectiveValue
-_NonNull
+FromEnv
 (GoEnvironme
@@ -1907,34 +1907,16 @@
 yAsNull(
-getEffectiveValue(
 GoEnviro
@@ -1937,25 +1937,57 @@
 ARCH
-, project, GOARCH
+.getProjectPreference().getEffectiveValue(project
 ));%0D
@@ -2142,34 +2142,16 @@
 yAsNull(
-getEffectiveValue(
 GoEnviro
@@ -2170,23 +2170,57 @@
 O_OS
-, 
+.getProjectPreference().getEffectiveValue(
 project
-, GOOS
 ));%0D
@@ -2384,24 +2384,23 @@
 iveValue
-_NonNull
+FromEnv
 (GoEnvir
@@ -3591,223 +3591,15 @@
 alue
-_NonNull(StringPreference stringPref, IProject project, %0D%0A%09%09%09String envAlternative) %7B%0D%0A%09%09return nullAsEmpty(getEffectiveValue(stringPref, project, envAlternative));%0D%0A%09%7D%0D%0A%09%0D%0A%09protected static String getEffectiveValue
+FromEnv
 (Str
@@ -3612,23 +3612,17 @@
 ference 
-stringP
+p
 ref, IPr
@@ -3687,15 +3687,9 @@
 e = 
-stringP
+p
 ref.
@@ -3766,31 +3766,8 @@
 null
- %7C%7C prefValue.isEmpty()
 ) %7B%0D
@@ -3777,16 +3777,28 @@
 %09return 
+nullAsEmpty(
 System.g
@@ -3818,16 +3818,17 @@
 rnative)
+)
 ;%0D%0A%09%09%7D%0D%0A

Fix project-overriden GOPATH pref.