/*
 * 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 flex.tools.debugger.cli;

import java.util.Vector;
import java.util.Iterator;

import flash.tools.debugger.Location;
import flash.tools.debugger.expression.ValueExp;


/**
 * An object that relates a CLI debugger breakpoint with an associated set
 * of CLI commands to perform.
 * 
 * A breakpoint can be enabled or disabled.  It can be set such
 * that it disabled or deletes itself after being hit N times.
 */
public class BreakAction
{
	// return values for getStatus()
	public final static int		RESOLVED = 1;
	public final static int		UNRESOLVED = 2;
	public final static int		AMBIGUOUS = 3;
	public final static int		NOCODE = 4;	// there is no executable code at the specified line

	/**
	 * This will be null if the user typed in a breakpoint expression which
	 * did not match any currently loaded location, but we have saved it
	 * (with status == UNRESOLVED) in case it gets resolved later when another
	 * SWF or ABC gets loaded.
	 */
	private LocationCollection	m_where;				// may be null

	/**
	 * This will be null if the breakpoint was created via the
	 * <code>BreakAction(String unresolvedLocation)</code> constructor.
	 */
	private String				m_breakpointExpression;	// may be null

	private Vector<String>		m_commands;
	private boolean				m_enabled;
	private boolean				m_autoDelete;
	private boolean				m_autoDisable;
	private boolean				m_silent;
	private boolean				m_singleSwf;			// is breakpoint meant for a single swf only
	private int					m_id;
	private int					m_hits;
	private ValueExp			m_condition;
	private String				m_conditionString;
	private int					m_status;
    private boolean             m_propagable;
    
	public BreakAction(LocationCollection c) throws NullPointerException
	{
		m_where = c;
		m_where.first().getFile();  // force NullPointerException if l == null
		m_status = RESOLVED;
		init();
	}

	public BreakAction(String unresolvedLocation)
	{
		m_breakpointExpression = unresolvedLocation;
		m_status = UNRESOLVED;
		init();
	}

	private void init()
	{
		m_id = BreakIdentifier.next();
		m_commands = new Vector<String>();
		m_propagable = true;
	}

	/* getters */
	public int					getCommandCount()				{ return m_commands.size(); }
	public String				commandAt(int i)				{ return m_commands.elementAt(i); }
	public Location				getLocation()					{ return (m_where != null) ? m_where.first() : null; }
    public LocationCollection	getLocations()					{ return m_where; }
	public int					getId()							{ return m_id; }
	public int					getHits()						{ return m_hits; }
	public boolean				isEnabled()						{ return m_enabled; }
	public boolean				isAutoDisable()					{ return m_autoDisable; }
	public boolean				isAutoDelete()					{ return m_autoDelete; }
	public boolean				isSilent()						{ return m_silent; }
	public boolean				isSingleSwf()					{ return m_singleSwf; }
	public ValueExp				getCondition()					{ return m_condition; }
	public String				getConditionString()			{ return m_conditionString; }
	public String				getBreakpointExpression()		{ return m_breakpointExpression; }
	public int					getStatus()						{ return m_status; }
    public boolean              isPropagable()                  { return m_propagable; }
    
	/* setters */
	public void addCommand(String cmd)					{ m_commands.add(cmd); }
	public void clearCommands()							{ m_commands.clear(); }
	public void addLocation(Location l)					{ m_where.add(l); }
	public void setEnabled(boolean enable)				{ m_enabled = enable; }
	public void setAutoDisable(boolean disable)			{ m_autoDisable = disable; }
	public void setAutoDelete(boolean delete)			{ m_autoDelete = delete; }
	public void setSilent(boolean silent)				{ m_silent = silent; }
	public void setCondition(ValueExp c, String s)		{ m_condition = c;  m_conditionString = s; }
	public void clearCondition()						{ setCondition(null, ""); } //$NON-NLS-1$
	public void hit()									{ m_hits++; }
	public void clearHits()								{ m_hits = 0; }
	public void setSingleSwf(boolean singleSwf)			{ m_singleSwf = singleSwf; }
	public void setBreakpointExpression(String expr)	{ m_breakpointExpression = expr; }
	public void setStatus(int status)					{ m_status = status; }
    public void setPropagable(boolean propagable)       { m_propagable = propagable; }
    
	public void setLocations(LocationCollection loc)
	{
		m_where = loc;
		if (loc != null)
			setStatus(RESOLVED);
	}

	/*
	 * Check to see if our location matches the requested one
	 */
    public boolean locationMatches(int fileId, int line, int isolateId)
    {
		boolean match = false;
		LocationCollection col = getLocations();
		if (col != null)
		{
			Iterator<Location> itr = col.iterator();
		
			// probe all locations looking for a match
			while(!match && itr.hasNext())
			{
				Location l = (Location)itr.next();
                if (l != null && l.getFile().getId() == fileId && l.getLine() == line && (isolateId == -1 || l.getIsolateId() == isolateId))
                	match = true;
			}
		}
		return match;
	}
}
