/*******************************************************************************
 * Copyright (c) 2009 Red Hat 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:
 *     Red Hat - Initial API and implementation
 *******************************************************************************/
package org.eclipse.wst.common.componentcore.internal.flat;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.wst.common.componentcore.internal.DependencyType;
import org.eclipse.wst.common.componentcore.internal.flat.VirtualComponentFlattenUtility.ShouldIncludeUtilityCallback;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualFolder;
import org.eclipse.wst.common.componentcore.resources.IVirtualReference;

public class FlatVirtualComponent implements IFlatVirtualComponent, ShouldIncludeUtilityCallback {
	
	public static class FlatComponentTaskModel extends HashMap<Object, Object> {
			private static final long serialVersionUID = 1L;
	}
	
	/**
	 * The datamodel, which may contain preferences, settings, or other data
	 * used by the various participants to determine how to properly 
	 * traverse this component. 
	 */
	private FlatComponentTaskModel dataModel;
	
	/**
	 * The root component being flattened. 
	 */
	private IVirtualComponent component;
	
	/**
	 * The list of participants to engage in the flattening process. 
	 */
	private IFlattenParticipant[] participants;

	/**
	 * The list of member resources for this component
	 */
	private List<IFlatResource> members = null;
	
	/**
	 * The list of child modules for this component
	 */
	private List<IChildModuleReference> children = null;
	
	
	public FlatVirtualComponent(IVirtualComponent component) {
		this(component, new FlatComponentTaskModel());
	}
	
	public FlatVirtualComponent(IVirtualComponent component, FlatComponentTaskModel dataModel) {
		this.component = component;
		this.dataModel = dataModel;
		participants = setParticipants();
		dataModel.put(EXPORT_MODEL, this);
	}
	
	/**
	 * Set the list of participants for this virtual component. 
	 * This is pulled from the datamodel. 
	 */
	protected IFlattenParticipant[] setParticipants() {
		Object o = dataModel.get(PARTICIPANT_LIST);
		if( o != null ) {
			if( o instanceof IFlattenParticipant )
				return new IFlattenParticipant[] { (IFlattenParticipant)o};
			if( o instanceof IFlattenParticipant[])
				return (IFlattenParticipant[])o;
			if( o instanceof List ) {
				List<IFlattenParticipant> l = (List<IFlattenParticipant>)o;
				return (IFlattenParticipant[]) l
						.toArray(new IFlattenParticipant[l.size()]);
			}
		}
		return new IFlattenParticipant[]{};
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.eclipse.wst.common.componentcore.internal.flat.IFlatVirtualComponent#fetchResources()
	 */
	public IFlatResource[] fetchResources() throws CoreException {
		if( members == null)
			cacheResources();
		return (FlatResource[]) members.toArray(new FlatResource[members.size()]);
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.eclipse.wst.common.componentcore.internal.flat.IFlatVirtualComponent#getChildModules()
	 */
	public IChildModuleReference[] getChildModules() throws CoreException {
		if( members == null )
			cacheResources();
		return (ChildModuleReference[]) children.toArray(new ChildModuleReference[children.size()]);
	}
	
	
	protected void cacheResources() throws CoreException {
		runInitializations();
		if( canOptimize()) {
			optimize(members, children);
		} else {
			treeWalk();
			runFinalizations(members);
		}
	}
	
	protected void runInitializations() {
		members = new ArrayList<IFlatResource>();
		children = new ArrayList<IChildModuleReference>();
		for( int i = 0; i < participants.length; i++ ) {
			participants[i].initialize(component, dataModel, members);
		}
	}
	
	protected boolean canOptimize() {
		for( int i = 0; i < participants.length; i++ ) {
			if( participants[i].canOptimize(component, dataModel))
				return true;
		}
		return false;
	}

	protected void optimize(List<IFlatResource> resources, List<IChildModuleReference> children) {
		for( int i = 0; i < participants.length; i++ ) {
			if( participants[i].canOptimize(component, dataModel)) {
				participants[i].optimize(component, dataModel, resources, children);
				return;
			}
		}
	}
	
	protected void runFinalizations(List<IFlatResource> resources) {
		for( int i = 0; i < participants.length; i++ ) {
			participants[i].finalize(component, dataModel, resources);
		}
	}
	
	protected void treeWalk() throws CoreException {
		if (component != null) {
			VirtualComponentFlattenUtility util = new VirtualComponentFlattenUtility(members, this);
			IVirtualFolder vFolder = component.getRootFolder();
			
			// actually walk the tree
			util.addMembers(component, vFolder, Path.EMPTY);

			//addRelevantOutputFolders(); // to be done in a participant later

			addConsumedReferences(util, component, new Path(""));
			addUsedReferences(util, component, new Path(""));
		}
	}
	
	/**
	 * Consumed references are, by definition, consumed, and should not
	 * be eligible to be exposed as child modules. They are consumed 
	 * directly into the module tree. 
	 * 
	 * The reference in question may have references of its own, both
	 * used and consumed. References of the child will be treated
	 * as references of the parent, whether consumed or used.  
	 * 
	 * A key difference in the handling of non-child USED references 
	 * as compared to CONSUMES is that CONSUMED references have their
	 * archiveName *ignored*, and its child members are directly consumed. 
	 * In contrast, a USED non-child keeps its archiveName as the folder name. 
	 *  
	 * @param vc
	 */
	protected void addConsumedReferences(VirtualComponentFlattenUtility util, IVirtualComponent vc, IPath root) throws CoreException {
		List consumableMembers = new ArrayList();
		Map<String, Object> options = new HashMap<String, Object>();
		options.put(IVirtualComponent.REQUESTED_REFERENCE_TYPE, IVirtualComponent.FLATTENABLE_REFERENCES);
		IVirtualReference[] refComponents = vc.getReferences(options);
    	for (int i = 0; i < refComponents.length; i++) {
    		IVirtualReference reference = refComponents[i];
    		if (reference != null && reference.getDependencyType()==IVirtualReference.DEPENDENCY_TYPE_CONSUMES) {
    			IVirtualComponent consumedComponent = reference.getReferencedComponent();
				if (consumedComponent.getRootFolder()!=null) {
					IVirtualFolder vFolder = consumedComponent.getRootFolder();
					util.addMembers(consumedComponent, vFolder, root.append(reference.getRuntimePath().makeRelative()));
					addConsumedReferences(util, consumedComponent, root.append(reference.getRuntimePath().makeRelative()));
					addUsedReferences(util, consumedComponent, root.append(reference.getRuntimePath().makeRelative()));
				}
    		}
    	}
	}
	
	/**
	 * This checks to see if any exportable file is actually a child module.
	 * Children modules will be exposed via the getChildModules() method. 
	 */
	public boolean shouldAddComponentFile(IVirtualComponent current, IFlatFile file) {
		for( int i = 0; i < participants.length; i++ ) {
			if( participants[i].isChildModule(component, dataModel, file)) {
				ChildModuleReference child = new ChildModuleReference(current.getProject(), file);
				children.add(child); 
				return false;
			} else if( !participants[i].shouldAddExportableFile(component, current, dataModel, file))
				return false;
		}
		return true;
	}

	protected void addUsedReferences(VirtualComponentFlattenUtility util, IVirtualComponent vc, IPath root) throws CoreException {
		Map<String, Object> options = new HashMap<String, Object>();
		options.put(IVirtualComponent.REQUESTED_REFERENCE_TYPE, IVirtualComponent.FLATTENABLE_REFERENCES);
		IVirtualReference[] allReferences = vc.getReferences(options);
    	for (int i = 0; i < allReferences.length; i++) {
    		IVirtualReference reference = allReferences[i];
			IVirtualComponent virtualComp = reference.getReferencedComponent();
			if (reference.getDependencyType() == DependencyType.USES ) {
				if( shouldIgnoreReference(reference))
					continue;
				
				if( !isChildModule(reference)) {
					addNonChildUsedReference(util, vc, reference, root.append(reference.getRuntimePath()));
				} else {
					ChildModuleReference cm = new ChildModuleReference(reference, root);
					List<IChildModuleReference> duplicates = new ArrayList();
					for( IChildModuleReference tmp : children ) {
						if(tmp.getRelativeURI().equals(cm.getRelativeURI()))
							duplicates.add(tmp);
					}
					children.removeAll(duplicates);
					children.add(cm);
				}
			}
    	}
	}
	
	/**
	 * Should we expose this used reference as a member file?
	 * 
	 * @param currentComponent the current component we're traversing
	 * @return true if it's a member file, false if it's a child module
	 */
	protected boolean isChildModule(IVirtualReference referencedComponent) {
		for( int i = 0; i < participants.length; i++ ) {
			if( participants[i].isChildModule(component, referencedComponent, dataModel))
				return true;
		}
		return false;
	}

	protected boolean shouldIgnoreReference(IVirtualReference referencedComponent) {
		for( int i = 0; i < participants.length; i++ ) {
			if( participants[i].shouldIgnoreReference(component, referencedComponent, dataModel))
				return true;
		}
		return false;
	}

	protected void addNonChildUsedReference(VirtualComponentFlattenUtility util, IVirtualComponent parent, 
			IVirtualReference reference, IPath runtimePath) throws CoreException {
		if( reference.getReferencedComponent().isBinary()) {
			handleNonChildUsedBinaryReference(util, parent, reference, runtimePath);
		} else /* !virtualComp.isBinary() */ {
			/*
			 * used references to non-binary components that are NOT child modules.
			 * These should be 'consumed' but maintain their name
			 * As of now I don't believe there are any such instances of this.
			 * I also believe in most cases, this probably is a child module that 
			 * the parent just doesn't know about.
			 * 
			 * Example: Ear Project consumes ESB project, Ear project does not 
			 * recognize ESB project as a child However, if the server adapter 
			 * can use nested exploded deployments (folders instead of zips),
			 * then this will still work. 
			 * 
			 * TODO Investigate / Discuss
			 */
			util.addMembers(reference.getReferencedComponent(), reference.getReferencedComponent().getRootFolder(), 
					runtimePath.append(reference.getArchiveName()));
		}
	}
	
	protected void handleNonChildUsedBinaryReference(VirtualComponentFlattenUtility util, IVirtualComponent parent, 
			IVirtualReference reference, IPath runtimePath) throws CoreException {
		// Binary used references must be added as a single file unless they're child modules
		final String archiveName2 = reference.getArchiveName();
		final String archiveName = new Path(archiveName2).lastSegment();
		final IVirtualComponent virtualComp = reference.getReferencedComponent();
		FlatFile mf = null;
		IFile ifile = (IFile)virtualComp.getAdapter(IFile.class);
		if( ifile != null ) {
			String name = null != archiveName ? archiveName : ifile.getName();
			mf = new FlatFile(ifile, name, runtimePath.makeRelative());
		} else {
			File extFile = (File)virtualComp.getAdapter(File.class);
			if( extFile != null ) {
				String name = null != archiveName ? archiveName : extFile.getName();
				mf = new FlatFile(extFile, name, runtimePath.makeRelative());
			}
		}
		
		if( mf != null ) {
			IFlatResource moduleParent = VirtualComponentFlattenUtility.getExistingModuleResource(members, mf.getModuleRelativePath());
			if (moduleParent != null && moduleParent instanceof IFlatFolder) {
				IFlatResource[] mf_members = ((IFlatFolder)moduleParent).members();
				for (int i = 0; i < mf_members.length; i++) {
					if (mf_members[i].getName().equals(mf.getName()))
						return;
				}
				VirtualComponentFlattenUtility.addMembersToModuleFolder((IFlatFolder)moduleParent, new FlatResource[]{mf});
			} else {
				if( shouldAddExportableFile(virtualComp, mf)) {
					if (mf.getModuleRelativePath().isEmpty()) {
						for( IFlatResource tmp : members) 
							if( tmp.getName().equals(mf.getName()))
								return;
						members.add(mf);
					} else {
						if (moduleParent == null) {
							moduleParent = VirtualComponentFlattenUtility.ensureParentExists(members, mf.getModuleRelativePath(), (IContainer)parent.getRootFolder().getUnderlyingResource());
						}
						VirtualComponentFlattenUtility.addMembersToModuleFolder((IFlatFolder)moduleParent, new FlatResource[] {mf});
					}
				} else {
					// Automatically added to children if it needed to be
				}
			}
		}
	}

	protected boolean shouldAddExportableFile(IVirtualComponent current, FlatFile file) {
		for( int i = 0; i < participants.length; i++ ) {
			if ( !participants[i].shouldAddExportableFile(component, current, dataModel, file))
				return false;
		}
		return true;
	}

	public IVirtualComponent getComponent() {
		return component;
	}
}
