﻿// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Permissive License.
// See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
// All other rights reserved.

Type.registerNamespace('AjaxControlToolkit.Animation');

AjaxControlToolkit.Animation.AnimationBehavior = function(element) {
    /// <summary>
    /// The AnimationBehavior allows us to associate animations (described by JSON) with events and
    /// have them play when the events are fired.  It relies heavily on the AJAX Control Toolkit
    /// animation framework provided in Animation.js.
    /// </summary>
    /// <param name="element" type="Sys.UI.DomElement">The DOM element the behavior is associated with</param>
    AjaxControlToolkit.Animation.AnimationBehavior.initializeBase(this, [element]);
    
    // Generic animation behaviors that automatically build animations from JSON descriptions
    this._onLoad = new AjaxControlToolkit.Animation.GenericAnimationBehavior(element);
    this._onClick = new AjaxControlToolkit.Animation.GenericAnimationBehavior(element);
    this._onMouseOver = new AjaxControlToolkit.Animation.GenericAnimationBehavior(element);
    this._onMouseOut = new AjaxControlToolkit.Animation.GenericAnimationBehavior(element);
    this._onHoverOver = new AjaxControlToolkit.Animation.GenericAnimationBehavior(element);
    this._onHoverOut = new AjaxControlToolkit.Animation.GenericAnimationBehavior(element);
    
    // Handlers for the events
    this._onClickHandler = null;
    this._onMouseOverHandler = null;
    this._onMouseOutHandler = null;
}
AjaxControlToolkit.Animation.AnimationBehavior.prototype = {
    initialize : function() {
        /// <summary>
        /// Setup the animations/handlers (and play the OnLoad animation immediately)
        /// </summary>
        /// <returns />
        AjaxControlToolkit.Animation.AnimationBehavior.callBaseMethod(this, 'initialize');
        
        var element = this.get_element();
        if (!element) throw new Error.invalidOperation('AjaxControlToolkit.Animation.AnimationBehavior must have an element');
        
        // Initialize the animation behaviors (and play OnLoad as soon
        // as possible if we have one)
        this._onLoad.initialize();
        this._onLoad.play();
        this._onClick.initialize();
        this._onMouseOver.initialize();
        this._onMouseOut.initialize();
        this._onHoverOver.initialize();
        this._onHoverOut.initialize();
        
        // Wireup the event handlers
        this._onClickHandler = Function.createDelegate(this, this.OnClick);
        $addHandler(element, 'click', this._onClickHandler);
        this._onMouseOverHandler = Function.createDelegate(this, this.OnMouseOver);
        $addHandler(element, 'mouseover', this._onMouseOverHandler);
        this._onMouseOutHandler = Function.createDelegate(this, this.OnMouseOut);
        $addHandler(element, 'mouseout', this._onMouseOutHandler);
    },
    
    dispose : function() {
        /// <summary>
        /// Dispose of the animations/handlers
        /// </summary>
        /// <returns />
        
        // Remove the event handlers
        var element = this.get_element();
        if (element) {
            if (this._onClickHandler) {
                $removeHandler(element, 'click', this._onClickHandler);
                this._onClickHandler = null;
            }
            if (this._onMouseOverHandler) {
                $removeHandler(element, 'mouseover', this._onMouseOverHandler);
                this._onMouseOverHandler = null;
            }
            if (this._onMouseOutHandler) {
                $removeHandler(element, 'mouseout', this._onMouseOutHandler);
                this._onMouseOutHandler = null;
            }
        }
        
        // Wipe the behaviors (we don't need to dispose them because
        // that will happen automatically in our base dispose)
        this._onLoad = null;
        this._onClick = null;
        this._onMouseOver = null;
        this._onMouseOut = null;
        this._onHoverOver = null;
        this._onHoverOut = null;
        
        AjaxControlToolkit.Animation.AnimationBehavior.callBaseMethod(this, 'dispose');
    },
    
//    getDescriptor : function() {
//        /// <summary>
//        /// Create a type descriptor
//        /// </summary>
//        /// <returns type="???">Type descriptor</returns>
//    
//        var descriptor = AjaxControlToolkit.Animation.AnimationBehavior.callBaseMethod(this, 'getDescriptor');
//        descriptor.addProperty('OnLoad', String); 
//        descriptor.addProperty('OnClick', String); 
//        descriptor.addProperty('OnMouseOver', String); 
//        descriptor.addProperty('OnMouseOut', String); 
//        descriptor.addProperty('OnHoverOver', String); 
//        descriptor.addProperty('OnHoverOut', String); 
//        return descriptor;
//    },
    
    get_OnLoad : function() {
        /// <value type="String">
        /// Generic OnLoad Animation's JSON definition
        /// </value>
        /// <remarks>
        /// Setting the OnLoad property will cause it to be played immediately
        /// </remarks>
        return this._onLoad.get_json();
    },
    set_OnLoad : function(value) {
        this._onLoad.set_json(value);
        this.raisePropertyChanged('OnLoad');
        this._onLoad.play();
    },
    
    get_OnLoadBehavior : function() {
        /// <value type="AjaxControlToolkit.Animation.GenericAnimationBehavior">
        /// Generic OnLoad Animation's behavior
        /// </value>
        return this._onLoad;
    },
    
    
    
    get_OnClick : function() {
        /// <value type="String">
        /// Generic OnClick Animation's JSON definition
        /// </value>
        return this._onClick.get_json();
    },
    set_OnClick : function(value) {
        this._onClick.set_json(value);
        this.raisePropertyChanged('OnClick');
    },
    
    get_OnClickBehavior : function() {
        /// <value type="AjaxControlToolkit.Animation.GenericAnimationBehavior">
        /// Generic OnClick Animation's behavior
        /// </value>
        return this._onClick;
    },
    
    OnClick : function() {
        /// <summary>
        /// Handler for the OnClick event
        /// </summary>
        /// <returns />
        this._onClick.play();
    },
    
    
    
    get_OnMouseOver : function() {
        /// <value type="String">
        /// Generic OnMouseOver Animation's JSON definition
        /// </value>
        return this._onMouseOver.get_json();
    },
    set_OnMouseOver : function(value) {
        this._onMouseOver.set_json(value);
        this.raisePropertyChanged('OnMouseOver');
    },
    
    get_OnMouseOverBehavior : function() {
        /// <value type="AjaxControlToolkit.Animation.GenericAnimationBehavior">
        /// Generic OnMouseOver Animation's behavior
        /// </value>
        return this._onMouseOver;
    },
    
    OnMouseOver : function() {
        /// <summary>
        /// Handler for the OnMouseOver event
        /// </summary>
        /// <returns />
        this._onMouseOver.play();
        this._onHoverOut.quit();
        this._onHoverOver.play();
    },
    
    
    
    get_OnMouseOut : function() {
        /// <value type="String">
        /// Generic OnMouseOut Animation's JSON definition
        /// </value>
        return this._onMouseOut.get_json();
    },
    set_OnMouseOut : function(value) {
        this._onMouseOut.set_json(value);
        this.raisePropertyChanged('OnMouseOut');
    },
    
    get_OnMouseOutBehavior : function() {
        /// <value type="AjaxControlToolkit.Animation.GenericAnimationBehavior" />
        /// Generic OnMouseOut Animation's behavior
        /// </value>
        return this._onMouseOut;
    },
    
    OnMouseOut : function() {
        /// <summary>
        /// Handler for the OnMouseOut event
        /// </summary>
        /// <returns />
        this._onMouseOut.play();
        this._onHoverOver.quit();
        this._onHoverOut.play();
    },
    
    
    
    get_OnHoverOver : function() {
        /// <value type="String">
        /// Generic OnHoverOver Animation's JSON definition
        /// </value>
        return this._onHoverOver.get_json();
    },
    set_OnHoverOver : function(value) {
        this._onHoverOver.set_json(value);
        this.raisePropertyChanged('OnHoverOver');
    },
    
    get_OnHoverOverBehavior : function() {
        /// <value type="AjaxControlToolkit.Animation.GenericAnimationBehavior">
        /// Generic OnHoverOver Animation's behavior
        /// </value>
        return this._onHoverOver;
    },
    
    
    
    get_OnHoverOut : function() {
        /// <value type="String">
        /// Generic OnHoverOut Animation's JSON definition
        /// </value>
        return this._onHoverOut.get_json();
    },
    set_OnHoverOut : function(value) {
        this._onHoverOut.set_json(value);
        this.raisePropertyChanged('OnHoverOut');
    },
    
    get_OnHoverOutBehavior : function() {
        /// <value type="AjaxControlToolkit.Animation.GenericAnimationBehavior">
        /// Generic OnHoverOut Animation's behavior
        /// </value>
        return this._onHoverOut;
    }
}
AjaxControlToolkit.Animation.AnimationBehavior.registerClass('AjaxControlToolkit.Animation.AnimationBehavior', AjaxControlToolkit.BehaviorBase);



AjaxControlToolkit.Animation.GenericAnimationBehavior = function(element) {
    /// <summary>
    /// The GenericAnimationBehavior handles the creation, playing, and disposing of animations
    /// created from a JSON description.  As we intend to expose a lot of generic animations
    /// across the framework, this behavior serves to simplify the amount of work required.
    /// </summary>
    AjaxControlToolkit.Animation.GenericAnimationBehavior.initializeBase(this, [element]);
    
    // JSON description of the animation that will be used to create it
    this._json = null;
    
    // Animation created from the JSON description that will be played
    this._animation = null;
}
AjaxControlToolkit.Animation.GenericAnimationBehavior.prototype = {
    initialize : function() {
        /// <summary>
        /// Initialize the behavior by creating the animation
        /// </summary>
        /// <returns />
        AjaxControlToolkit.Animation.GenericAnimationBehavior.callBaseMethod(this, 'initialize');
        
        this.createAnimation();
    },
    
    createAnimation : function()  {
        /// <summary>
        /// Create the animation using its JSON description and the behavior's
        /// element as its default target
        /// </summary>
        /// <returns />
        
        var element = this.get_element();
        if (element) {
            this._animation = AjaxControlToolkit.Animation.buildAnimation(this._json, element);
            if (this._animation) {
                if (!this._animation.get_target()) {
                    this._animation.set_target(element);
                }
                this._animation.initialize();
            }
            this.raisePropertyChanged('animation');
        }
    },
    
    dispose : function() {
        /// <summary>
        /// Dispose the behavior and its animation
        /// </summary>
        /// <returns />
        
        this.disposeAnimation();
        AjaxControlToolkit.Animation.GenericAnimationBehavior.callBaseMethod(this, 'dispose');
    },
    
    disposeAnimation : function() {
        /// <summary>
        /// Dispose the animation
        /// </summary>
        /// <returns />
        
        if (this._animation) {
            this._animation.dispose();
        }
        this._animation = null;
    },
    
//    getDescriptor : function() {
//        /// <summary>
//        /// Get a type descriptor
//        /// </summary>
//        /// <returns type="???>Type descriptor</returns>
//        
//        var descriptor = AjaxControlToolkit.Animation.AnimationBehavior.callBaseMethod(this, 'getDescriptor');
//        descriptor.addProperty('json', String); 
//        descriptor.addProperty('animation', Object, true); 
//        return descriptor;
//    },
    
    play : function() {
        /// <summary>
        /// Play the animation if it isn't already playing.  If it's already playing this does nothing.
        /// </summary>
        /// <returns />
        
        if (this._animation && !this._animation.get_isPlaying()) {
            this.stop();
            this._animation.play();
        }
    },
    
    stop : function() {
        /// <summary>
        /// Stop the animation if it's already playing
        /// </summary>
        /// <returns />
        
        if (this._animation) {
            if (this._animation.get_isPlaying()) {
                this._animation.stop();
            }
        }
    },
    
    quit : function() {
        /// <summary>
        /// Quit playing the animation without updating the final state (i.e. if
        /// the animation was moving, this would leave it in the middle of its path).\
        /// </summary>
        /// <remarks>
        /// This differs from the stop function which will update the final state.  The
        /// quit function is most useful for scenarios where you're toggling back and forth
        /// between two animations (like those used in OnHoverOver/OnHoverOut) and you don't
        /// want to completely finish one animation if its counterpart is triggered.
        /// </remarks>
        /// <returns />
    
        if (this._animation) {
            if (this._animation.get_isPlaying()) {
                this._animation._updatePercentComplete(100, false);
            }
        }
    },
    
    get_json : function() {
        /// <summary>
        /// JSON animation description
        /// </summary>
        /// <value type="String" />
        return this._json;
    },
    set_json : function(value) {
        // Only wipe and rebuild if they're changing the value
        if (this._json != value) {
            // Clear the old animation
            this.disposeAnimation();
            
            // Setup the new animation
            this._json = value;
            this.createAnimation();
            this.raisePropertyChanged('json');
        }
    },
    
    get_animation : function() {
        /// <summary>
        /// Animation created from the JSON description
        /// </summary>
        /// <value type="AjaxControlToolkit.Animation.Animation" />
        return this._animation;
    }
}

AjaxControlToolkit.Animation.GenericAnimationBehavior.registerClass('AjaxControlToolkit.Animation.GenericAnimationBehavior', AjaxControlToolkit.BehaviorBase);
if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();