package net.sf.fmj.media.content.merge;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.media.IncompatibleSourceException;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.MediaProxy;
import javax.media.NoDataSourceException;
import javax.media.protocol.DataSource;

import net.sf.fmj.utility.LoggerSingleton;

/**
 * MediaProxy Handler for merge protocol/content type, allowing multiple merged data sources to be specified with a single URL.
 * Creates a merging datasource from all of the component datasources
 * that correspond to the (multiple) URLs embedded within the URL.
 * The separator characters used to separate the embedded URLs are
 * arbitrary, and are determined by looking at the first and last
 * character in the remainder.  This allows plenty of choices for
 * avoiding conflicts with characters within the embedded URLs.
 * Examples:
 * merge:[civil:/0][javasound://0]
 * merge:{civil:/0}{javasound://0}
 * merge:<civil:/0><javasound://0>
 * 
 * @author Ken Larson
 *
 */
public class Handler implements MediaProxy
{
	private static final Logger logger = LoggerSingleton.logger;
	
	private net.sf.fmj.media.protocol.merge.DataSource source;
	
	public DataSource getDataSource() throws IOException, NoDataSourceException
	{
		try
		{
			final String remainder = source.getLocator().getRemainder();
			
			if (remainder.length() < 3)
				throw new NoDataSourceException("URL is too short to contain start char, end char, and at least 1 embedded URL");
			
			final String startComponent = "" + remainder.charAt(0);
			final String stopComponent = "" + remainder.charAt(remainder.length() - 1);
			final String splitOn = "\\" + stopComponent + "\\" + startComponent;	// TODO: how do we know if we need to escape these?
			
			final String[] urlComponents = remainder.substring(1, remainder.length() - 1).split(splitOn);
			if (urlComponents.length == 0)
				throw new NoDataSourceException("No URLs embedded within URL: " + source.getLocator());
			
			final DataSource[] dataSourceComponents = new DataSource[urlComponents.length];
			
			for (int i = 0; i < urlComponents.length; ++i)
			{
				final String url = urlComponents[i];
				dataSourceComponents[i] = Manager.createDataSource(new MediaLocator(url));
			}
			
			try
			{
				return Manager.createMergingDataSource(dataSourceComponents);
			} catch (IncompatibleSourceException e)
			{
				logger.log(Level.WARNING, "" + e, e);
				throw new NoDataSourceException("" + e);
			}
		}
		catch (NoDataSourceException e)
		{
			logger.log(Level.WARNING, "" + e, e);
			throw e;
		}
	}

	public void setSource(DataSource source) throws IOException, IncompatibleSourceException
	{
		if (!(source instanceof net.sf.fmj.media.protocol.merge.DataSource))
			throw new IncompatibleSourceException();
		
		this.source = (net.sf.fmj.media.protocol.merge.DataSource) source;
	}

}
