package sso;

import java.sql.*;

public class Lock extends Immobile
{
	protected boolean	locked;			// true if locked
	protected Thing		key;			// game object required to unlock
	protected int		lockDifficulty;	// difficulty to pick or lock without key
	protected GameObject	host;		// host object for lock
	protected Trap		trap;			// trap

	// statics
	public static final String picklockSkill = "sso.skill.PickLock";

	/**
	 *  Protected constructor. Use factory method for new lock.
	 */
	protected Lock()
	{
		super();
	}

	/**
	 *  Public Factory Method. Get a new Lock object.
	 */
	public static Lock createLock()
	{
		Lock l = new Lock();
		l.init();
		return l;
	}

	/**
	 *  Initializer for new locks.
	 */
	protected void init()
	{
		super.init();

		locked = false;
		key = null;
		lockDifficulty = 10;
		host = null;
		trap = null;
	}

	/**
	 *  Is the lock locked?
	 */
	public boolean isLocked()
	{
		return locked;
	}

	/**
	 *  Set the lock's locked status
	 */
	public void setLocked(boolean locked)
	{
		this.locked = locked;

		propChanged("locked");
	}

	/**
	 *  Get the lock's key
	 */
	public Thing getKey()
	{
		return key;
	}

	/**
	 *  Set the lock's key
	 */
	public void setKey(Thing key)
	{
		this.key = key;

		propChanged("key");
	}

	/**
	 *  Get the lock difficulty
	 */
	public int getLockDifficulty()
	{
		return lockDifficulty;
	}

	/**
	 *  Set the lock difficulty
	 */
	public void setLockDifficulty(int diff)
	{
		lockDifficulty = diff;
	
		propChanged("lockDifficulty");
	}

	/**
	 *  Get the lock host
	 */
	public GameObject getHost()
	{
		return host;
	}

	/**
	 *  Set the lock host
	 */
	public void setHost(GameObject go)
	{
		host = go;

		propChanged("host");
	}

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

	/**
	 *  Is the object trapped?
	 */
	public boolean isTrapped()
	{
		return trap != null;
	}

	/**
	 *  Set the trap object for this lock
	 */
	public void setTrap(Trap trap)
	{
		this.trap = trap;
		this.trap.setHost(this);

		propChanged("trap");
	}

	/**
	 *  Attempt to pick the lock
	 */
	public boolean pickLock(PC victim)
	{
		boolean o_locked = locked;
	
		// trigger a trap, if present
		if (isTrapped())
		{
			if (trap.isArmed())
			{
				trap.trigger(victim);
			}
		}

		// attempt to pick the lock
		locked = victim.roll(picklockSkill, lockDifficulty) > lockDifficulty;
		
		propChanged("locked");

		return o_locked != locked;
	}

	/**
	 *  Attempt to lock the lock
	 */
	public boolean lock(PC victim, Thing o_key)
	{
		if (locked)
		{
			boolean o_locked = locked;
	
			if (key != null)
			{
				if (!key.equals(o_key))
				{
					if (isTrapped())
					{
						trap.trigger(victim);
					}
				}
				else
				{
					locked = true;
				}
			}
			else
			{
				locked = true;
			}
	
			return o_locked != locked;
		}
		return true;
	}

	/**
	 *  Attempt to unlock the lock
	 */
	public boolean unlock(PC victim, Thing o_key)
	{
		if (!locked)
		{
			boolean o_locked = locked;

			if (key != null)
			{
				if (!key.equals(o_key))
				{
					if (isTrapped())
					{
						trap.trigger(victim);
					}
				}
				else
				{
					locked = false;
				}
			}
			else
			{
				locked = false;
			}

			return o_locked != locked;
		}
		return true;
	}


	/**
	 *  Create the rows needed to store the Lock
	 */
	protected void createRows()
	{
		super.createRows();

		Statement stmt = null;

		try
		{
			stmt = Persistant.getStatement();

			stmt.executeUpdate("INSERT INTO Lock (lock_id, locked, key_id, lock_diff, host_id, trap_id) SET (" + id + ", 0, -1, 10, -1, -1)");

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

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

			stmt = null;
		}
	}

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

		Statement stmt = null;

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

			stmt.executeUpdate("UPDATE Lock SET locked=" + (locked ? 1 : 0) + ", key_id=" + (key != null ? key.getID() : Registry.ID_INVALID) + ", lock_diff=" + lockDifficulty + ", host_id=" + (host != null ?  host.getID() : Registry.ID_INVALID) + ", trap_id=" + (trap != null ? trap.getID() : Registry.ID_INVALID) + " WHERE lock_id=" + id);

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

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

			stmt = null;
		}
	}

	/**
	 *  Load a Lock object
	 */
	public static Lock loadLock(int id)
	{
		Lock l = null;

		if (Registry.isLoaded(id))
		{
			l = (Lock)Registry.get(id);
		}
		else
		{
			l = new Lock();
			l.id = id;
			l.load();
		}

		return l;
	}

	/**
	 *  Load lock object data from the database
	 */
	protected void load()
	{
		super.load();

		Statement stmt = null;
		ResultSet rs = null;

		try
		{
			stmt = Persistant.getStatement();

			rs = stmt.executeQuery("SELECT * FROM Lock WHERE lock_id=" + id);

			while (rs.next())
			{
				locked = rs.getInt("locked") != 0;
				key = Thing.loadThing(rs.getInt("key_id"));
				lockDifficulty = rs.getInt("lock_diff");
				host = GameObject.loadGameObject(rs.getInt("host_id"));
				trap = Trap.loadTrap(rs.getInt("trap_id"));
			}

			rs.close();
			rs = null;

			stmt.close();
			stmt = null;
		}
		catch (SQLException e)
		{
			System.err.println("Trying to load Lock (" + 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 lock object
	 */
	public void unregister()
	{
		if (trap != null)
		{
			trap.unregister();
		}

		Statement stmt = null;

		try
		{
			stmt = Persistant.getStatement();

			stmt.executeUpdate("DELETE FROM Lock WHERE lock_id=" + id);

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

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

	/**
	 *  Tester
	 */
	public static void main(String [] args)
	{
		Lock l = Lock.createLock();
		l.store();
		l = Lock.loadLock(l.getID());
		l.unregister();
	}
}

