
if (typeof com == "undefined") 
    com = {};
if (typeof com.rozengain == "undefined") 
    com.rozengain = {};

com.rozengain.Tweening = function(){
    this.control = null;				// -- the host object
    this.rootElement = null;			// -- the xaml root element
    this.fontSource = null;				// -- this will hold the load font
    this.displayObjects = [];			// -- this array stores programmatically created xaml objects
    this.tweens = [];					// -- this array stores the different tweening functions
	this.outputWindow = null;			// -- the output div
	this.tweenDuration = 2;				// -- standard tween duration
    this.transitionTypes = [			// -- JSTweener transition types
		"easeNone", "easeInQuad", "easeOutQuad", "easeInOutQuad", "easeInCubic", "easeOutCubic", "easeInOutCubic", 
		"easeOutInCubic", "easeInQuart", "easeOutQuart", "easeInOutQuart", "easeOutInQuart", "easeInQuint", "easeOutQuint", 
		"easeInOutQuint", "easeOutInQuint", "easeInSine", "easeOutSine", "easeInOutSine", "easeOutInSine", "easeInExpo", 
		"easeOutExpo", "easeInOutExpo", "easeOutInExpo", "easeInCirc", "easeOutCirc", "easeInOutCirc", "easeOutInCirc", 
		"easeInElastic", "easeOutElastic", "easeInOutElastic", "easeOutInElastic", "easeInBack", "easeOutBack", "easeOutBack", 
		"easeOutInBack", "easeInBounce", "easeOutBounce", "easeInOutBounce", "easeOutInBounce"
	];
    var cl = this;						// -- point to this object. this is used because we cannot use
    									// -- "this" inside the functions
    
    /**
     * Silverlight initialisation
     */
    this.createSilverlight = function(){
		cl.outputWindow = document.getElementById( "OutputWindow" );
		
        Silverlight.createObjectEx({
            source: "xml/Tweening.xaml",
            parentElement: document.getElementById("SilverlightControlHost"),
            id: "SilverlightControl",
            properties: {
                width: "900",
                height: "600",
                version: "1.0"
            },
            events: {
                onLoad: cl.handleLoad
            }
        });
    };
    
    /**
     * Onload event handler
     */
    this.handleLoad = function(cntrl, usrContext, rootElem){
        cl.control = cntrl;
        cl.rootElement = rootElem;
        cl.loadFonts();
    };
    
	/**
	 * Create a downloader for the font
	 */
    this.loadFonts = function(){
        var downloader = cl.control.createObject("downloader");
        downloader.addEventListener("completed", cl.fontDownloaded);
        downloader.open("GET", "assets/WEDNESDA.TTF");
        downloader.send();
    };
    
	/**
	 * Font loading completed
	 */
    this.fontDownloaded = function(sender, eventArgs){
        cl.fontSource = sender;
        cl.createObjects();
    };

	/**
	 * Programmatically create the xaml objects
	 */    
    this.createObjects = function(){
        for (var i = 0; i < 15; i++) {
            var xamlFragment = '' +
				 '<Canvas Width="75" Height="26">' +
					'<Canvas.RenderTransform>'+
		      			'<TransformGroup>' +
		        			'<RotateTransform CenterX="37.5" CenterY="13" Angle="0"/>' +
							'<ScaleTransform ScaleX="1.0" ScaleY="1.0" />' +
							'<SkewTransform AngleX="0" AngleY="0" />' + 
		      			'</TransformGroup>' + 
		    		'</Canvas.RenderTransform>' +
					'<TextBlock Width="75" Height="26" />' +
				'</Canvas>';
			
            var displayObject = cl.control.content.createFromXaml(xamlFragment, true);
            
            displayObject["Canvas.Left"] = 80 + (Math.random() * ( cl.rootElement.width - 160 ) );
            displayObject["Canvas.Top"] = 80 + (Math.random() * ( cl.rootElement.height - 160 ) );
			
			var textBlock = displayObject.children.getItem( 0 );
            textBlock.text = String.fromCharCode( 65 + ( Math.random() * 25 ) );
            textBlock.setFontSource( cl.fontSource );
            textBlock.fontFamily = "Wednesday";
            textBlock.foreGround = cl.getRandomColor();
            textBlock.fontSize = "100";
            
            cl.rootElement.children.add( displayObject );
			
			// -- add the object to an array for easy access
            cl.displayObjects.push( displayObject );
        }
        
        cl.initialiseTweens();
		cl.doTween( null, null );
    };
	
	/**
	 * Perform a tween on a random object
	 */
	this.doTween = function()
	{
		var object = cl.getRandomObject();
		
		cl.tweens[ parseInt( Math.random() * cl.tweens.length ) ]( object );		
	};
    
	/**
	 * Create the tween function array
	 */
    this.initialiseTweens = function(){
		cl.tweens = [
			cl.positionTween,
			cl.scaleTween,
			cl.angleTween,
			cl.skewTween
		];
    };
    
	/**
	 * Tweens the object's positin 
	 */
    this.positionTween = function( object, index )
	{
		var tweenType = cl.getRandomTweenType();
		var left = 80 + parseInt( (Math.random() * ( cl.rootElement.width - 160 ) ) );
		var top = 80 + parseInt( (Math.random() * ( cl.rootElement.height - 160 ) ) );
		
        JSTweener.addTween(object, {
            "Canvas.Left": left,
            "Canvas.Top": top,
            time: cl.tweenDuration,
            transition: tweenType,
			onComplete: cl.doTween
        });
		
		cl.out(
			"Canvas Position", 
			"Transition type: " + tweenType, 
			"\"Canvas.Left\": " + left, 
			"\"Canvas.Top\": " + top
		);
    };
    
	/**
	 * Tweens the object's angle
	 */
    this.angleTween = function( object )
	{		
		var transformGroup = object.renderTransform;
		var rotateTransform = transformGroup.children.getItem( 0 );
		var tweenType = cl.getRandomTweenType();
		var angle = parseInt( Math.random() * 360 );
		
     	JSTweener.addTween( rotateTransform, {
            angle: angle,
            time: cl.tweenDuration,
            transition: tweenType,
			onComplete: cl.doTween
        });
		
		cl.out(
			"RotateTransform", 
			"Transition type: " + tweenType, 
			"angle: " + angle
		);
    };

	/**
	 * Tweens the object's scale
	 */
    this.scaleTween = function( object )
	{
		var transformGroup = object.renderTransform;
		var scaleTransform = transformGroup.children.getItem( 1 );
		var tweenType = cl.getRandomTweenType();
		var scaleX = 0.5 + parseInt( Math.random() * 2 );
		var scaleY = 0.5 + parseInt( Math.random() * 2 );
		
     	JSTweener.addTween(scaleTransform, {
			scaleX: scaleX,
            scaleY: scaleY,
            time: cl.tweenDuration,
            transition: tweenType,
			onComplete: cl.doTween
        });
		
		cl.out( 
			"ScaleTransform",
			"Transition type: " + tweenType, 
			"scaleX: " + scaleX,
			"scaleY: " + scaleY
		);
    };
	
	/**
	 * Tweens the object's skewing
	 */
	this.skewTween = function( object )
	{
		var transformGroup = object.renderTransform;
		var skewTransform = transformGroup.children.getItem( 2 );
		var tweenType = cl.getRandomTweenType();
		var angleX = parseInt( Math.random() * 60 ) - 30;
		var angleY = parseInt( Math.random() * 90 ) - 45;
		
     	JSTweener.addTween( skewTransform, {
			angleX: angleX,
            angleY: angleY,
            time: cl.tweenDuration,
            transition: tweenType,
			onComplete: cl.doTween
        });
		
		cl.out( 
			"SkewTransform",
			"Transition type: " + tweenType, 
			"angleX: " + angleX,
			"angleY: " + angleY
		);
    };
	
	/**
	 * Returns a random tween type
	 */
    this.getRandomTweenType = function()
	{
        return cl.transitionTypes[parseInt(Math.random() * cl.transitionTypes.length)];
    };
	
	/**
	 * Returns a random programmatically created xaml object
	 */
	this.getRandomObject = function()
	{
		return cl.displayObjects[parseInt(Math.random() * cl.displayObjects.length)];
	};

	/**
	 * Returns a random argb color in hex format
	 */
    this.getRandomColor = function(){
        var r = parseInt(Math.random() * 256).toString(16);
        var g = parseInt(Math.random() * 256).toString(16);
        var b = parseInt(Math.random() * 256).toString(16);
        
        if (r.length == 0) 
            r = "00";
        else 
            if (r.length == 1) 
                r = "0" + r;
        
        if (g.length == 0) 
            g = "00";
        else 
            if (g.length == 1) 
                g = "0" + g;
        
        if (b.length == 0) 
            b = "00";
        else 
            if (b.length == 1) 
                b = "0" + b;
        
        return "#ff" + r + "" + g + "" + b;
    };
    
	/**
	 * Output to the OutputWindow div
	 */
	this.out = function()
	{
		var s = "";
		for( var i=0; i < arguments.length; i++ )
		{
			s += arguments[ i ] + "<br/>";
		}
		
		cl.outputWindow.innerHTML = s;
	}
    
	/**
	 * Start the application
	 */
    this.createSilverlight();
};
