package org.eclipse.update.examples.buildzip;

/*
 * (c) Copyright IBM Corp. 2000, 2002.
 * All Rights Reserved.
 */ 
 
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.Properties;
import java.util.StringTokenizer;

import org.eclipse.core.runtime.PluginVersionIdentifier;
import org.eclipse.update.core.ContentReference;
import org.eclipse.update.core.model.FeatureModel;
import org.eclipse.update.core.model.PluginEntryModel;
import org.eclipse.update.core.model.URLEntryModel;

/**
 * An example feature parser. It handles features packaged as
 * build zip's using the format used for integration and stable builds
 * posted on the downloads pages at www.eclipse.org
 * </p>
 * @since 2.0
 */

public class BuildZipFeatureParser {	
	
	private BuildZipFeatureFactory factory;
	private BuildZipPluginParser pluginParser;
	
	public BuildZipFeatureParser(BuildZipFeatureFactory factory) {
		this.factory = factory;
	}
	
	public FeatureModel parse(BuildZipFeatureContentProvider cp) throws Exception {				
		return parseFeature(cp);
	}
	
	private FeatureModel parseFeature(BuildZipFeatureContentProvider cp) throws Exception {		
		
		// get reference to the build manifest
		ContentReference manifestRef = cp.getFeatureBuildManifest();
		InputStream is = manifestRef.getInputStream();		
		
		// load buildmanifest.properties
		Properties manifest = new Properties();
		try {
			manifest.load(is);
		} finally {
			if (is!=null) try { is.close(); } catch(IOException e) {}
		}
		
		// populate feature model
		FeatureModel feature = factory.createFeatureModel();
		parseFeatureEntry(cp, feature, manifest);
		
		// parse plugin entries
		parsePluginEntries(cp, feature, manifest); 
		
		// parse non-plugin entries
		parseNonPluginEntries(cp, feature, manifest);
		
		// unpack feature entry content
		cp.unpackFeatureEntryContent(feature, null/*IProgressMonitor*/);
		
		return feature;
	}
	
	private void parseFeatureEntry(BuildZipFeatureContentProvider cp, FeatureModel feature, Properties manifest) throws Exception {
		
		// parse out build zip file name. It is assumed to be in the
		// form <package identifier>-<build date>-<target platform>.zip,
		// where
		//		<package identifier> is hyphen (-) separaterd token list
		//		<build date> is single all-numeric token
		//		<target platform> is hyphen (-) separaterd token list
		
		String pkgId = "";
		String target = "";
		String build = "";
		String state = "ID";
		boolean firstToken = true;
		String zipName = URLDecoder.decode(cp.getURL().getFile());
		int ix = zipName.lastIndexOf("/");
		if (ix != -1)
			zipName = zipName.substring(ix+1);
		if (zipName.endsWith(".zip")) {
			zipName = zipName.substring(0,zipName.length()-4);
		}
		StringTokenizer tokenizer = new StringTokenizer(zipName,"-",false);
		String token;
		while(tokenizer.hasMoreTokens()) {
			token = tokenizer.nextToken();
			try {
				Long.parseLong(token);
				state = "TARGET";
				target = "";
				firstToken = true;
				build = token+".0.0";
			} catch (NumberFormatException e) {
				if (state.equals("ID")) {
					pkgId += (firstToken ? "" : " ") + token;
				} else {
					target += (firstToken ? "" : " ") + token;
				}
				firstToken = false;
			}
		}
		
		// generate base feature attributes
		feature.setFeatureIdentifier(pkgId.replace(' ','.'));
		feature.setFeatureVersion(build);
		feature.setLabel(pkgId.substring(0,1).toUpperCase() + pkgId.substring(1) + " for " + target);
		feature.setProvider("www.eclipse.org");
		feature.setImageURLString("splash/splash_full.bmp");
		feature.setOS(target.replace(' ','-'));	
		
		// add description
		URLEntryModel description = factory.createURLEntryModel();
		description.setURLString("readme/readme.html");
		description.setAnnotation("x");
		feature.setDescriptionModel(description);
		
		// add license
		URLEntryModel license = factory.createURLEntryModel();
		license.setURLString("about.html");
		license.setAnnotation("You must view the full license by following the \"License\" link in the feature preview.\nSelecting \"Accept\" indicates that you have viewed and accepted the feature license.");
		feature.setLicenseModel(license);
		
		// add copyright
		URLEntryModel copyright = factory.createURLEntryModel();
		copyright.setURLString("notice.html");
		copyright.setAnnotation("x");
		feature.setCopyrightModel(copyright);
	}	
	
	private void parsePluginEntries(BuildZipFeatureContentProvider cp, FeatureModel feature, Properties manifest) throws Exception {
		
		Enumeration entries = manifest.keys();
		String plugin;
		String pluginId;
		String pluginVersion;
		String pluginBuildVersion;
		PluginEntryModel pluginEntry;
		while(entries.hasMoreElements()) {
			plugin = (String) entries.nextElement();
			if (plugin.startsWith("plugin@")) {
				pluginId = plugin.substring(7);
				pluginBuildVersion = manifest.getProperty(plugin);
				if (pluginBuildVersion.equals("HEAD")) {
					String featureVersion = feature.getFeatureVersion();
					int ix = featureVersion.indexOf(".");
					String featureMajor = ix==-1 ? featureVersion : featureVersion.substring(0,ix);
					pluginBuildVersion += "-" + featureMajor;
				}
				pluginEntry = factory.createPluginEntryModel();
				pluginVersion = parsePluginVersionInManifest(cp, pluginId, pluginEntry);
				if (pluginVersion != null) {
					pluginEntry.setPluginIdentifier(pluginId);
					pluginEntry.setPluginVersion((new PluginVersionIdentifier(pluginVersion)).toString()+"."+pluginBuildVersion);
					feature.addPluginEntryModel(pluginEntry);
				}
			}
		}		
	}
	
	private void parseNonPluginEntries(BuildZipFeatureContentProvider cp, FeatureModel feature, Properties manifest) throws Exception {
	//	NonPluginEntryModel nonPluginEntry = factory.createNonPluginEntryModel();
	//	nonPluginEntry.setIdentifier("root");
	//	feature.addNonPluginEntryModel(nonPluginEntry);
	}
	
	private String parsePluginVersionInManifest(BuildZipFeatureContentProvider cp, String pluginId, PluginEntryModel pluginEntry) {

		if (pluginParser == null)
			pluginParser = new BuildZipPluginParser();
				
		InputStream is = null;				
		ContentReference pluginManifest;
		try {
			// try plugin.xml
			pluginManifest  = cp.getPluginManifest(pluginId, false);
			is = pluginManifest.getInputStream();
			return pluginParser.parse(is);
		} catch (Exception e) {
			try {
				// retry with feature.xml
				pluginManifest  = cp.getPluginManifest(pluginId, true);
				is = pluginManifest.getInputStream();
				String result = pluginParser.parse(is);
				pluginEntry.isFragment(true);
				return result;
			} catch (Exception e2) {
				return null;
			}
		} finally {
			if (is != null) try { is.close(); } catch (IOException e) {}
		}
	}
}
