package sso;

import java.sql.*;
import sso.event.*;

public class Window extends Wall implements Openable
{
	protected Lock		lock;			// lock on window
	protected Trap		trap;			// trap on window
	protected boolean	open;			// is window open?
	protected boolean	shuttered;		// is window shuttered? (blocks event
										// propagation)
	protected int		windowType;		// type of window

	// Window Types
	public final static int	GAP		= 0x01;
	public final static int	SLIT	= 0x02;
	public final static int	SASHED	= 0x04;
	public final static int	PLATE	= 0x08;

	// window sizes
	public final static int	PEEP	= 0x10;
	public final static int	SMALL	= 0x20;
	public final static int	MEDIUM	= 0x40;
	public final static int	LARGE	= 0x80;
	public final static int	WHOLE	= 0x100;

	// condition
	public final static int	BROKEN	= 0x200;

	// shap
	public final static int	HORIZ	= 0x1000;
	public final static int	VERT	= 0x2000;
	public final static int	SQUARE	= 0x4000;
	public final static int	ROUND	= 0x8000;

	// placement
	public final static int	TOP		= 0x10000;
	public final static int MIDDLE	= 0x20000;
	public final static int	BOTTOM	= 0x40000;
	

	/**
	 *  Protected constructor. Use a factory method instead.
	 */
	protected Window()
	{
		super();
		propEvents = true;		// windows can propagate events
	}

	/**
	 *  Factory method. Create a new Window.
	 */
	public static Window createWindow()
	{
		Window w = new Window();
		w.init();
		return w;
	}

	/**
	 *  Protected window initializer.
	 */
	protected void init()
	{
		super.init();

		lock = null;
		trap = null;
		open = false;
		shuttered = false;
		windowType = SASHED | MEDIUM | HORIZ | SQUARE | MIDDLE;
	}

	/**
	 *  Get the lock
	 */
	public Lock getLock()
	{
		return lock;
	}

	/**
	 *  Set the lock
	 */
	public void setLock(Lock lock)
	{
		this.lock = lock;
		this.lock.setHost(this);

		propChanged("lock");
	}

	/**
	 *  Get the trap
	 */
	public Trap getTrap()
	{
		return trap;
	}

	/**
	 *  Set the trap
	 */
	public void setTrap(Trap trap)
	{
		this.trap = trap;
		this.trap.setHost(this);
	
		propChanged("trap");
	}

	/**
	 *  Is the window open?
	 */
	public boolean isOpen()
	{
		return open;
	}

	/**
	 *  Open the window
	 */
	public boolean open(PC victim)
	{
		if (getLock() != null)
		{
			if (!getLock().isLocked() && !isOpen())
			{
				if (getTrap() != null)
				{
					if (getTrap().isArmed())
					{
						getTrap().trigger(victim);
					}
				}

				open = true;
				propChanged("open");
			}
		}
		else
		{
			open = true;
			propChanged("open");
		}

		return open;
	}

	/**
	 *  Close the window
	 */
	public boolean close(PC victim)
	{
		if (getTrap() != null)
		{
			if (getTrap().isArmed())
			{
				getTrap().trigger(victim);
			}
		}

		open = false;

		propChanged("open");

		return open;
	}

	/**
	 *  Is the window shuttered?
	 */
	public boolean isShuttered()
	{
		return shuttered;
	}

	/**
	 *  Shutter the window.
	 */
	public void shutter()
	{
		shuttered = true;

		propChanged("shuttered");
	}

	/**
	 *  Unshutter the window.
	 */
	public void unshutter()
	{
		shuttered = false;

		propChanged("shuttered");
	}

	/**
	 *  Get the window type
	 */
	public int getWindowType()
	{
		return windowType;
	}

	/**
	 *  Set the window type
	 */
	public void setWindowType(int type)
	{
		windowType = type;

		propChanged("windowType");
	}


	/**
	 *  Create the row needed to store this window object
	 */
	protected void createRows()
	{
		super.createRows();

		Statement stmt = null;

		try
		{
			stmt = Persistant.getStatement();

			stmt.executeUpdate("INSERT INTO Window (window_id, lock_id, trap_id, open, shuttered, window_type) SET (" + id + ", -1, -1, 1, 0, 0)");

			stmt.close();
			stmt = null;
		}
		catch (SQLException e)
		{
			System.err.println("Trying to create rows to store a Window (" + id
			+ "): " + e.getMessage());
		}

		if (stmt != null)
		{
			try
			{
				stmt.close();
			}
			catch (SQLException e)
			{
				//
			}

			stmt = null;
		}
	}

	/**
	 *  Store the Window
	 */
	public void store()
	{
		super.store();

		Statement stmt = null;

		try
		{
			stmt = Persistant.getStatement();

			if (lock != null)
			{
				lock.store();
			}

			if (trap != null)
			{
				trap.store();
			}

			stmt.executeUpdate("UPDATE Window SET lock_id=" + (lock != null ? lock.getID() : Registry.ID_INVALID) + ", trap_id=" + (trap != null ? trap.getID() : Registry.ID_INVALID) + ", open=" + (open ? "1" : "0") + ", shuttered=" + (shuttered ? "1" : "0") + ", window_type=" + windowType + " WHERE window_id=" + id);

			stmt.close();
			stmt = null;
		}
		catch (SQLException e)
		{
			System.err.println("Trying to store window (" + id + "): " +
			e.getMessage());
		}

		if (stmt != null)
		{
			try
			{
				stmt.close();
			}
			catch (SQLException e)
			{
				//
			}

			stmt = null;
		}
	}

	/**
	 *  Load a Window object.
	 */
	public static Window loadWindow(int id)
	{
		Window w = null;

		if (Registry.isLoaded(id))
		{
			w = (Window)Registry.get(id);
		}
		else
		{
			w = new Window();
			w.id = id;
			w.load();
		}

		return w;
	}

	/**
	 *  Load the window from the datbase.
	 */
	protected void load()
	{
		super.load();

		Statement stmt = null;
		ResultSet rs = null;

		try
		{
			stmt = Persistant.getStatement();

			rs = stmt.executeQuery("SELECT * FROM Window WHERE window_id=" + id);

			while (rs.next())
			{
				lock = Lock.loadLock(rs.getInt("lock_id"));
				trap = Trap.loadTrap(rs.getInt("trap_id"));
				open = rs.getInt("open") != 0;
				shuttered = rs.getInt("shuttered") != 0;
				windowType = rs.getInt("window_type");
			}

			rs.close();
			rs = null;

			stmt.close();
			stmt = null;
		}
		catch (SQLException e)
		{
			System.err.println("Trying to load Window (" + id + "): " +
			e.getMessage());
		}

		if (rs != null)
		{
			try
			{
				rs.close();
			}
			catch (SQLException e)
			{
				//
			}
			
			rs = null;
		}

		if (stmt != null)
		{
			try
			{
				stmt.close();
			}
			catch (SQLException e)
			{
				//
			}

			stmt = null;
		}
	}

	/**
	 *  Unregister the object from the database.
	 */
	public void unregister()
	{
		Statement stmt = null;

		try
		{
			if (lock != null)
			{
				lock.unregister();
			}

			if (trap != null)
			{
				trap.unregister();
			}
		
			stmt = Persistant.getStatement();

			stmt.executeUpdate("DELETE FROM Window WHERE window_id=" + id);
			
			stmt.close();
			stmt = null;
		}
		catch (SQLException e)
		{
			System.err.println("Trying to unregister Window (" + id + "): " +
			e.getMessage());
		}

		if (stmt != null)
		{
			try
			{
				stmt.close();
			}
			catch (SQLException e)
			{
				//
			}

			stmt = null;
		}

		super.unregister();
	}


	// Event handlers
	/**
	 *  Consume (do not propagate) action events under certain conditions.
	 *  Do not propagate speech events if window closed.
	 *  Do not propagate sight events if window shuttered.
	 */
	public void handleActionEvent(ActionEvent evt)
	{
		if (shuttered && !open)
		{
			// consume the event
			evt.setTTL(0);
		}
		else if (shuttered)
		{
			switch (evt.getFlag())
			{
				case ActionEvent.EMOTE:
				case ActionEvent.SNEAK:
				case ActionEvent.WALK:
				case ActionEvent.RUN:
				case ActionEvent.DESTROY:
				case ActionEvent.CREATE:
				case ActionEvent.DISAPPEAR:
				case ActionEvent.APPEAR:
				case ActionEvent.DODGE:
				case ActionEvent.HIDE:
				case ActionEvent.LIE:
				case ActionEvent.SEARCH:
				case ActionEvent.GIVE:
				case ActionEvent.STEAL:
				case ActionEvent.PICKLOCK:
				case ActionEvent.DISARM:
				case ActionEvent.STAND:
				case ActionEvent.SIT:
				  evt.setTTL(0);
			}
		}
		else if (!open)
		{
			switch(evt.getFlag())
			{
				case ActionEvent.UNKNOWN:
				case ActionEvent.TALK:
				case ActionEvent.ORDER:
				case ActionEvent.ORATE:
				case ActionEvent.SHOUT:
					evt.setTTL(0);
			}
		}

		// we really don't want wall to handle the event
//		super.handleActionEvent(evt);
	}

	
}

