package com.pocketthis.basic.xsl;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import javax.xml.transform.URIResolver;
import javax.xml.transform.stream.StreamSource;

import com.pocketthis.basic.xml.ObjectSource;
import com.pocketthis.basic.xml.ParsedFileException;

/**
 * @author cebert
 */
public final class URLDirectoryResolver implements URIResolver {

	public URLDirectoryResolver(ObjectSource importFileSource, File baseDir) {
		_importFileSource = importFileSource;
		_baseDirPath = Arrays.asList(stripTrailingSlash(baseDir.getAbsoluteFile().toURI().toString()).split(PATH_SPLIT_PATTERN));
	}

	public Source resolve(String href, String base) throws TransformerException {
		try {
			String subdir = getFileSubdir(base) + getUrlSubdir(href);
			final File file = (File) _importFileSource.getObject(subdir + getUrlFile(href));
			final StreamSource source = new StreamSource(file);
			source.setSystemId(file.getAbsoluteFile().toURI().toString());
			return source;
		} catch (IOException e) {
			throw new TransformerException(e);
		} catch (ParsedFileException e) {
			throw new TransformerException(e);
		}
	}

	private String getUrlFile(String href) {
		return new File(href).getName();
	}

	private String getUrlSubdir(String href) {
		List importDir = Arrays.asList(href.split(PATH_SPLIT_PATTERN));
		StringBuffer subdirBuffer = new StringBuffer();
		addPathElements(subdirBuffer, importDir, 0);
		String subdir = subdirBuffer.toString();
		return subdir;
	}

	private String getFileSubdir(String base) {
		if (base != null) {
			List importDir = Arrays.asList(base.split(PATH_SPLIT_PATTERN));
			int index = getFirstDifference(importDir);
			StringBuffer subdirBuffer = new StringBuffer();
			for (int i = index; i < _baseDirPath.size(); ++i) {
				subdirBuffer.append("..");
				subdirBuffer.append(URLDirectoryResolver.HREF_PATH_SEPARATOR);
			}
			addPathElements(subdirBuffer, importDir, index);
			String subdir = subdirBuffer.toString();
			return subdir;
		} else {
			return "";
		}
	}

	private void addPathElements(StringBuffer subdirBuffer, List importDir, final int startIndex) {
		for (int i = startIndex; i + 1 < importDir.size(); ++i) {
			subdirBuffer.append(importDir.get(i));
			subdirBuffer.append(URLDirectoryResolver.HREF_PATH_SEPARATOR);
		}
	}

	private int getFirstDifference(List importDir) {
		int lastMatchingElement;
		for (lastMatchingElement = 0; importDir.size() > lastMatchingElement && _baseDirPath.size() > lastMatchingElement; ++lastMatchingElement) {
			if (!importDir.get(lastMatchingElement).equals(_baseDirPath.get(lastMatchingElement))) {
				break;
			}
		}
		return lastMatchingElement;
	}

	private String stripTrailingSlash(String path) {
		if (path.lastIndexOf(URLDirectoryResolver.HREF_PATH_SEPARATOR) == path.length() - 1) {
			return path.substring(0, path.length() - 1);
		} else {
			return path;
		}
	}
	private final ObjectSource _importFileSource;
	private final List _baseDirPath;
	private static final char HREF_PATH_SEPARATOR = '/';
	private static final String PATH_SPLIT_PATTERN = "[/\\\\]+";
}