/*******************************************************************************
 * Copyright (c) 2003, 2005 IBM Corporation 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
 * 
 * Contributors:
 *     IBM Corporation - Initial API and implementation
 *******************************************************************************/
package org.eclipse.wst.server.core.internal;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;

import org.eclipse.wst.server.core.*;
/**
 * Helper class that stores preference information for the server tools.
 * 
 * TODO: Currently this class always reads from disk. It should cache the file
 * and have a resource listener.
 */
public class ProjectProperties implements IProjectProperties {
	private static final String PROJECT_PREFERENCE_FILE = ".runtime";
	
	protected IProject project;
	
	protected String serverId;
	protected String runtimeId;
	protected boolean serverProject = false;
	
	// project properties listeners
	protected transient List listeners;

	/**
	 * ProjectProperties constructor.
	 * 
	 * @param project a project
	 */
	public ProjectProperties(IProject project) {
		super();
		this.project = project;
	}
	
	/**
	 * Load the preferences.
	 */
	private void loadPreferences() {
		Trace.trace(Trace.FINEST, "Loading project preferences: " + project);
		
		InputStream in = null;
		try {
			IMemento memento = null;
			if (!project.exists() || !project.isOpen())
				return;
			IFile file = project.getFile(PROJECT_PREFERENCE_FILE);
			if (file != null && file.exists()) {
				in = file.getContents();
				memento = XMLMemento.loadMemento(in);
			}
			
			if (memento == null)
				return;
			
			serverId = memento.getString("server-id");
			runtimeId = memento.getString("runtime-id");
			String s = memento.getString("servers");
			if (s != null && "true".equals(s))
				serverProject = true;
			else
				serverProject = false;
		} catch (Exception e) {
			Trace.trace(Trace.SEVERE, "Could not load preferences: " + e.getMessage());
		} finally {
			try {
				if (in != null)
					in.close();
			} catch (Exception e) {
				// ignore
			}
		}
	}
	
	private void savePreferences(IProgressMonitor monitor) throws CoreException {
		if (project.exists() && project.isOpen()) {
			IFile file = project.getFile(PROJECT_PREFERENCE_FILE);
			
			if (file.exists() && file.isReadOnly()) {
				IStatus status = ResourcesPlugin.getWorkspace().validateEdit(new IFile[] { file }, null);
				if (status.getSeverity() == IStatus.ERROR)
					// didn't work or not under source control
					throw new CoreException(status);
			}
			
			InputStream in = null;
			try {
				XMLMemento memento = XMLMemento.createWriteRoot("runtime");

				if (runtimeId != null)
					memento.putString("runtime-id", runtimeId);
				if (serverId != null)
					memento.putString("server-id", serverId);
				if (serverProject)
					memento.putString("servers", "true");
				else
					memento.putString("servers", "false");
				in = memento.getInputStream();
				
				if (file.exists())
					file.setContents(in, true, true, monitor);
				else
					file.create(in, true, monitor);
			} catch (Exception e) {
				throw new CoreException(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, "", e));
			} finally {
				try {
					in.close();
				} catch (Exception e) {
					// ignore
				}
			}
			return;
		}
	}

	/**
	 * Returns the preferred runtime server for the project. This method
	 * returns null if the server was never chosen or does not currently exist. (if the
	 * server is recreated or was in a closed project, etc. this method will return
	 * the original value if it becomes available again)
	 *
	 * @return server org.eclipse.wst.server.core.IServer
	 */
	public IServer getDefaultServer() {
		loadPreferences();

		if (serverId == null || serverId.length() == 0)
			return null;
		
		IServer server = ServerCore.findServer(serverId);
		/*if (server != null && ServerUtil.containsModule(server, module))
			return server;
		else
			return null;*/
		return server;
	}

	/**
	 * Sets the default server.
	 * 
	 * @param server a server
	 * @param monitor a progress monitor
	 * @throws CoreException if anything goes wrong
	 */
	public void setDefaultServer(IServer server, IProgressMonitor monitor) throws CoreException {
		loadPreferences();
		
		String newServerId = null;
		if (server != null)
			newServerId = server.getId();
		if (serverId == null && newServerId == null)
			return;
		if (serverId != null && serverId.equals(newServerId))
			return;
		
		serverId = newServerId;
		savePreferences(monitor);
	}
	
	protected String getRuntimeTargetId() {
		loadPreferences();
		return runtimeId;
	}
	
	protected void setRuntimeTargetId(String newRuntimeId, IProgressMonitor monitor) throws CoreException {
		loadPreferences();
		runtimeId = newRuntimeId;
		savePreferences(monitor);
	}

	/**
	 * Returns the current runtime target type for the given project.
	 * 
	 * @return the runtime target
	 */
	public IRuntime getRuntimeTarget() {
		loadPreferences();
		if (runtimeId == null)
			return null;
		return ServerCore.findRuntime(runtimeId);
	}

	/**
	 * Sets the runtime target for the project.
	 * 
	 * @param runtime the target runtime
	 * @param monitor a progress monitor
	 * @throws CoreException if anything goes wrong
	 */
	public void setRuntimeTarget(IRuntime runtime, IProgressMonitor monitor) throws CoreException {
		loadPreferences();
		IRuntime oldRuntime = null;
		if (runtimeId != null)
			oldRuntime = ServerCore.findRuntime(runtimeId);
		setRuntimeTarget(oldRuntime, runtime, true, monitor);
	}

	protected void setRuntimeTarget(IRuntime oldRuntime, IRuntime newRuntime, boolean save, IProgressMonitor monitor) throws CoreException {
		Trace.trace(Trace.RUNTIME_TARGET, "setRuntimeTarget : " + oldRuntime + " -> " + newRuntime);
		
		if (oldRuntime == null && newRuntime == null)
			return;
		if (oldRuntime != null && oldRuntime.equals(newRuntime))
			return;
		
		IRuntimeTargetHandler[] handlers = ServerCore.getRuntimeTargetHandlers();
		if (handlers == null)
			return;
	
		int size = handlers.length;
		// remove old target
		if (oldRuntime != null) {
			IRuntimeType runtimeType = oldRuntime.getRuntimeType();
			for (int i = 0; i < size; i++) {
				IRuntimeTargetHandler handler = handlers[i];
				long time = System.currentTimeMillis();
				boolean supports = handler.supportsRuntimeType(runtimeType);
				Trace.trace(Trace.RUNTIME_TARGET, "  < " + handler + " " + supports);
				if (supports)
					((RuntimeTargetHandler)handler).removeRuntimeTarget(project, oldRuntime, monitor);
				Trace.trace(Trace.PERFORMANCE, "Runtime target: <" + (System.currentTimeMillis() - time) + "> " + handler.getId());
			}
		}
		
		// add new target
		if (newRuntime != null) {
			runtimeId = newRuntime.getId();
			if (save)
				savePreferences(monitor);
			IRuntimeType runtimeType = newRuntime.getRuntimeType();
			for (int i = 0; i < size; i++) {
				IRuntimeTargetHandler handler = handlers[i];
				long time = System.currentTimeMillis();
				boolean supports = handler.supportsRuntimeType(runtimeType);
				Trace.trace(Trace.RUNTIME_TARGET, "  > " + handler + " " + supports);
				if (supports)
					((RuntimeTargetHandler)handler).setRuntimeTarget(project, newRuntime, monitor);
				Trace.trace(Trace.PERFORMANCE, "Runtime target: <" + (System.currentTimeMillis() - time) + "> " + handler.getId());
			}
		} else {
			runtimeId = null;
			if (save)
				savePreferences(monitor);
		}
		
		fireRuntimeTargetChanged(newRuntime);
		Trace.trace(Trace.RUNTIME_TARGET, "setRuntimeTarget <");
	}

	/**
	 * Adds a new project properties listener.
	 * Has no effect if an identical listener is already registered.
	 * 
	 * @param listener the properties listener
	 * @see #removeProjectPropertiesListener(IProjectPropertiesListener)
	 */
	public void addProjectPropertiesListener(IProjectPropertiesListener listener) {
		Trace.trace(Trace.LISTENERS, "Adding project properties listener " + listener + " to " + this);
		
		if (listeners == null)
			listeners = new ArrayList();
		listeners.add(listener);
	}

	/**
	 * Removes an existing project properties listener.
	 * Has no effect if the listener is not registered.
	 * 
	 * @param listener the properties listener
	 * @see #addProjectPropertiesListener(IProjectPropertiesListener)
	 */
	public void removeProjectPropertiesListener(IProjectPropertiesListener listener) {
		Trace.trace(Trace.LISTENERS, "Removing project properties listener " + listener + " from " + this);
		
		if (listeners != null)
			listeners.remove(listener);
	}

	/**
	 * Fire a event because the runtime target changed.
	 *
	 * @param runtime org.eclipse.wst.server.core.IRuntime
	 */
	private void fireRuntimeTargetChanged(IRuntime runtime) {
		Trace.trace(Trace.LISTENERS, "->- Firing runtimeTargetChanged event: " + runtime + " ->-");
	
		if (listeners == null || listeners.isEmpty())
			return;
	
		int size = listeners.size();
		IProjectPropertiesListener[] ppl = new IProjectPropertiesListener[size];
		listeners.toArray(ppl);
	
		for (int i = 0; i < size; i++) {
			Trace.trace(Trace.LISTENERS, "  Firing runtimeTargetChanged event to " + ppl[i]);
			try {
				ppl[i].runtimeTargetChanged(project, runtime);
			} catch (Exception e) {
				Trace.trace(Trace.SEVERE, "  Error firing runtimeTargetChanged event to " + ppl[i], e);
			}
		}
	
		Trace.trace(Trace.LISTENERS, "-<- Done firing runtimeTargetChanged event -<-");
	}
	
	/**
	 * Returns <code>true</code> if this project can contain server artifacts, and
	 * <code>false</code> otherwise.
	 * 
	 * @return <code>true</code> if this project can contain server artifacts, and
	 *    <code>false</code> otherwise
	 */
	public boolean isServerProject() {
		loadPreferences();
		return serverProject;
	}

	/**
	 * Sets whether the project can contain server resources.
	 * 
	 * @param b <code>true</code> to allow the project to contain server
	 *    resources, or <code>false</code> to not allow the project to contain
	 *    servers
	 * @param monitor a progress monitor, or <code>null</code> if progress
	 *    reporting and cancellation are not desired
	 * @throws CoreException if there is a problem setting the server project
	 */
	public void setServerProject(boolean b, IProgressMonitor monitor) throws CoreException {
		loadPreferences();
		serverProject = b;
		savePreferences(monitor);
	}
	
	public String toString() {
		return "ProjectProperties[" + project + ", " + serverId + ", " + runtimeId + "]";
	}
}