﻿/* Build storyboard and add to Canvas.Resource
    sSBName:     Story board name (blank will generate unique name)
    aAnmiations: Array holding animation information in the following format:
        var aAnimations = 

*/
function AnimationBuilder(oRoot) {
    this.oRoot = oRoot;
    this.bXAMLLog = true;
    this.sXAMLLogId = "XAMLLog";

    this.build = function(sSBName, aAnimations, onComplete) {
        // Start storyboard fragment
        var aXamlFragment =  [
            '<Storyboard xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="', sSBName, '">'];
        
        // 0 Loop through aAnimations by target
        for (var i=0; i<aAnimations.length; i++) {
            var aTarg = aAnimations[i];
            
            // 1 Loop though target animations
            for (var j=0; j<aTarg[1].length; j++) {
                var aAnims = aTarg[1];
    	        
                // Create reference to property name
                var sProperty = aAnims[j][0];                
                
                // 
                switch (aAnims[j][0]) {
                    case "ScaleX":
                        sProperty = "(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)";
                        break;
                    case "ScaleY":
                        sProperty = "(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)";
                        break;
                     case "Rotation":
                        sProperty = "(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)";
                        break;   
                    default:
                        // Convert property to animation property
                        if (aAnims[j][0].indexOf(".") > -1) {
                            var sProperty = "(" + aAnims[j][0] + ")";
                        } else {
                            var sProperty = aAnims[j][0];
                        }    	                
                        break;
                }
                
	            // Define and create animation fragment.
                aXamlFragment.push('<DoubleAnimationUsingKeyFrames BeginTime="', aAnims[j][1], '" Storyboard.TargetName="',
                                    aTarg[0], '" Storyboard.TargetProperty="', sProperty, '">');     
                                               
                // 2 Loop through animation keyframes
                for (var k=0; k<aAnims[j][2].length; k++) {
                    // Create reference to animation from array
                    var aKeys = aAnims[j][2];
                    
                    // Create reference to target
                    var eTarget = this.oRoot.findname(aTarg[0]);
                    
                    // Initialise value variable
                    var nValue;
                    
                    if (typeof(aKeys[k][1]) == "number") {
                        nValue = aKeys[k][1];
                        
                    } else if (typeof(aKeys[k][1]) == "string") {
                        
                       
                        // Extract appropriate current value
                        if (aAnims[j][0] == "ScaleX") {
                            var nCurrent = eTarget.RenderTransform.Children.getItem(0).ScaleX;
                        } else if (aAnims[j][0] == "ScaleY") {
                            var nCurrent = eTarget.RenderTransform.Children.getItem(0).ScaleY;
                        } else if (aAnims[j][0] == "Rotation") {
                            var nCurrent = eTarget.RenderTransform.Children.getItem(2).Angle;    
                        } else {
                            var nCurrent = eTarget[aAnims[j][0]];
                        }
                        
                        // If the value is a string with a % in it, apply relative percentage as value
                        if (aKeys[k][1].indexOf("%") > -1) {
                            nValue = nCurrent * (Number(aKeys[k][1].replace("%", ""))/100);
                        } else {
                            // otherwise apply relative magnitude as value
                            nValue = nCurrent + Number(aKeys[k][1]);
                        }
                    }
                    
                    
                    // If the spline is not defined, apply a default linear line
                    if (typeof(aKeys[k][2]) == "undefined") {
                        aKeys[k][2] = "0,0 1,1"
                    }
                    
                    // Add keyframe to fragment
                    aXamlFragment.push('<SplineDoubleKeyFrame KeyTime="', aKeys[k][0], '" Value="', nValue,
                                        '" KeySpline="', aKeys[k][2], '"/>');
                    
                } // 2 End keyframes
                
                // Complete animation fragment
                aXamlFragment.push('</DoubleAnimationUsingKeyFrames>');
                
            } // 1 End Animations
           
        } // 0 End targets
        
        var oAnimExisitng = this.oRoot.findname(sSBName);
            
        if (oAnimExisitng != null) {
            // Add the animation to the Canvas Resources object.
            this.oRoot.Resources.Remove(oAnimExisitng);
        }
        
        // End Storyboard fragment
        aXamlFragment.push('</Storyboard>');
        
        var sXamlFragment = aXamlFragment.join("");
        
        // Create StoryBoard object from xamlFragment
        var oStoryBoard = this.oRoot.GetHost().content.createFromXaml(sXamlFragment);
        
        // Add storyboard to resources in XAML tree
        this.oRoot.Resources.Add(oStoryBoard);
        
        // If XAMLLog is true, output to text area
        if (this.bXAMLLog) {
            document.getElementById(this.sXAMLLogId).value += sXamlFragment;
        }
        
        // Add completion event if it exists
        if (typeof(onComplete) != "undefined") {
            oStoryBoard.AddEventListener("Completed", onComplete);
        }
        
        if (typeof(oStoryBoard) != "null") {
            
            // Return animation object
            return oStoryBoard;
        } else {
            
            // Show error if animation couldn't be added
            alert("Error adding animation:\n\n" + sXamlFragment);
            return false;
        }
    } // End build
    
    return this;
    
} // End AnimationBuilder