/* $Id$
 *
 * Copyright (c) 1999 Xenonsoft Limited. All Rights Reserved.
 *
 * This software is protected by copyright. You are hereby notified from
 * now by reading this message. This software is also the confidential 
 * and proprietary information of Xenonsoft Limited.  ("Confidential
 * Information"). 
 *
 * This software is distributed under the Xenonsoft Public end user 
 * License ("XPeL"), where the machine-readable source code is provided 
 * under the "Open Source" model.
 * For more information, please read the file "LICENSE-XPL.txt" 
 */

// File:`CollisionHandler.java'
//
//
// DESCRIPTION
//	Collision Handler
// 
// Author
//
//	Peter Pilgrim
//	Mon May 24 00:33:27 BST 1999
// 
// RCS HEADER 
// 
//	$Author$
//	$Date$
//	$Source$
//	$Revision$    $State$    $Locker$
//
//
// History:
// --------------------------------------------------------------------------------
//	$Log
//

package xenon.humanoid;

import java.beans.*;				// for PropertyChangeListener
import java.awt.*;				// for Component, Graphics
import java.awt.event.*;			// for ActionEvent, ActionListener

import xenon.gamekit.*;				// for GameEngine, WorldObject, etc
import xenon.soundkit.*;			// for SoundEngine, PPMCAudioPlayer, etc

/**
 * The collision handler class that is to contains <b>static</b>
 * collision methods for the arcade game.
 *
 */
public class CollisionHandler {

    public final static EmptyListener EMPTY_LISTENER = new EmptyListener();
    
    public static void starshipAndAlien( 
	WorldObject starship, WorldObject alien )
    {
	// System.out.println( "starshipAndAlien("+starship+","+alien+")" );
	
	// if ( starship.isDestroyed() || alien.isDestroyed() ) return;

	GameEngine engine = starship.getGameEngine();

	OvalExplosion explosion = new OvalExplosion( 
	    engine, null,
	    starship.getWorldXpos(), starship.getWorldYpos(), Color.blue );
	explosion.setXVelocity( starship.getXVelocity() / 2 );
	explosion.setYVelocity( starship.getYVelocity() / 2 );
	starship.setXVelocity( starship.getXVelocity() / 3 );
	starship.setYVelocity( starship.getYVelocity() / 3 );

	engine.addWorldObject( explosion );

	starship.destroy();
	alien.destroy();

	engine.setLevelCompleted(false);	/* ! */

	explosion.addPropertyChangeListener( new PropertyChangeListener() {
	    public void propertyChange(PropertyChangeEvent evt) {
		if ( evt.getPropertyName().equals( WorldObject.DESTROYED_PROPERTY ) )
		{
		    WorldObject sprite = (WorldObject)evt.getSource();
		    GameEngine eng = sprite.getGameEngine();
		    eng.setPlayerDied(true);
		    eng.setLevelCompleted(false);
		    // System.out.println( "Player died - Dropping all humans now (2)" );
		    Starship ship = (Starship)eng.getPlayerObject();
		    ship.dropAllRescuedHumans( false );
		}
	    }
	} ) ;
    }

    public static void laserblastAndLander( 
	WorldObject laserblast, WorldObject lander )
    {
	// System.out.println( "laserblastAndLander("+laserblast+","+lander+")" );
	
	GameEngine engine = laserblast.getGameEngine();

	Explosion explosion = new Explosion( 
	    engine, null, 
	    lander.getWorldXpos(), lander.getWorldYpos(), Color.yellow );

	engine.addWorldObject( explosion );

	Lander lander1 = (Lander)lander;
	Human human1 = lander1.getCapturedHuman();
	if (human1 != null) {
	    // Bonus for freeing object
	    engine.incrementScore( lander1.getPointsScored() );
	    human1.setState( Human.STATE_FALLING );
	    human1.setImprisoner( null );
	    lander1.setCapturedHuman( null );
	    lander1.setState( Lander.STATE_HUNTING );
	}

	laserblast.destroy();
	lander.destroy();

	engine.incrementScore( lander1.getPointsScored() );
    }

    public static void laserblastAndHuman( 
	WorldObject laserblast, WorldObject human )
    {
	// System.out.println( "laserblastAndHuman("+laserblast+","+human+")" );
	
	GameEngine engine = laserblast.getGameEngine();

	if ( human instanceof Human ) {
	    Human rhuman1 = (Human)human;
	    
	    // Bugfix: Mon Aug 09 00:15:16 BST 1999
	    // Humans that are not rescued can be laser blasted!
	    if ( rhuman1.getState() != Human.STATE_RESCUED ) {
		Explosion explosion = new Explosion( 
		    engine, null, 
		    human.getWorldXpos(), human.getWorldYpos(), Color.white );
		
		engine.addWorldObject( explosion );
		
		// System.out.println( "Ouch human x:"+rhuman1.getWorldXpos()+
		// 		    " y:"+rhuman1.getWorldYpos() );
		PPMCAudioPlayer mcap = engine.getMCAudioPlayer();
		mcap.play( 10, rhuman1.getOuchSound().getSoundData() );

		laserblast.destroy();
		rhuman1.destroy();
	    }
	}
    }

    public static void laserblastAndBaiter( 
	WorldObject laserblast, WorldObject baiter )
    {
	// System.out.println( "laserblastAndBaiter("+laserblast+","+baiter")" );
	
	HumanoidGameEngine engine = (HumanoidGameEngine)laserblast.getGameEngine();

	Explosion explosion = new Explosion( 
	    engine, null, 
	    baiter.getWorldXpos(), baiter.getWorldYpos(), Color.yellow );

	engine.addWorldObject( explosion );

	engine.incrementScore( baiter.getPointsScored() );

	int world_xpos = (int)( Math.random() * engine.world_width );
	int world_ypos = (int)( Math.random() * engine.world_height );
	
	BonusFlyer flyer = new BonusFlyer( 
	    engine, baiter.getWorldXpos(), baiter.getWorldYpos(),
	    baiter.getXVelocity(), 0, baiter.getPointsScored() );
	engine.addWorldObject( flyer );

	Baiter newBaiter = new Baiter( 
	    engine, world_xpos, world_ypos, 14, 1 );
	newBaiter.setResponse( ( engine.level > 10 ? 0 : 1 ) );
	newBaiter.setBombletProbability( engine.bombletProbabilityBaiters );
	int delay = 32+(int)(Math.random()*32.0);
	Implosion implosion = new Implosion( 
	    engine, newBaiter, world_xpos, world_ypos, Color.yellow, delay );
	    
	laserblast.destroy();
	baiter.destroy();
	engine.addWorldObject( implosion );
    }

    public static void laserblastAndPod( 
	WorldObject laserblast, WorldObject pod )
    {
	// System.out.println( "laserblastAndPod("+laserblast+","+baiter")" );
	
	HumanoidGameEngine engine = (HumanoidGameEngine)laserblast.getGameEngine();

	//
	// The order of these following three statements are VERY
	// important.
	//
	// Normally the last alien, except for baiters, that is
	// destroyed by the player ends the sheets.  However pods
	// behave differently. If a pod is the last alien on a
	// sheet, we want to get a chance to create some more
	// alien swarmers. Beside we dont to make it too easy for
	// the player.
	//
 
	// 
	// Create the swarmers (FIRST)
	//
	engine.generateSwarmers( HumanoidGameEngine.NUMBER_OF_SWARMERS_PER_POD,
				 pod.getWorldXpos(), pod.getWorldYpos() );

	//
	// Destroy the pod and the laserblast (SECOND)
	//
	Explosion explosion = new Explosion( 
	    engine, null, 
	    pod.getWorldXpos(), pod.getWorldYpos(), Color.yellow );

	engine.addWorldObject( explosion );
	engine.incrementScore( pod.getPointsScored() );

	laserblast.destroy();
	pod.destroy();
    }

    public static void laserblastAndAlien( 
	WorldObject laserblast, WorldObject alien )
    {
	// System.out.println( "laserblastAndAlien("+laserblast+","+alien")" );
	
	HumanoidGameEngine engine = (HumanoidGameEngine)laserblast.getGameEngine();

	Explosion explosion = new Explosion( 
	    engine, null, alien.getWorldXpos(), alien.getWorldYpos(), 
	    alien.getRadarColor() );

	engine.addWorldObject( explosion );

	engine.incrementScore( alien.getPointsScored() );
	if ( alien instanceof Bomber ) {
	    Bomber bomber = (Bomber)alien;
	    PPMCAudioPlayer mcap = engine.getMCAudioPlayer();
	    mcap.play( 3, bomber.getDiedSound().getSoundData() );
	}

	if ( alien instanceof Swarmer ) {
	    Swarmer rswarmer1 = (Swarmer)alien;
	    PPMCAudioPlayer mcap = engine.getMCAudioPlayer();
	    mcap.play( 3, rswarmer1.getDiedSound().getSoundData() );
	}

	alien.destroy();
	laserblast.destroy();
    }
    
    public static void landerAndHuman( 
	WorldObject lander, WorldObject human )
    {
	// System.out.println( "landerAndHuman("+lander+","+human+")" );
	
	GameEngine engine = lander.getGameEngine();
	Lander lander1 = (Lander)lander;
	Human human1 = (Human)human;

	if ( lander1.getState() != Lander.STATE_MUTANT &&
	     human1.getState() == Human.STATE_FREE ) {
	    lander1.setState( Lander.STATE_CAPTURED );
	    human1.setState( Human.STATE_CAPTURED );
	    lander1.setCapturedHuman( human1 );
	    human1.setImprisoner( lander1 );
	}
    }

    public static void starshipAndHuman( 
	WorldObject starship, WorldObject human )
    {
	// System.out.println( "starshipAndHuman("+lander+","+human+")" );
	
	HumanoidGameEngine engine = (HumanoidGameEngine)starship.getGameEngine();
	Starship ship1 = (Starship)starship;
	Human human1 = (Human)human;

	if (human1.getState() == Human.STATE_FALLING ) {
	    human1.setState( Human.STATE_RESCUED );
	    human1.setImprisoner( ship1 );
	    ship1.addHuman( human1 );
	    engine.incrementScore( 500 );
	    human1.setVisible(true);
	    
	    /** Gets reference to multi channel audio player */
	    PPMCAudioPlayer audioPlayer = engine.getMCAudioPlayer();
	    audioPlayer.play( 5, engine.soundHuman.getSoundData() );

	    BonusFlyer flyer = new BonusFlyer( 
		engine, human.getWorldXpos(), human.getWorldYpos(),
		human.getXVelocity(), 0, 500 );
	    engine.addWorldObject( flyer );
	}
    }

    public static void registerAllCollisions()
    {
	CollisionMapDispatcher dispatcher = CollisionMapDispatcher.getInstance();

	dispatcher.addCollisionListener(
	    LaserBlast.class, Lander.class,
	    new CollisionListener() {
	    public void collisionDetected( WorldObject obj1, WorldObject obj2 ) {
		laserblastAndLander( obj1, obj2 );
	    }
	} );

	dispatcher.addCollisionListener(
	    Starship.class, Lander.class,
	    new CollisionListener() {
	    public void collisionDetected( WorldObject obj1, WorldObject obj2 ) {
		starshipAndAlien( obj1, obj2 );
	    }
	} );

	dispatcher.addCollisionListener(
	    Starship.class, Bomblet.class,
	    new CollisionListener() {
	    public void collisionDetected( WorldObject obj1, WorldObject obj2 ) {
		starshipAndAlien( obj1, obj2 );
	    }
	} );

	dispatcher.addCollisionListener(
	    LaserBlast.class, Human.class,
	    new CollisionListener() {
	    public void collisionDetected( WorldObject obj1, WorldObject obj2 ) {
		laserblastAndHuman( obj1, obj2 );
	    }
	} );

	dispatcher.addCollisionListener(
	    Lander.class, Human.class,
	    new CollisionListener() {
	    public void collisionDetected( WorldObject obj1, WorldObject obj2 ) {
		landerAndHuman( obj1, obj2 );
	    }
	} );

	dispatcher.addCollisionListener(
	    Starship.class, Human.class,
	    new CollisionListener() {
	    public void collisionDetected( WorldObject obj1, WorldObject obj2 ) {
		starshipAndHuman( obj1, obj2 );
	    }
	} );

	dispatcher.addCollisionListener(
	    LaserBlast.class, Baiter.class,
	    new CollisionListener() {
	    public void collisionDetected( WorldObject obj1, WorldObject obj2 ) {
		laserblastAndBaiter( obj1, obj2 );
	    }
	} );

	dispatcher.addCollisionListener(
	    LaserBlast.class, Bomber.class,
	    new CollisionListener() {
	    public void collisionDetected( WorldObject obj1, WorldObject obj2 ) {
		laserblastAndAlien( obj1, obj2 );
	    }
	} );

	dispatcher.addCollisionListener(
	    LaserBlast.class, Pod.class,
	    new CollisionListener() {
	    public void collisionDetected( WorldObject obj1, WorldObject obj2 ) {
		laserblastAndPod( obj1, obj2 );
	    }
	} );

	dispatcher.addCollisionListener(
	    LaserBlast.class, Swarmer.class,
	    new CollisionListener() {
	    public void collisionDetected( WorldObject obj1, WorldObject obj2 ) {
		laserblastAndAlien( obj1, obj2 );
	    }
	} );

	
	dispatcher.addCollisionListener(
	    Starship.class, Baiter.class,
	    new CollisionListener() {
	    public void collisionDetected( WorldObject obj1, WorldObject obj2 ) {
		starshipAndAlien( obj1, obj2 );
	    }
	} );

	dispatcher.addCollisionListener(
	    Starship.class, Bomber.class,
	    new CollisionListener() {
	    public void collisionDetected( WorldObject obj1, WorldObject obj2 ) {
		starshipAndAlien( obj1, obj2 );
	    }
	} );

	dispatcher.addCollisionListener(
	    Starship.class, Pod.class,
	    new CollisionListener() {
	    public void collisionDetected( WorldObject obj1, WorldObject obj2 ) {
		starshipAndAlien( obj1, obj2 );
	    }
	} );

	dispatcher.addCollisionListener(
	    Starship.class, Swarmer.class,
	    new CollisionListener() {
	    public void collisionDetected( WorldObject obj1, WorldObject obj2 ) {
		starshipAndAlien( obj1, obj2 );
	    }
	} );

	// Register redundant collisions
	dispatcher.addCollisionListener( 
	    Lander.class, Lander.class, EMPTY_LISTENER );
	dispatcher.addCollisionListener( 
	    Lander.class, Bomblet.class, EMPTY_LISTENER );
	
    }
    
    
    public static class EmptyListener implements CollisionListener {
	/**
	 * A method signature for two objects that have collided.
	 *
	 * @param obj1 the first object that collided
	 * @param obj2 the second object that collided
	 */
	public void collisionDetected( WorldObject obj1, WorldObject obj2 )
	{
	    // Do nothing
	}

    }
}

// fini
