package com.hammurapi.swf;

import java.io.File;
import java.io.IOException;
import java.util.ListIterator;

import com.flagstone.transform.DoAction;
import com.flagstone.transform.EventHandler;
import com.flagstone.transform.Movie;
import com.flagstone.transform.MovieTag;
import com.flagstone.transform.action.Action;
import com.flagstone.transform.action.GetUrl;
import com.flagstone.transform.button.DefineButton2;

/**
 * Processes SWF file. Parameters: <code>&lt;input file&gt; [&lt;output file&gt;]</code>. If second parameter is absent then the source file 
 * gets overwritten. 
 * <P/>For each DefineButton2 in the movie the processor iterates over its event handlers and event handler actions and:
 * <UL>
 * <LI>Replaces target in GetUrl() if GetUrl is in format <code>target(<i>&lt;new target&gt;</i>):<i>&lt;URL&gt;</i></code> with the new target.
 * If the new target is in format <code>_level<i>&lt;number&gt;</i></code> then the command loads a movie at <code>URL</code> to the player at 
 * specified layer. Examples: 
 * 	<UL>
 * 		<LI><code>target():http://www.hammurapi.com/somepage.html</code> - opens http://www.hammurapi.com/somepage.html
 * in the same browser frame.</LI>
 * 		<LI><code>target(myframe):http://www.hammurapi.com/somepage.html</code> - opens http://www.hammurapi.com/somepage.html
 * in <code>myframe</code> browser frame.</LI>
 * 		<LI><code>target(_level1):somemovie.swf</code> - loads somemovie.swf to layer 1 into the player.</LI>
 * 	</UL>
 * </LI>
 * <LI>Converts button's GetUrl URL's prefixed with <code>$DoAction:</code> into DoAction actions. In other words, button's GetUrl are converted into
 * frame's actions. For example, the button was configured to load a movie into the player <code>$DoAction:target(_level1):next.swf</code>.
 * After processing <code>next.swf</code> will be loaded when the player reaches the frame where the button is defined.
 * </LI>
 * </UL> 
 * If input file is a directory then the processor processes .swf files and recurses into subdirectories. 
 *  
 * @author Pavel Vlasov
 *
 */
public class SwfProcessor {
	
	private static final String TARGET_PREFIX = "target(";
	private static final String TARGET_SUFFIX = "):";
	private static final String DO_ACTION_PREFIX = "$DoAction:";
	private static final String SWF_EXTENSION = ".swf";

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		System.out.println("Parameters: <input file> [<output file>]");
		processFile(new File(args[0]), args.length==1 ? null : new File (args[1]));
	}

	private static boolean processFile(File in, File out) throws Exception {
		if (in.isDirectory()) {
			boolean ret = false;
			if (out!=null) {
				if (!out.mkdirs()) {
					throw new IOException("Could not create "+out.getAbsolutePath());
				}
			}
			for (File child: in.listFiles()) {
				if (child.getName().toLowerCase().endsWith(SWF_EXTENSION) || child.isDirectory()) {
					if (processFile(child, out==null ? null : new File(out, child.getName()))) {
						ret = true;
					}
				}
			}
			if (!ret) {
				out.delete();
			}
			return ret;
		} else {
			System.out.println("Processing "+in.getAbsolutePath()+(out==null ? "" : " -> "+out.getAbsolutePath()));
			Movie movie = new Movie();
			movie.decodeFromFile(in);
			ListIterator<MovieTag> tit = movie.getObjects().listIterator();
			while (tit.hasNext()) {
				MovieTag obj = tit.next();
				DoAction doActionTag = null;
				if (obj instanceof DefineButton2) {
					DefineButton2 button = (DefineButton2) obj;
					for (EventHandler event: button.getEvents()) {
						ListIterator<Action> ait = event.getActions().listIterator();
						while (ait.hasNext()) {
							Action action = ait.next();
							if (action instanceof GetUrl) {
								GetUrl gu = (GetUrl) action;
								String url = gu.getUrl();
								boolean doAction = url.startsWith(DO_ACTION_PREFIX);
								if (doAction) {
									url = url.substring(DO_ACTION_PREFIX.length());
								}
								if (url.startsWith(TARGET_PREFIX)) {
									int idx = url.indexOf(TARGET_SUFFIX, TARGET_PREFIX.length());
									if (idx!=-1) {
										gu = new GetUrl(url.substring(idx+TARGET_SUFFIX.length()), url.substring(TARGET_PREFIX.length(), idx));
										System.out.println("\t"+url+" -> "+gu);
										if (doAction) {
											if (doActionTag==null) {
												doActionTag = new DoAction();
											}
											doActionTag.getActions().add(gu);
										} else {
											ait.remove();
											ait.add(gu);
										}									
									}
								}
							}
						}
					}
					if (doActionTag!=null) {
						tit.add(doActionTag);
					}					
				}
			}
			
			movie.encodeToFile(out==null ? in : out);
			return true;
		}
	}

}
