# Source: composer/rotation-composer.js

    /**
     * @module ./rotation-composer.reel
     * @requires montage/composer/composer
     */
    var Composer = require("./composer").Composer,
        TranslateComposer = require("./translate-composer").TranslateComposer;

    /**
     * @class RotationComposer
     * @extends Composer
     */
    exports.RotationComposer = Composer.specialize(/** @lends RotationComposer# */ {

        /**
            Dispatched when a rotation is started

            @event rotationStart
            @memberof RotationComposer
            @param {RotationEvent} event
        */

        /**
            Dispatched when a rotation changes

            @event rotation
            @memberof RotationComposer
            @param {RotationEvent} event
        */

        /**
            Unit for dispatched angles. Options: radians and degrees
            Radians are the default as it is the standard in angular measures
            To think about: should it accept "deg" as degrees to be equivalent to CSS notation?
        */
        _unit: {
            value: "radians"
        },

        unit: {
            get: function () {
                return this._unit;
            },
            set: function (value) {
                if (value === "degrees") {
                    this._unit = "degrees";
                } else {
                    this._unit = "radians";
                }
            }
        },

        constructor: {
            value: function RotationComposer() {
                this.super();
                this._translateComposer = new TranslateComposer();
                this._translateComposer.hasMomentum = false;
                this._translateComposer.hasBouncing = false;
            }
        },

        // Load/unload

        load: {
            value: function() {
                this.component.addComposerForElement(this._translateComposer, this.element);
                this._translateComposer.load();
                this._translateComposer.addEventListener("translateStart", this, false);
                this._translateComposer.addEventListener("translateEnd", this, false);
                this._translateComposer.addEventListener("translate", this, false);
            }
        },

        unload: {
            value: function() {
            }
        },

        handleTranslateStart: {
            value: function() {
                var start = this._translateComposer.pointerStartEventPosition,
                    deltaX = start.pageX - this.center.pageX,
                    deltaY = start.pageY - this.center.pageY;

                this._translateComposer.translateX = start.pageX;
                this._translateComposer.translateY = start.pageY;
                this._previousAngle = Math.atan2(deltaY, deltaX);
                this._deltaAngle = 0;
                this._dispatchRotateStart();
            }
        },

        handleTranslateEnd: {
            value: function() {
                this._dispatchRotateEnd();
            }
        },

        handleTranslate: {
            value: function(event) {
                var deltaX = event.translateX - this.center.pageX,
                    deltaY = event.translateY - this.center.pageY,
                    currentAngle = Math.atan2(deltaY, deltaX),
                    deltaAngle = currentAngle - this._previousAngle;

                if (deltaAngle > Math.PI) {
                    deltaAngle -= Math.PI * 2;
                } else {
                    if (deltaAngle < -Math.PI) {
                        deltaAngle += Math.PI * 2;
                    }
                }
                this.angleInRadians += deltaAngle;
                this._deltaAngle = deltaAngle;
                this._previousAngle = currentAngle;
                this._dispatchRotate();
            }
        },

        angleInRadians: {
            value: 0
        },

        _deltaAngle: {
            value: 0
        },

        _dispatchRotateStart: {
            value: function() {
                var event = document.createEvent("CustomEvent");

                event.initCustomEvent("rotateStart", true, true, null);
                event.unit = this._unit;
                if (this._unit === "radians") {
                    event.rotation = this.angleInRadians;
                    event.deltaRotation = this._deltaAngle;
                } else {
                    event.rotation = (this.angleInRadians * 180) / Math.PI;
                    event.deltaRotation = (this._deltaAngle * 180) / Math.PI;
                }
                this.dispatchEvent(event);
            }
        },

        _dispatchRotate: {
            value: function() {
                var event = document.createEvent("CustomEvent");

                event.initCustomEvent("rotate", true, true, null);
                event.unit = this._unit;
                if (this._unit === "radians") {
                    event.rotation = this.angleInRadians;
                    event.deltaRotation = this._deltaAngle;
                } else {
                    event.rotation = (this.angleInRadians * 180) / Math.PI;
                    event.deltaRotation = (this._deltaAngle * 180) / Math.PI;
                }
                this.dispatchEvent(event);
            }
        },

        _dispatchRotateEnd: {
            value: function() {
                var event = document.createEvent("CustomEvent");

                event.initCustomEvent("rotateEnd", true, true, null);
                event.unit = this._unit;
                event.deltaRotation = 0;
                if (this._unit === "radians") {
                    event.rotation = this.angleInRadians;
                } else {
                    event.rotation = (this.angleInRadians * 180) / Math.PI;
                }
                this.dispatchEvent(event);
            }
        },

        // To review: I would call this axisCoordinates or similar
        center: {
            value: null
        },

        _start: {
            value: null
        },

        _translateComposer: {
            value: null
        },

        animateMomentum: {
            get: function () {
                return this._translateComposer.animateMomentum;
            },
            set: function (value) {
                this._translateComposer.animateMomentum = !!value;
            }
        },

        /**
         * Whether to keep translating after the user has releases the cursor.
         * @type {boolean}
         * @default true
         */
        hasMomentum: {
            get: function () {
                return this._translateComposer.hasMomentum;
            },
            set: function (value) {
                this._translateComposer.hasMomentum = !!value;
            }
        }

    });