// Copyright 2001-2005, Danger, Inc.  All Rights Reserved.
// This file is subject to the Danger, Inc. Sample Code License,
// which is provided in the file SAMPLE_CODE_LICENSE.
// Copies are also available from http://developer.danger.com/

package com.example.AudioDemo;

import danger.app.Application;
import danger.app.Event;
import danger.app.Timer;
import danger.ui.Screen;
import danger.ui.ScreenWindow;
import danger.ui.StaticText;
import danger.util.DEBUG;

/**
 * Implements the MainWindow class. It is created from a Screen resource. The
 * layout merely shows the current play state as a StaticText item that is
 * updated to properly reflect that value.
 * 
 * This object has different code for the 1.1 version, as compared to the 2.0
 * and greater version. In general, the goal is to have one source base, but
 * sometimes there are improvements in the OS that are compelling enough to
 * break that goal. Properly handling the Pause of the soundtrack is one of
 * these cases.
 * 
 * The SDK has a code file override feature which helps to avoid duplicating
 * the entire source tree. In this case, the single file that varies between
 * versions, MainWindow.java has a 1.1 specific file in the 'common' directory.
 * The 2.0 directory includes just the MainWindow.java file that compiles for
 * the 2.0 version of the OS, and uses the rest of the application code from
 * common.
 * 
 * 
 * In the 1.1 variant here, handling Pause is more difficult than in later
 * versions of the OS. The soundtrack needs to be Paused when a System Dialog
 * comes up over the MainWindow. The way to do this under 1.1 is to have a Timer
 * object that will continuously check for whether MainWindow is frontmost. If
 * it is not, the audio is paused. This is the correct UI for system dialogs,
 * including the Sound Profile chooser, Calendar events, and even the Menu
 * itself. The Timer works on a 1 second basis, so there can be as much as 1
 * second of lag before it is paused. This is why under the 2.0 variant, the
 * strategy changes.
 * 
 * Since this is the 1.1 variant, the UI event of
 * Hiptop2Event.DEVICE_BUTTON_CANCEL is used, even though this is never expected
 * to be seen.
 */
public class MainWindow extends ScreenWindow implements Resources, Commands {

	/**
	 * local reference for the application, to avoid the need for coercion.
	 */
	private AudioDemo mApplication;

	/**
	 * reference variables for the StaticText item in the window, to allow for
	 * updating the string.
	 */
	private StaticText mPlayingText;

	/**
	 * A timer object is necessary to check for system dialogs that may come up
	 * over the MainWindow. In that case, the Audio needs to be shut down.
	 */
	static private Timer sTimer;

	static private final boolean kTimerRepeats = true;

	static private final int kOneSecond = 1000;

	// ------------------------------------------------------------------------
	/**
	 * onDecoded is called after the window has been created from resources. The
	 * reason to override this routine is to allow access to screen widgets, so
	 * they can be updated when the play state changes.
	 * 
	 * This 1.1 version of the source uses the Window Listener, so that it can
	 * be called in response to a Timer event. This Timer event is the way that
	 * Pause needs to be implemented for older devices.
	 * 
	 * Under the 2.0 or greater OSes, this behavior is improved by using the
	 * onActivate and onDeactivate Window routines.
	 */
	public void onDecoded() {
		// get coerced reference to current App, it's used to update all window
		// widgets.
		mApplication = (AudioDemo) Application.getCurrentApp();

		// After the window is created, the StaticText field has a default
		// value that will be updated upon user menu choices.
		// Therefore, find and save a reference to the object of interest.
		mPlayingText = (StaticText) getDescendantWithID(ID_PLAYING_TEXT);

		// As the MainWindow has been fully created, now create a 1 second
		// timer, used to shut down the music for system alerts.
		// The events are sent to this object, MainWindow.
		sTimer = new Timer(kOneSecond, kTimerRepeats, this);
		sTimer.start();

		super.onDecoded();
	}

	/**
	 * Handles events. Called automatically whenever this window receives an
	 * event. The only events handled are related to the menu and Timer.
	 */
	public boolean receiveEvent(Event e) {
		switch (e.type) {
		case EVENT_MUSIC_OFF:
			DemoSounds.stopLoop();
			mPlayingText.setText(mApplication.getString(ID_STOPPED));

			DEBUG.p("MainWindow: EVENT_MUSIC_OFF");
			return true;

		case EVENT_MUSIC_ON:
			DemoSounds.startLoop();
			mPlayingText.setText(mApplication.getString(ID_PLAYING));

			DEBUG.p("MainWindow: EVENT_MUSIC_ON");
			return true;

		// When called for the Timer event, this needs to check if the
		// MainWindow is still frontmost. If not, the assumption is that a
		// System Alert has come up over the application, in which case the
		// music must be stopped. If the MainWindow is up, call resume,
		// which will have no deleterious effect if it was already running.
		case Event.EVENT_TIMER:
			if (Screen.isWindowActive(this)) {
				DemoSounds.resume();
			} else {
				DemoSounds.pause();
			}
			return true;
		}

		return super.receiveEvent(e);
	}

	/**
	 * Upon the Down Widget hit, play a Torpedo sound for JoyPad events. This is
	 * preferable to the Up Widget hit for something where the user expects an
	 * immediate response.
	 */
	public boolean eventWidgetDown(int inWhichWidget, Event inEvent) {
		switch (inWhichWidget) {

		// For the keypad hits, launch the torpedo sounds.
		case Event.DEVICE_ARROW_LEFT:
		case Event.DEVICE_ARROW_UP:
		case Event.DEVICE_ARROW_RIGHT:
		case Event.DEVICE_ARROW_DOWN:
			DemoSounds.startTorpedo(inWhichWidget);
			return true;

		case Event.DEVICE_BUTTON_JUMP:
			// Always make sure to call super.eventWidgetUp for this control so
			// the system can execute the correct behavior (returning to the
			// Jump screen with phone selected).
			break;
		}
		return super.eventWidgetDown(inWhichWidget, inEvent);
	}

	/**
	 * Handles device buttons, specifically the Cancel, and Done buttons.
	 */
	public boolean eventWidgetUp(int inWhichWidget, Event inEvent) {
		switch (inWhichWidget) {

		// This demonstrates how to use a control from Sidekick2 in a way that
		// is still compatible with original Sidekick devices. The
		// DEVICE_BUTTON_CANCEL event is defined in the Hiptop2Events.java file.
		// On original Sidekick devices, this event is never sent. On Sidekick2
		// devices, this event will be received and handled here.
		// In the 2.0 API realm, this could be "Event.DEVICE_BUTTON_CANCEL"
		// instead.
		case Hiptop2Events.DEVICE_BUTTON_CANCEL:
			mApplication.returnToLauncher();
			return true;

		// For both the Cancel or Back/Done button from the MainWindow, it will
		// jump back to the launcher screen to provide a better experience.
		case Event.DEVICE_BUTTON_BACK:
			mApplication.returnToLauncher();
			return true;
		}

		// Always make sure to call super.eventWidgetUp for other events so the
		// system can execute the correct behavior (e.g. returning to the Jump
		// screen with phone selected).
		return super.eventWidgetUp(inWhichWidget, inEvent);
	}
}
