/*
 *
 *  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.swf.types;

import java.util.Arrays;

import flash.swf.Action;
import flash.swf.ActionHandler;

/**
 * This class represents an array of AS2 byte codes.
 */
public class ActionList extends ActionHandler
{
	// start numbering internal opcodes at 256 to make sure we wont
	// collide with a real player opcode.  player opcodes are 8-bit.
	public static final int sactionLabel = 256;
	public static final int sactionLineRecord = 257;
	public static final int sactionRegisterRecord = 258;

	public ActionList()
	{
        this(false);
	}

    public ActionList(int capacity)
    {
        this(false, capacity);
    }

    public ActionList(boolean keepOffsets)
    {
        this(keepOffsets, 10);
    }

    public ActionList(boolean keepOffsets, int capacity)
    {
        if (keepOffsets)
            offsets = new int[capacity];
        actions = new Action[capacity];
        size = 0;
    }

	private int[] offsets;
	private Action[] actions;
	private int size;

    public boolean equals(Object object)
    {
        boolean isEqual = false;

        if (object instanceof ActionList)
        {
            ActionList actionList = (ActionList) object;

            if ( Arrays.equals(actionList.actions, this.actions) )
            {
                isEqual = true;
            }
        }

        return isEqual;
    }    

	public void visitAll(ActionHandler handler)
	{
		visit(handler, 0, size-1);
    }

	public void visit(ActionHandler handler, int startIndex, int endIndex)
	{
		endIndex = (endIndex < 0) ? size-1 : endIndex;
		for (int j=startIndex; j <= endIndex; j++)
		{
			Action a = actions[j];
			if (a.code != sactionLabel && a.code != sactionLineRecord)
			{
				// don't call this for labels
                if (offsets != null)
    				handler.setActionOffset(offsets[j], a);
                else
                    handler.setActionOffset(j, a);
			}
			a.visit(handler);
		}
    }

    public void setActionOffset(int offset, Action a)
    {
		insert(offset, a);
    }

	public void grow(int capacity)
	{
        if (offsets != null)
        {
            int[] newoffsets = new int[capacity];
            System.arraycopy(offsets,0,newoffsets,0,size);
            offsets = newoffsets;
        }

		Action[] newactions = new Action[capacity];
		System.arraycopy(actions,0,newactions,0,size);
		actions = newactions;
	}

	public int size()
	{
		return size;
	}

	public Action getAction(int i)
	{
		return actions[i];
	}

	public int getOffset(int i)
	{
		return offsets[i];
	}

	public void remove(int i)
	{
        if (offsets != null)
    		System.arraycopy(offsets, i+1, offsets, i, size-i-1);
		System.arraycopy(actions, i+1, actions, i, size-i-1);
		size--;
	}

	/**
	 * perform a binary search to find the requested offset.
	 * @param k
	 * @return the index where that offset is found, or -(ins+1) if
	 * the key is not found, and ins is the insertion index.
	 *
	 */
	private int find(int k)
	{
        if (offsets != null)
        {
            int lo = 0;
            int hi = size-1;

            while (lo <= hi)
            {
                int i = (lo + hi)/2;
                int m = offsets[i];
                if (k > m)
                    lo = i + 1;
                else if (k < m)
                    hi = i - 1;
                else
                    return i; // key found
            }
            return -(lo + 1);  // key not found, lo is the insertion point
        }
        else
        {
            return k;
        }
	}

	public void insert(int offset, Action a)
	{
		if (size==actions.length)
			grow(size*2);
		int i;
		if (size == 0 || offsets == null && offset == size || offsets != null && offset > offsets[size-1])
		{
			// appending.
			i = size;
		}
		else
		{
			i = find(offset);
			if (i < 0)
			{
				// offset not used yet.  compute insertion point
				i = -i - 1;
			}
			else
			{
				// offset already used.  if we are inserting a real action, make it be last
				if (a.code < 256)
				{
					// this is a real action, we want it to be last at this offset
					while (i < size && offsets[i] == offset)
						i++;
				}
			}
            if (offsets != null)
    			System.arraycopy(offsets, i, offsets, i+1, size-i);
			System.arraycopy(actions, i, actions, i+1, size-i);
		}
        if (offsets != null)
    		offsets[i] = offset;
		actions[i] = a;
		size++;
	}

    public void append(Action a)
    {
        int i=size;
        if (i == actions.length)
            grow(size*2);
        actions[i] = a;
        size = i+1;
    }

    public String toString()
    {
        StringBuilder stringBuffer = new StringBuilder();

        stringBuffer.append("ActionList: count = " + actions.length);
        stringBuffer.append(", actions = ");

        for (int i = 0; i < size; i++)
        {
            stringBuffer.append(actions[i]);
        }

        return stringBuffer.toString();
    }

	/**
	 * Return the index within this action list of the first
	 * occurence of the specified actionCode, searching foward
	 * starting at the given index
	 */
	public int indexOf(int actionCode, int startAt)
	{
		int at = -1;
		for(int i=startAt; at<0 && i<actions.length; i++)
		{
			Action a = getAction(i);
			if (a != null && a.code == actionCode)
				at = i;
		}
		return at;
	}

	/**
	 * Return the index within this action list of the first
	 * occurence of the specified actionCode, searching backward
	 * starting at the given index
	 */
	public int lastIndexOf(int actionCode, int startAt)
	{
		int at = -1;
		for(int i=startAt; at<0 && i>=0; i--)
		{
			Action a = getAction(i);
			if (a != null && a.code == actionCode)
				at = i;
		}
		return at;
	}

	// specialized indexOf and lastIndexOf that start at the beginning and end of the actions list respectively
	public int indexOf(int actionCode) { return indexOf(actionCode, 0); }
	public int lastIndexOf(int actionCode) { return lastIndexOf(actionCode, actions.length-1); }

    public void setAction(int i, Action action)
    {
        actions[i] = action;
    }
}
