/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.cauldron.bld.ivy;

import static java.lang.String.format;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;

import org.apache.ivy.core.module.descriptor.Artifact;
import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.apache.ivy.core.resolve.ResolveData;
import org.apache.ivy.plugins.repository.Resource;
import org.apache.ivy.plugins.repository.url.URLResource;
import org.apache.ivy.plugins.resolver.BasicResolver;
import org.apache.ivy.plugins.resolver.util.ResolvedResource;
import org.apache.ivy.util.FileUtil;
import org.cauldron.bld.config.BldFactory;
import org.cauldron.bld.core.internal.model.osgi.RequiredBundle;
import org.cauldron.sigil.model.IModelElement;
import org.cauldron.sigil.model.common.VersionRange;
import org.cauldron.sigil.model.eclipse.ISigilBundle;
import org.cauldron.sigil.model.osgi.IBundleModelElement;
import org.cauldron.sigil.repository.IResolution;
import org.cauldron.sigil.repository.ResolutionException;

/**
 * This resolver is able to work with Sigil repositories.
 * It does not allow publishing.
 */
public class SigilResolver extends BasicResolver implements IBldResolver {
	/** the sigil-injected dependency organisation name */
	static final String ORG_SIGIL = "sigil";
	
	private IBldResolver resolver;
	private String config;
	private boolean extractBCP = false;
	private Map<String, Resource> resourcesCache = new HashMap<String, Resource>();
	
	/**
	 * no-args constructor required by Ivy.
	 * 
	 * XXX: It doesn't currently seem to matter that Ivy instantiates this many times,
	 * since SigilParser caches it, and the ProjectRepositoryProvider static cache
	 * prevents it being re-loaded unnecessarily.
	 * 
	 * If this should become a problem, then we will need to delegate to a singleton instance,
	 * as we have done in SigilParser.
	 */
	public SigilResolver() {
	}
	
	public void setConfig(String config) {
		this.config = config;
	}
	
	/**
	 * if true, resolver extracts any jars embedded in Bundle-ClassPath.
	 */
	public void setExtractBCP(String extract) {
		this.extractBCP = Boolean.parseBoolean(extract);
	}

	private IBldResolver getResolver() {
		if (resolver == null) {
			if (config == null) {
				throw new Error("SigilResolver: not configured. Specify config=\"PATH\" in ivysettings.xml.");
			}
			try {
				URI uri;
				File file = new File(config);
				
				if (file.isAbsolute()) {
					uri = file.toURI();
				} else {
    				URI cwd = new File(".").toURI();
    				uri = cwd.resolve(config);
				}
				
				Map<String, Properties> repositories = BldFactory.getConfig(uri).getRepositoryConfig();
				resolver = new BldResolver(repositories);
			} catch (IOException e) {
				throw new Error("SigilResolver: failed to configure: " + e);
			}
		}
		return resolver;
	}

	public IResolution resolveOrFail(IModelElement element, boolean transitive) throws ResolutionException {
		return getResolver().resolveOrFail(element, transitive);
	}

	public IResolution resolve(IModelElement element, boolean transitive) {
		return getResolver().resolve(element, transitive);
	}

	public String getTypeName() {
		return "sigil";
	}

	/*
	 * synthesize an ivy descriptor for a Sigil dependency. called after Sigil
	 * resolution, so descriptor already contains resolved version.
	 */
	public ResolvedResource findIvyFileRef(DependencyDescriptor dd, ResolveData data) {
		ResolvedResource ref = null;

		ModuleRevisionId id = dd.getDependencyRevisionId();

		if (!id.getOrganisation().equals(ORG_SIGIL)) {
			return null;
		}

		ISigilBundle bundle = resolve(id);
		if (bundle == null) {
			return null;
		}

		String symbolicName = id.getName();
		String version = bundle.getVersion().toString();

		Resource res = new SigilIvy(extractBCP ? bundle : null, symbolicName, version);
		ref = new ResolvedResource(res, version);

		Log.debug(format("findIvyFileRef: dd=%s => ref=%s", dd, ref));
		return ref;
	}

	@Override
	protected ResolvedResource findArtifactRef(Artifact artifact, Date date) {
		String name = artifact.getName();
		ModuleRevisionId id = artifact.getModuleRevisionId();

		if (!id.getOrganisation().equals(ORG_SIGIL)) {
			return null;
		}
		
		ISigilBundle bundle = resolve(id);
		if (bundle == null) {
			return null;
		}

		IBundleModelElement info = bundle.getBundleInfo();
		URI uri = info.getUpdateLocation();
		Resource res = null;

		try {
			URL url =  (uri != null) ? uri.toURL() : bundle.getLocation().toFile().toURL();
    		if (name.contains("!")) {
    			String[] split = name.split("!");
    			url = new URL("jar:" + url + "!/" + split[1] + "." + artifact.getExt());
    		}
			res = new URLResource(url);
		} catch (MalformedURLException e) {
			System.out.println("Oops! " + e);
		}

		String version = bundle.getVersion().toString();
		ResolvedResource ref = new ResolvedResource(res, version);

		Log.debug(format("findArtifactRef: artifact=%s, date=%s => ref=%s", artifact, date, ref));
		return ref;
	}

	private ISigilBundle resolve(ModuleRevisionId id) {
		String revision = id.getRevision();
		String range = revision;

		if (revision.indexOf(',') < 0) {
			// SigilParser has already resolved the revision from the import
			// version range.
			// We now need to locate the same bundle to get its download URL.
			// We must use an OSGi version range to specify the exact version,
			// otherwise it will resolve to "specified version or above".
			range = "[" + revision + "," + revision + "]";
		}

		RequiredBundle bundle = new RequiredBundle();
		bundle.setSymbolicName(id.getName());
		bundle.setVersions(VersionRange.parseVersionRange(range));

		try {
			IResolution resolution = resolveOrFail(bundle, false);
			ISigilBundle[] bundles = resolution.getBundles().toArray(new ISigilBundle[0]);
			if (bundles.length == 1) {
				return bundles[0];
			}
		} catch (ResolutionException e) {
			return null;
		}
		return null;
	}

	/*
	 * Implement BasicResolver abstract methods
	 */

	@Override
	protected long get(Resource res, File dest) throws IOException {
		FileUtil.copy(res.openStream(), dest, null);
		long len = res.getContentLength();
		Log.debug(format("get(%s, %s) = %d", res, dest, len));
		return len;
	}


	@Override
	public Resource getResource(String source) throws IOException {
		source = encode(source);
		Resource res = resourcesCache.get(source);
		if (res == null) {
			res = new URLResource(new URL(source));
			resourcesCache.put(source, res);
		}
		Log.debug(format("SIGIL: getResource(%s) = %d", source, res));
		return res;
	}

	private static String encode(String source) {
		return source.trim().replaceAll(" ", "%20");
	}

	@SuppressWarnings("unchecked")
	@Override
	protected Collection findNames(Map tokenValues, String token) {
		throw new Error("SigilResolver: findNames not supported.");
	}

	public void publish(Artifact artifact, File src, boolean overwrite) throws IOException {
		throw new Error("SigilResolver: publish not supported.");
	}

	public void beginPublishTransaction(ModuleRevisionId module, boolean overwrite) throws IOException {
		// stop publish attempts being silently ignored.
		throw new Error("SigilResolver: publish not supported.");
	}

	/*
	 * Synthesize a virtual ivy file for a Sigil dependency.
	 */
	static class SigilIvy implements Resource {
		private StringBuilder content = new StringBuilder();
		private String name;
		private boolean exists = true;

		private SigilIvy() {
		}

		public SigilIvy(ISigilBundle bundle, String module, String rev) {
			this.name = "sigil!" + module + "#" + rev;

			String org = ORG_SIGIL;
			// FIXME: make status and pub configurable
			String status = "release";
			String pub = "20080912162859";

			content.append("<ivy-module version=\"1.0\">\n");

			content.append(format(
					"<info organisation=\"%s\" module=\"%s\" revision=\"%s\" status=\"%s\" publication=\"%s\"/>\n",
					org, module, rev, status, pub));
			
			String bcp = readBundleClassPath(bundle);
			if (bcp != null) {
    			content.append("<publications>\n");
    			for (String j : bcp.split(",\\s*")) {
    				if (j.equals(".")) {
            			content.append("<artifact/>\n");
    				} else if (!j.endsWith("component-activator.jar")) {
    					if (j.endsWith(".jar"))
    						j = j.substring(0, j.length() - 4);
            			content.append(format("<artifact name=\"%s!%s\"/>\n", module, j));
        			}
    			}
    			content.append("</publications>\n");
			}

			// TODO: add dependencies?
			// <dependencies>
			// <dependency org="org.apache" name="log4j" rev="1.2.12"
			// revConstraint="[1.2,1.3)"/>
			// </dependencies>

			content.append("</ivy-module>\n");
		}
		
        private String readBundleClassPath(ISigilBundle bundle) {
        	if (bundle == null)
        		return null;
        	
        	URI uri = bundle.getBundleInfo().getUpdateLocation();
            InputStream is = null;
			try {
    			URL url =  (uri != null) ? uri.toURL() : bundle.getLocation().toFile().toURL();
				is = url.openStream();
            	JarInputStream js = new JarInputStream(is, false);
                Manifest m = js.getManifest();
                if (m != null)
                    return (String) m.getMainAttributes().getValue("Bundle-ClassPath");
			} catch (IOException e) {
			} finally {
				if (is != null) {
					try {
						is.close();
					} catch (IOException e2) {
					}
				}
			}
			
            return null;
        }

		public String toString() {
			return "SigilIvy[" + name + "]";
		}

		// clone is used to read checksum files
		// so clone(getName() + ".sha1").exists() should be false
		public Resource clone(String cloneName) {
			Log.debug("SigilIvy: clone: " + cloneName);
			SigilIvy clone = new SigilIvy();
			clone.name = cloneName;
			clone.exists = false;
			return clone;
		}

		public boolean exists() {
			return exists;
		}

		public long getContentLength() {
			return content.length();
		}

		public long getLastModified() {
			// TODO Auto-generated method stub
			Log.debug("NOT IMPLEMENTED: getLastModified");
			return 0;
		}

		public String getName() {
			return name;
		}

		public boolean isLocal() {
			return false;
		}

		@SuppressWarnings("deprecation")
		public InputStream openStream() throws IOException {
			return new java.io.StringBufferInputStream(content.toString());
		}
	}
}
