/**********************************************************************
 * This file is part of "Object Teams Development Tooling"-Software
 * 
 * Copyright 2013, 2015 GK Software AG
 *  
 * 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
 * 
 * Please visit http://www.objectteams.org for updates and contact.
 * 
 * Contributors:
 * 	Stephan Herrmann - Initial API and implementation
 **********************************************************************/
package org.eclipse.objectteams.internal.osgi.weaving;

import static org.eclipse.objectteams.otequinox.TransformerPlugin.log;

import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.objectteams.internal.osgi.weaving.AspectBinding.BaseBundle;
import org.eclipse.objectteams.internal.osgi.weaving.AspectBinding.TeamBinding;
import org.eclipse.objectteams.internal.osgi.weaving.Util.ProfileKind;
import org.eclipse.objectteams.otequinox.ActivationKind;
import org.eclipse.objectteams.otredyn.runtime.TeamManager;
import org.eclipse.objectteams.otredyn.transformer.jplis.ObjectTeamsTransformer;
import org.objectteams.Team;
import org.osgi.framework.Bundle;
import org.osgi.framework.hooks.weaving.WovenClass;

/**
 * This class triggers the actual loading/instantiation/activation of teams.
 * <p>
 * It implements a strategy of deferring those teams that are not ready for
 * instantiating / activating, which we check by comparing the sets of
 * bound base classes of the team vs. the set of classes currently being
 * processed by class loading & weaving.
 * This reflects that fact that classes for which loading has already been
 * started would otherwise trigger an irrecoverable NoClassDefFoundError. 
 * </p><p>
 * Which teams participate in deferred instantiation is communicated via the 
 * shared list {@link #deferredTeams}.
 * </p>
 */
@NonNullByDefault
public class TeamLoader {

	/** Collect here any teams that cannot yet be handled and should be scheduled later. */
	private List<WaitingTeamRecord> deferredTeams;

	private Set<String> beingDefined;
	
	boolean useDynamicWeaving;

	public TeamLoader(List<WaitingTeamRecord> deferredTeams, Set<String> beingDefined, boolean useDynamicWeaving) {
		this.deferredTeams = deferredTeams;
		this.beingDefined = beingDefined;
		this.useDynamicWeaving = useDynamicWeaving;
	}

	/**
	 * Team loading, 1st attempt before the base class is even loaded
	 * Trying to do these phases: load (now) instantiate/activate (if ready),
	 */
	public void loadTeamsForBase(BaseBundle baseBundle, WovenClass baseClass, AspectPermissionManager permissionManager) {
		@NonNull String className = baseClass.getClassName();
		Collection<TeamBinding> teamsForBase = baseBundle.teamsPerBase.get(className);
		if (teamsForBase == null) 
			return; // not done

		// permission checking can be performed now or later, depending on readiness:
		boolean permissionManagerReady = permissionManager.isReady();

		// ==== check permissions before we start activating:
		if (permissionManagerReady) { // otherwise we will register pending obligations below.
			Set<TeamBinding> deniedTeams = permissionManager.checkAspectPermissionDenial(teamsForBase);
			if (!deniedTeams.isEmpty()){
				for (WaitingTeamRecord rec : new ArrayList<>(this.deferredTeams))
					if (deniedTeams.contains(rec.team))
						this.deferredTeams.remove(rec);
			}
		}
		
		List<Team> teamInstances = new ArrayList<>();
		for (TeamBinding teamForBase : teamsForBase) {
			if (teamForBase.isActivated) continue;
			if (teamForBase.hasBeenDenied()) {
				log(IStatus.WARNING, "Not activating team "+teamForBase.teamName+" due to denied permissions.");
				continue;
			}
			// Load:
			Class<? extends Team> teamClass;
			teamClass = teamForBase.loadTeamClass();
			if (teamClass == null) {
				log(new ClassNotFoundException("Not found: "+teamForBase), "Failed to load team "+teamForBase);
				continue;
			}
			// Try to instantiate & activate, failures are recorded in deferredTeams
			ActivationKind activationKind = teamForBase.getActivation();
			if (activationKind == ActivationKind.NONE) {
				teamForBase = teamForBase.getOtherTeamToActivate();
				if (teamForBase != null) {
					if (teamForBase.isActivated) continue;
					activationKind = teamForBase.getActivation();
					teamClass = teamForBase.loadTeamClass();
					if (teamClass == null) {
						log(new ClassNotFoundException("Not found: "+teamForBase.teamName+" in bundle "+teamForBase.getAspectBinding().aspectPlugin), "Failed to load team "+teamForBase);
						continue;						
					}
				} else {
					continue;
				}
			}
			if (activationKind == ActivationKind.NONE) 
				continue;
			Team instance = instantiateAndActivate(teamForBase.getAspectBinding(), teamForBase, activationKind);
			if (instance != null)
				teamInstances.add(instance);
		}

		if (!permissionManagerReady)
			permissionManager.addBaseBundleObligations(teamInstances, teamsForBase, baseBundle);
	}

	public static @Nullable Pair<URL,String> findTeamClassResource(String className, Bundle bundle) {
		for (String candidate : possibleTeamNames(className)) {
			URL result = bundle.getResource(candidate.replace('.', '/')+".class");
			if (result != null)
				return new Pair<>(result, candidate);
		}
		return null;
	}

	/** 
	 * Starting from currentName compute a list of potential binary names of (nested) teams
	 * using "$__OT__" as the separator, to find class parts of nested teams.  
	 */
	public static List<String> possibleTeamNames(String currentName) {
		List<String> result = new ArrayList<String>();
		result.add(currentName);
		char sep = '.'; // assume source name
		if (currentName.indexOf('$') > -1)
			// binary name
			sep = '$';
		int from = currentName.length()-1;
		while (true) {
			int pos = currentName.lastIndexOf(sep, from);
			if (pos == -1)
				break;
			String prefix = currentName.substring(0, pos); 
			String postfix = currentName.substring(pos+1);
			if (sep=='$') {
				if (!postfix.startsWith("__OT__"))
					result.add(0, currentName = prefix+"$__OT__"+postfix);
			} else {
				// heuristic: 
				// only replace if parent element looks like a class (expected to start with uppercase)
				int prevDot = prefix.lastIndexOf('.');
				if (prevDot > -1 && Character.isUpperCase(prefix.charAt(prevDot+1))) 
					result.add(0, currentName = prefix+"$__OT__"+postfix);
				else 
					break;
			}
			from = pos-1;
		}
		return result;
	}

	/**
	 * Check if the given team is ready. If so instantiate it and if activationKind requires also activate it.
	 */
	@Nullable Team instantiateAndActivate(AspectBinding aspectBinding, TeamBinding team, ActivationKind activationKind)
	{
		for (TeamBinding equivalent : team.equivalenceSet)
			if (equivalent.instance != null && equivalent.isActivated) return equivalent.instance;

		String teamName = team.teamName;
		// don't try to instantiate before all base classes successfully loaded.
		synchronized(aspectBinding) {
			if (!isReadyToLoad(aspectBinding, team, teamName, activationKind)) {
				if (this.useDynamicWeaving)
					TeamManager.prepareTeamActivation(team.teamClass);
				return null;
			}
			for (TeamBinding equivalent : team.equivalenceSet)
				equivalent.isActivated = true;
		}

		try {
			long time = 0;
			if (Util.PROFILE) time= System.nanoTime();

			Team instance = team.getInstance();
			
			try {
				switch (activationKind) {
				case ALL_THREADS:
					instance.activate(Team.ALL_THREADS);
					log(IStatus.INFO, "Activated team "+teamName);
					break;
				case THREAD:
					instance.activate();
					log(IStatus.INFO, "Activated team "+teamName);
					break;
				//$CASES-OMITTED$
				default:
					break;
				}
				if (Util.PROFILE) Util.profile(time, ProfileKind.Activation, teamName);
			} catch (NoClassDefFoundError|ClassCircularityError e) {
				try { // clean up:
					switch (activationKind) {
					case ALL_THREADS: instance.deactivate(Team.ALL_THREADS); break;
					case THREAD: instance.deactivate(); break;
					default: break;
					}
				} catch (Throwable t) { /* ignore */ }
				for (TeamBinding eq : team.equivalenceSet)
					eq.isActivated = false;
				String notFoundName = e.getMessage().replace('/', '.');
				synchronized (this.deferredTeams) {
					this.deferredTeams.add(new WaitingTeamRecord(team, activationKind, notFoundName));
				}
			} catch (Throwable t) {
				// application errors during activation
				log(t, "Failed to activate team "+teamName);
			}
			return instance;
		} catch (ClassCircularityError e) {
			for (TeamBinding eq : team.equivalenceSet)
				eq.isActivated = false;
			String notFoundName = e.getMessage().replace('/', '.');
			synchronized (this.deferredTeams) {
				this.deferredTeams.add(new WaitingTeamRecord(team, activationKind, notFoundName));
			}
		} catch (Throwable e) {
			// application error during constructor execution?
			log(e, "Failed to instantiate team "+teamName);
		}
		return null;
	}

	private boolean isReadyToLoad(AspectBinding aspectBinding,
									TeamBinding team, String teamName,
									ActivationKind activationKind)
	{
		String unloadableBaseClass = findUnloadableBaseClass(team);
		if (unloadableBaseClass != null) {
			synchronized (deferredTeams) {
				WaitingTeamRecord record = new WaitingTeamRecord(team, activationKind, unloadableBaseClass);
				deferredTeams.add(record);
			}
			log(IStatus.INFO, "Defer instantation/activation of team "+teamName+", waiting for "+unloadableBaseClass);
			return false;
		}
		return true;
	}
	
	private @Nullable String findUnloadableBaseClass(TeamBinding team) {
		// easy tests first:
		for (String baseclass : team.baseClassNames) {
			if (this.beingDefined.contains(baseclass))
				return baseclass;
		}
		// definite, more expensive tests:
		Class<?> teamClass = team.teamClass;
		if (teamClass != null) {
			// use a throw-away class loader so we have a fresh chance to load any failed classes later
			// (only initiating class loader remembers the failure, if this is discarded, the slate is clean):
			ClassLoader tryLoader = new ClassLoader(teamClass.getClassLoader()) {};
			for (String baseclass : team.baseClassNames) { 
				Boolean previous = ObjectTeamsTransformer.initiatedByThrowAwayLoader.get();
				try {
					ObjectTeamsTransformer.initiatedByThrowAwayLoader.set(Boolean.TRUE);
					tryLoader.loadClass(baseclass);
				} catch (Throwable t) {
					return baseclass;
				} finally {
					ObjectTeamsTransformer.initiatedByThrowAwayLoader.set(previous);
				}
			}
		}
		return null;
	}
}
