/*
 *
 *  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 flash.tools;

import flash.swf.Action;
import flash.swf.Header;
import flash.swf.TagDecoder;
import flash.swf.TagHandler;
import flash.swf.Dictionary;
import flash.swf.ActionConstants;
import flash.swf.MovieMetaData;
import flash.swf.tags.DefineButton;
import flash.swf.tags.DoAction;
import flash.swf.tags.DoInitAction;
import flash.swf.tags.PlaceObject;
import flash.swf.tags.DefineSprite;
import flash.swf.types.ActionList;
import flash.swf.types.ButtonCondAction;
import flash.swf.types.ClipActionRecord;
import flash.swf.actions.DefineFunction;
import flash.swf.actions.ConstantPool;
import flash.util.Trace;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;

/**
 * This class implements the TagHandler interface
 * and provides a mechanism for containing the
 * actions associated with a SWF.
 */
public class SwfActionContainer extends TagHandler
{
	boolean		errorProcessing = true;
	ActionList	m_master;

	// temporaries used while decoding
	Dictionary  m_dictionary; 
	Header		m_header;

    public SwfActionContainer(byte[] swf, byte[] swd)	{ this(new ByteArrayInputStream(swf), new ByteArrayInputStream(swd));	}
    public SwfActionContainer(InputStream swfIn)		{ this(swfIn, null); }

    public SwfActionContainer(InputStream swfIn, InputStream swdIn)
	{
		TagDecoder p = new TagDecoder(swfIn, swdIn);
		try
		{
			process(p);
			errorProcessing = false;
		}
		catch(IOException io)
		{
			if (Trace.error)
				io.printStackTrace();
		}
	}

	// getters 
	public ActionList	getMasterList() { return m_master; }
	public Header		getHeader()		{ return m_header; }
	public Dictionary	getDictionary() { return m_dictionary; }

	// Did we hit an error in processing the swf? 
	public boolean hasErrors() { return errorProcessing; }

	/**
	 * Ask a TagDecoder to do its magic, calling us 
	 * upon each encounter of a new tag.
	 */
	void process(TagDecoder d) throws IOException
	{
		m_master = new ActionList(true);
        d.setKeepOffsets(true);
		d.parse(this);
	}

	/**
	 * Return a path to an ActionList that contains the given offset
	 * if an exact match is not found then return the largest
	 * that does not exceed offset.
	 */
	public ActionLocation locationLessOrEqualTo(int offset)
	{
		ActionLocation l = new ActionLocation();
		locationLessOrEqualTo(l, m_master, offset);
		return l;
	}

    public static ActionLocation locationLessOrEqualTo(ActionLocation location, ActionList list, int offset)
	{
		int at = findLessOrEqualTo(list, offset);
		if (at > -1)
		{
			// we hit so mark it and extract a constant pool if any
			location.at = at;
			location.actions = list;

			Action a = list.getAction(0);
			if (a.code == ActionConstants.sactionConstantPool)
				location.pool = (ConstantPool)a;

			// then see if we need to traverse
			a = list.getAction(at);
			if ( (a.code == ActionConstants.sactionDefineFunction) ||
				 (a.code == ActionConstants.sactionDefineFunction2) )
			{
				location.function = (DefineFunction)a;
				locationLessOrEqualTo(location, ((DefineFunction)a).actionList, offset);
			}
			else if (a instanceof DummyAction)
			{
				// our dummy container, then we drop in
				locationLessOrEqualTo(location, ((DummyAction)a).getActionList(), offset);
			}
		}
		return location;
	}

	// find the index of the largest offset in the list that does not
	// exceed the offset value provided. 
	public static int findLessOrEqualTo(ActionList list, int offset)
	{
		int i = find(list, offset);
		if (i < 0)
		{
			// means we didn't locate it, so get the next closest one
			// which is 1 below the insertion point
			i = (-i - 1) - 1;
		}
		return i;
	}

	// perform a binary search to locate the offset within the sorted
	// list of offsets within the action list.
	// if no match then (-i - 1) provides the index of where an insertion
	// would occur for this offset in the list.
	public static int find(ActionList list, int offset)
	{
        int lo = 0;
        int hi = list.size()-1;

        while (lo <= hi)
        {
            int i = (lo + hi)/2;
            int m = list.getOffset(i);
            if (offset > m)
                lo = i + 1;
            else if (offset < m)
                hi = i - 1;
            else
                return i; // offset found
        }
        return -(lo + 1);  // offset not found, low is the insertion point
	}

	/**
	 * Dummy Action container for housing all of  our
	 * topmost level actionlists in a convenient form
	 */
	public class DummyAction extends Action
	{
		public DummyAction(ActionList list)
		{
			super(ActionConstants.sactionNone);
			m_actionList = list;
		}

		// getters/setters
		public ActionList		getActionList()					{ return m_actionList; }
		public String			getClassName()					{ return m_className; }
		public void				setClassName(String name)		{ m_className = name; }

		private ActionList		m_actionList;
		private String			m_className;
	}

	/**
	 * Store away the ActionLists for later retrieval
	 */
    DummyAction recordActions(ActionList list)
    {
		DummyAction da = null;
		if (list != null && list.size() > 0)
		{
			// use the first offset as our reference point
			int offset = list.getOffset(0);

			// now create a pseudo action for this action list in our master
			da = new DummyAction(list);
			m_master.setActionOffset(offset, da);
		}
		return da;
	}

	/**
	 * -----------------------------------------------
	 * The following APIs override TagHandler.
	 * -----------------------------------------------
	 */
	public void doInitAction(DoInitAction tag)
	{
		DummyAction a = recordActions(tag.actionList);

		// now fill in the class name if we can
		if (m_header.version > 6 && tag.sprite != null)
		{
			String __Packages = MovieMetaData.idRef(tag.sprite, m_dictionary);
			String className = (__Packages != null && __Packages.startsWith("__Packages")) ? __Packages.substring(11) : null; //$NON-NLS-1$
			a.setClassName(className);
		}
	}

	public void doAction(DoAction tag)
	{
		recordActions(tag.actionList);
	}


	public void defineSprite(DefineSprite tag)
	{
		// @todo need to support actions in sprites!!! 
	}

	public void placeObject2(PlaceObject tag)
	{
		if (tag.hasClipAction())
		{
            Iterator it = tag.clipActions.clipActionRecords.iterator();
            while (it.hasNext())
            {
    		    ClipActionRecord record = (ClipActionRecord) it.next();
   			    recordActions(record.actionList);
            }
		}
	}

	public void defineButton(DefineButton tag)
	{
		recordActions(tag.condActions[0].actionList);
	}

	public void defineButton2(DefineButton tag)
	{
        if (tag.condActions.length > 0)
        {
            for (int i=0; i < tag.condActions.length; i++)
            {
                ButtonCondAction cond = tag.condActions[i];
                recordActions(cond.actionList);
            }
		}
	}

	public void setDecoderDictionary(Dictionary dict)
	{
		m_dictionary = dict;
	}

	public void header(Header h)
	{
		m_header = h;
	}

	/**
	 * -----------------------------------------------
	 * END: override TagHandler.
	 * -----------------------------------------------
	 */
}
