/*
 *
 *  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;

import flash.swf.tags.DefineTag;
import flash.swf.tags.DoABC;
import flash.swf.tags.FrameLabel;
import flash.swf.tags.ImportAssets;
import flash.swf.tags.SymbolClass;
import flash.swf.tags.DefineFont;
import flash.swf.types.ActionList;

import java.util.*;

/**
 * Represents one SWF frame.  Each frame runs its initActions,
 * doActions, and control tags in a specific order, so we group them
 * this way while forming the movie.
 */
public class Frame
{
	public List<ActionList> doActions;
	public List<Tag> controlTags;
	public FrameLabel label;
	public List<ImportAssets> imports;
	public int pos = 1;	

	private Map<String, DefineTag> exports;
	private List<DefineTag> exportDefs;

	public List<DoABC> doABCs;

	public SymbolClass symbolClass;

	public List<DefineFont> fonts;

	public Frame()
	{
		exports = new HashMap<String, DefineTag>();
		exportDefs = new ArrayList<DefineTag>();
		doActions = new ArrayList<ActionList>();
		controlTags = new ArrayList<Tag>();
		imports = new ArrayList<ImportAssets>();
		fonts = new ArrayList<DefineFont>();

		doABCs = new ArrayList<DoABC>();
		symbolClass = new SymbolClass();
	}

	public Iterator<Tag> getReferences()
	{
		ArrayList<Tag> list = new ArrayList<Tag>();

		// exported symbols
		for (Iterator<DefineTag> j = exportDefs.iterator(); j.hasNext();)
		{
			DefineTag def = j.next();
			list.add(def);
		}

        list.addAll( symbolClass.class2tag.values() );

		// definitions for control tags
		for (Iterator<Tag> j = controlTags.iterator(); j.hasNext();)
		{
			Tag tag = j.next();
			for (Iterator k = tag.getReferences(); k.hasNext();)
			{
				DefineTag def = (DefineTag) k.next();
				list.add(def);
			}
		}

		return list.iterator();
	}

    public void mergeSymbolClass(SymbolClass symbolClass)
    {
        this.symbolClass.class2tag.putAll( symbolClass.class2tag );
    }
	public void addSymbolClass(String className, DefineTag symbol)
	{      
        // FIXME: error below should be possible... need to figure out why it is happening when running 'ant frameworks'
		//DefineTag tag = (DefineTag)symbolClass.class2tag.get(className);
        //if (tag != null && ! tag.equals(symbol))
        //{
        //    throw new IllegalStateException("Attempted to define SymbolClass for " + className + " as both " +
        //            symbol + " and " + tag);
        //}
        this.symbolClass.class2tag.put( className, symbol );
	}

	public boolean hasSymbolClasses()
	{
		return !symbolClass.class2tag.isEmpty();
	}

	public void addExport(DefineTag def)
	{
		Object old = exports.put(def.name, def);
		if (old != null)
		{
			exportDefs.remove(old);
		}
		exportDefs.add(def);
	}

	public boolean hasExports()
	{
		return !exports.isEmpty();
	}

	public Iterator<DefineTag> exportIterator()
	{
		return exportDefs.iterator();
	}

	public void removeExport(String name)
	{
		Object d = exports.remove(name);
		if (d != null)
		{
			exportDefs.remove(d);
		}
	}

	public void setExports(Map definitions)
	{
		for (Iterator i = definitions.entrySet().iterator(); i.hasNext();)
		{
			Map.Entry entry = (Map.Entry) i.next();
			DefineTag def = (DefineTag) entry.getValue();
			addExport(def);
		}
	}

	public boolean hasFonts()
	{
		return !fonts.isEmpty();
	}

	public void addFont(DefineFont tag)
	{
		fonts.add(tag);
	}

	public Iterator<DefineFont> fontsIterator()
	{
		return fonts.iterator();
	}
}
