//
//					code.js
//
//	Magnet game sample app now ported to Javascript and WPF/E.
//

/*jsl:option explicit*/
/*jsl:import pageTV.js*/ 
/*jsl:import pageList.js*/ 
/*jsl:import pageChanList.js*/ 

// video player can't do relative paths so figure out where we are
BASE_URL = location.href;
BASE_URL = BASE_URL.substr( 0, BASE_URL.lastIndexOf( '/' ) );
BASE_URL = BASE_URL.substr( 0, BASE_URL.lastIndexOf( '/' ) );

var CELLWIDTH = 45;
var CELLHEIGHT = 25;
var GRIDWIDTH = 9;
var GRIDHEIGHT = 10;
var EXTGRIDHEIGHT = GRIDHEIGHT + 3;
var WARNINGROW = 9;
var MAGNETHEIGHT = 12;
var MAGNET_STARTING_COL = 4;

var BOARD_X = 194;
var BOARD_Y = 74;

var SCORE_X_CENTER = 95;

var LEVEL_X_CENTER = 95;

var METER_WIDTH = 28;
var METER_HEIGHT = 207;
var METER_X = 75;
var METER_Y = 250;
var METER_PIXELS_PER_BRICK = 3;
var BRICKS_PER_LEVEL = METER_HEIGHT / METER_PIXELS_PER_BRICK;

var NUM_FIREWORKS = 8;
var MAGNET_MAX_LOAD = 3;

var LAYOUT_POLL_DELAY = 500;
var g_width = -1;
var g_height = -1;

var g_aStars;
var g_aBlocks;
var magnetBlocks;

var cmdq = new Array();
var kq = new Array();

var KEY_LEFT = 37;
var KEY_UP = 38;
var KEY_RIGHT = 39;
var KEY_DOWN = 40;
var KEY_PAUSE = 80;		// P
var KEY_EXIT = 88;		// X
var KEY_ENTER = 13;
var KEY_ESC = 27;

// global time var
var Now = 0;

var rootReady = false;
var bodyReady = false;
var initd = false;

// hack to get key bubbles in mozilla
if( !document.all )
{
	document.onkeypress = onkey;
	document.onkeydown = onkey;
}

//
//						rootLoaded
//
//	Called when the Jolt control finishes init'ing up
//
function rootLoaded()
{
	rootReady = true;
	if( bodyReady )
	{
		init();
	}
}

//
//						bodyLoaded
//
//	Called when the main HTML page body finishes loading
//
function bodyLoaded()
{
	bodyReady = true;
	if( rootReady )
	{
		init();
	}
}

//
//						init
//
//	Called one the Jolt control and the HTML body are both finished loading
//
function init()
{
    if( initd )
        return;
        
	// find the control
    g_wpfctrl = document.getElementById("wpfobj");

    // make the fireworks
    createStars();
    
    // make the animated blocks
    initAnimBlocks();
    
    // make blocks grid
    g_aBlocks = new Array( EXTGRIDHEIGHT );
    var i;
    for( i = 0; i < g_aBlocks.length; i++ )
    {
        g_aBlocks[i] = new Array( GRIDWIDTH );
    }
    
    // make temp storage for attacted blocks
    magnetBlocks = new Array();
    
    
	// start the layout watcher
	pollResize();

	// only allow one init
	initd = true;
	
    // start the second timer
    onOneSecond();
    	
	// prime the pump for the main worker tick
	onTick();
	
	// launch the game logic
	launch();
}

//
//                      createStars
//
function createStars()
{
    // get handles to the stars
    var i;
    g_aStars = new Array();
    for( i = 0; i < 8; i++ )
    {
        var st = new Star();
        st.handle = g_aStars[i] = findName( "star" + i );
        st.handle.Opacity = 0;
        
        // find the animation handles for this star
        st.animX = findName( 'anStar' + i + 'x' );
        st.animY = findName( 'anStar' + i + 'y' );
        st.anim = findName( 'anStar' + i );
        
        g_aStars[i] = st;
    }
}


//
//						findName
//
//	Handles the annoying exception that FindName throws if the name isn't found
//
function findName( nm )
{
	var obj = null;
	try
	{
		obj = g_wpfctrl.FindName( nm );
	}
	catch( e ) {}
	return obj;
}

var layoutCnt = 0;

//
//						layout
//
function layout()
{
	// bw/bh now have reasonable aspect ratio dimensions
	var obj = document.getElementById( 'wpfediv' );
	obj.style.left = '0px';
	obj.style.top = '0px';
	obj.style.width = g_width + 'px';
	obj.style.height = g_height + 'px';

	g_wpfctrl.style.left = '0px';
	g_wpfctrl.style.top = '0px';
	//g_wpfctrl.style.width = g_width + 'px';
	//g_wpfctrl.style.height = g_height + 'px';
	g_wpfctrl.width = 10;
	g_wpfctrl.height = 10;
	g_wpfctrl.width = g_width;
	g_wpfctrl.height = g_height;
	
    var root = findName( "rootCanvas" );

	scaleElement( root, false );
}

//
//                              pollResize
//
//  Watch for changes in vertical size of body and width of containing div.
//
function pollResize()
{
    var delay = LAYOUT_POLL_DELAY;
    var b = document.body;

    // snapshot last known dimensions
    var curW = g_width;
    var curH = g_height;
    
    // update
    getClientSize();
    
    // see if we have to do anything
    if( g_width == curW && g_height == curH )
    {
        setTimeout( "pollResize()", delay );
        return;
    }

	// do a layout pass
	layout();
	
	// and keep watching
    setTimeout( "pollResize()", delay );
}

//
//                      getClientSize
//
//  Browser-dependent fetch of client area dimensions.
//
//  Sets global vars g_width and g_height.
//
function getClientSize()
{
    // get inner screen height and width, very browser dependent
    var x, y;
    if (self.innerHeight)
    {
        // all except Explorer
        x = self.innerWidth;
        y = self.innerHeight;
    }
    else if (document.documentElement && document.documentElement.clientHeight)
    {
        // Explorer 6 Strict Mode
        x = document.documentElement.clientWidth;
        y = document.documentElement.clientHeight;
    }
    else if (document.body)
    {
        // other Explorers
        x = document.body.clientWidth;
        y = document.body.clientHeight;
    }

	// remember new size	
	g_width = x;	
    g_height = y;
}

//
//						onkey
//
function onkey( ev )
{
    var evt = ev ? ev : window.event;
    var kc = evt.keyCode;
    
	switch( kc )
	{
	case KEY_LEFT:
	case KEY_RIGHT:
	case KEY_UP:
	case KEY_DOWN:
	case KEY_ENTER:
	    kq.push( kc );
		break;

    case KEY_PAUSE:
        fPaused = !fPaused;
        break;
        
	default:
		//alert( "kc: " + kc );
		break;
	}
}

//
//                      checkKey
//
function checkKey()
{
    var key = 0;
    if (kq.length != 0)
    {
        key = kq.shift();
    }
    return key;
}


//
//					toHexColor
//
function toHexColor( n )
{
	var s = '000000' + n.toString( 16 );
	s = s.substr( s.length - 6 );
	return '#' + s;
}


//
//						absmod
//
//	Absolute value modulus that wraps negative around to positive.
//
function absmod( n, range )
{
	while( n < 0 )
	{
		n += range;
	}
	return n % range;
}

type="text/javascript" 
//
//						absmod
//
//	Absolute value modulus that wraps negative around to positive.
//
function absmod( n, range )
{
	if( n >= 0 )
	{
		return n % range;
	}
	while( n < 0 )
	{
		n += range;
	}
	return n % range;
}



/* Used to scale objects to fit the control's size
 * If maintainAspectRatio is false, this will center the element.
 * @param element element to scale
 * @param agControl control to size the contents to
 * @param maintainAspectRatio false to stretch to fit, true to keep ratio.
 */
function scaleElement(element, maintainAspectRatio)
{
	//alert( "scale: " + element );
    var width = g_width;
    var height = g_height;
    
    var naturalWidth = 640;
    var naturalHeight = 480;
    
    var scaleRatio = naturalWidth / naturalHeight;
    var offsetX = 0;
    var offsetY = 0;
    
    if (maintainAspectRatio) {
        if (width / scaleRatio > height) {
            offsetX = (width - height * scaleRatio) / 2;
            width = height * scaleRatio;
        }
        else {
            offsetY = (height - width / scaleRatio) / 2;
            height = width / scaleRatio;
        }
    }
    
    var scaleX = width / naturalWidth;
    var scaleY = height / naturalHeight;
    setScale(element, scaleX, scaleY, offsetX, offsetY);
}

function setScale(element, x, y, offsetX, offsetY) {
    var renderTransform = "<TransformGroup>"
    renderTransform += "<ScaleTransform ScaleX='" + x + "' ScaleY='" + y + "'/>";
    renderTransform += "<TranslateTransform X='" + offsetX + "' Y='" + offsetY + "'/>";
    renderTransform += "</TransformGroup>";
    
    var transform = g_wpfctrl.createFromXaml(renderTransform);
    element.renderTransform = transform;
}

var statusTimeout = -1;

//
//						statusMessage
//
//	Pops an ugly little message up for a few seconds.
//
function statusMessage( sMsg )
{
	findName( 'tbDebugMsg' ).Text = sMsg;
	findName( 'cnvDebugMsg' ).Opacity = 1;
	if( statusTimeout != -1 )
	{
		clearTimeout( statusTimeout );
	}
	statusTimeout = setTimeout( 'hideStatusMessage()', 10000 );
}

//
//						hideStatusMessage
//
function hideStatusMessage()
{
	findName( 'cnvDebugMsg' ).Opacity = 0;
}

//
//                      random
//
function random( range )
{
    return Math.floor( Math.random() * range );
}

var startNow = -1;
//
//                      onOneSecond
//
//  Ticks every second to keep Now up to date.
//
function onOneSecond()
{
    Now = Math.round( new Date().getTime() / 1000);
    if( startNow == -1 )
    {
        startNow = Now;
    }
    Now -= startNow;
    
    setTimeout( "onOneSecond()", 1000 );
}

