﻿//--------------------------------------------------------------------------
// <copyright file="ActivePanel-ProductPanel-Reach.js" company="CM Group Ltd.">
//     Copyright © CM Group Ltd. All rights reserved.
// </copyright>
//--------------------------------------------------------------------------
//
// Params object example :
//
//   var panelParams = {
//       canvasId: 'activePanel',                   : ID attribute value of the target canvas element
//       logoST:      'images/logo-st.png',         : Path to the Studio logo image
//       logoLS:      'images/logo-ls.png',         : Path to the Lightshow logo image
//       logoRE:      'images/logo-re.png',         : Path to the Reach logo image
//       viewPort: { width: 255, height: 140 }      : Desired size of the visualisation
//   };
//
//--------------------------------------------------------------------------

// Define namespace
if (!ActivePanel) { var ActivePanel = {}; }

//--------------------------------------------------------------------------

// CM Active Panel Component
ActivePanel.ProductPanel = function (params) {
    var $ctx, $canvas, $handle, $sprites = [], $gameTime = 0, $fps = 15, $inheriting = {};

    // ---------------------------------------------------------------------
    // .ctor
    $canvas = document.getElementById(params.canvasId);
    if ($canvas && $canvas.getContext('2d')) {
        $ctx = $canvas.getContext('2d');
        $canvas.width = params.viewPort.width;
        $canvas.height = params.viewPort.height;
    }
    else {
        throw {
            name: 'Load Error',
            message: 'Unable to load canvas from id: ' + params.canvasId
        };
    }

    // ---------------------------------------------------------------------
    // Directions enum
    var $Directions = {
        Up: 1, Right: 2, Down: 4, Left: 8
    };

    // ---------------------------------------------------------------------
    // Sprite class
    var Sprite = function (p) {
        var isFadingIn, isFadingOut, fadeSpeed;
        isFadingIn = false;
        isFadingOut = false;

        // Private methods
        var updatePosition = function () {
            if (this.acceleration > 0) {
                switch (this.direction) {
                    case $Directions.Up:
                        this.position.y -= this.acceleration;
                        break;
                    case $Directions.Down:
                        this.position.y += this.acceleration;
                        break;
                    case $Directions.Left:
                        this.position.x -= this.acceleration;
                        break;
                    case $Directions.Right:
                        this.position.x += this.acceleration;
                        break;
                }
            }
        };

        // Public methods
        this.reset = function () {
            // Global state
            this.ctx = p.ctx;
            this.elapsed = 0.0;
            this.opacity = 0;

            // Parameter state
            this.position = p.position || { x: 0.0, y: 0.0 };
            this.lifeTime = p.lifeTime || { from: 0.0, duration: 0.0 };
            this.maxOpacity = p.maxOpacity || 1.0;
            this.fadeSpeed = p.fadeSpeed || 0.05;
            this.acceleration = p.acceleration || 0.0;
            this.direction = p.direction || $Directions.Right;

            // Notify subclasses to reset too
            if (this.resetOverride) {
                this.resetOverride();
            }
        };

        this.update = function (gameTime) {
            if (!this.ctx) {
                return; // no context to render to
            }

            // gameTime is number of ticks since the animation started,
            // therefore to convert that to a meaningful time value we
            // to need to calculate what that number means based on our
            // frames per second.
            this.elapsed = (gameTime / $fps) * 1000;
            if (this.elapsed < this.lifeTime.from ||
                        this.elapsed > (this.lifeTime.from + this.lifeTime.duration)) {

                // fading on timeout
                if (!isFadingOut && this.opacity >= this.maxOpacity) {
                    isFadingOut = true;
                }
                if (this.opacity <= 0) {
                    isFadingOut = false;
                }
                if (isFadingOut) {
                    this.opacity -= (this.fadeSpeed);
                    updatePosition.call(this); // keep updating until no longer visible
                }

                return; // life time has expired 
            }

            // Update opacity value
            if (this.opacity < this.maxOpacity) {
                this.opacity += this.fadeSpeed;
            }

            // Update the sprite position
            updatePosition.call(this);

            // Notify 
            if (this.updateOverride) {
                this.updateOverride(this.elapsed);
            }
        };

        this.draw = function () {
            if (!this.ctx || this.isComplete()) {
                return; // no context to render to or the sprite is inactive
            }

            this.ctx.save();
            this.ctx.globalAlpha = Math.max(0, this.opacity);
            if (this.drawOverride) {
                this.drawOverride(); // Notify
            }
            this.ctx.restore();
        };

        this.isComplete = function () {
            if (isFadingIn || isFadingOut) {
                return false;
            }

            return this.elapsed > (this.lifeTime.from + this.lifeTime.duration);
        };
    };

    // ---------------------------------------------------------------------
    // Text Sprite class
    var TextSprite = function (p) {
        if (arguments[0] === $inheriting) {
            return; // Assigning prototype so exit
        }

        // Call inherited .ctor
        Sprite.call(this, p);

        // Public methods
        this.resetOverride = function () {
            this.text = p.text || 'OOPS! NO TEXT SET';
            this.font = p.font || '16pt Arial';
            this.colour = p.colour || 'Black';
        };

        this.drawOverride = function () {
            this.ctx.save();
            this.ctx.font = this.font;
            this.ctx.fillStyle = this.colour;
            this.ctx.fillText(this.text, this.position.x, this.position.y);
            this.ctx.restore();
        };

        // Initialisation complete
        this.reset.call(this); // call base reset method
    };

    // Inherit from Sprite
    TextSprite.prototype = new Sprite($inheriting);

    // ---------------------------------------------------------------------
    // Image Sprite class
    var ImageSprite = function (p) {
        var img, isLoaded = false;

        if (arguments[0] === $inheriting) {
            return; // Assigning prototype so exit
        }

        // Call inherited .ctor
        Sprite.call(this, p);

        // Public methods
        this.resetOverride = function () {
            if (!img) {
                img = new Image();
                img.onload = function () {
                    isLoaded = true;
                };
                img.src = p.imageSource;
            }
        };

        this.drawOverride = function () {
            if (!isLoaded) {
                return; // Image is not yet loaded
            }

            this.ctx.save();
            this.ctx.drawImage(img, this.position.x, this.position.y);
            this.ctx.restore();
        };

        // Initialisation complete
        this.reset.call(this); // call base reset method
    };

    // Inherit from Sprite
    ImageSprite.prototype = new Sprite($inheriting);

    // ---------------------------------------------------------------------
    // Renders the background for the control
    var renderBackground = function (ctx) {
        ctx.save();
        ctx.fillStyle = 'rgba(0, 0, 0, 0.35)';
        ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
        ctx.restore();
    };

    // ---------------------------------------------------------------------
    // Updates the state of control before the draw method is called
    var update = function () {
        var i, sprite, complete = true;
        $gameTime += 1;
        for (i = 0; i < $sprites.length; i++) {
            sprite = $sprites[i];
            if (sprite.hasOwnProperty('update')) {
                sprite.update($gameTime);
                if (!sprite.isComplete()) {
                    complete = false;
                }
            }
        }

        if (complete) {
            clearInterval($handle); // stop the loop when complete

            // reset the sprites
            for (i = 0; i < $sprites.length; i++) {
                sprite = $sprites[i];
                if (sprite.hasOwnProperty('reset')) {
                    sprite.reset();
                }
            }

            // start the animation again
            startGameLoop();
        }
    };

    // ---------------------------------------------------------------------
    // Draws the visible elements
    var draw = function (ctx) {
        var i, sprite;

        // Clear the back buffer
        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

        // Render background elements
        renderBackground(ctx);

        // Render sprites
        for (i = 0; i < $sprites.length; i++) {
            sprite = $sprites[i];
            if (sprite.hasOwnProperty('draw')) {
                sprite.draw();
            }
        }
    };

    var startGameLoop = function () {
        $gameTime = 0;
        $handle = setInterval(function () {
            update();
            draw($ctx);
        }, 1000 / $fps);
    };

    //-----------------------------------------------------------------------
    // Public interface
    return {
        render: function () {
            var panelInfo = {};

            renderBackground($ctx);

            // Defaults
            panelInfo.largeFont = '20pt Oswald';
            panelInfo.largeStyle = 'rgba(255, 255, 255, 0.7)';
            panelInfo.largeSpace = 30;
            panelInfo.smallFont = '14pt Oswald';
            panelInfo.smallStyle = 'rgba(255, 255, 255, 0.7)';
            panelInfo.smallSpace = 22;
            panelInfo.startPosX = 20;
            panelInfo.StartPosYDefault = 190;
            panelInfo.duration = 10 * 1000;

            // Reach Panel #1
            panelInfo.start = 0;
            panelInfo.startPosY = panelInfo.StartPosYDefault;
            (function () {
                $sprites.push(new ImageSprite({
                    ctx: $ctx,
                    position: { x: 500, y: 15 },
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
                    maxOpacity: 1,
                    imageSource: params.logoST
                }));
                $sprites.push(new TextSprite({
                    ctx: $ctx,
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
                    position: { x: panelInfo.startPosX, y: panelInfo.startPosY - 110 },
                    text: 'Luminosity',
                    font: '24pt Oswald',
                    colour: panelInfo.largeStyle
                }));
                $sprites.push(new TextSprite({
                    ctx: $ctx,
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
                    position: { x: panelInfo.startPosX, y: panelInfo.startPosY - 75 },
                    text: 'Studio',
                    font: '24pt Oswald',
                    colour: panelInfo.largeStyle
                }));
                $sprites.push(new TextSprite({
                    ctx: $ctx,
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
                    position: { x: panelInfo.startPosX, y: panelInfo.startPosY += panelInfo.largeSpace },
                    text: 'Rapid authoring for eLearning',
                    font: panelInfo.largeFont,
                    colour: panelInfo.largeStyle
                }));
                $sprites.push(new TextSprite({
                    ctx: $ctx,
                    position: { x: panelInfo.startPosX, y: panelInfo.startPosY += panelInfo.smallSpace },
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
					opacity: 1,
                    text: 'Now with HTML5 output for mobile and tablet devices',
                    font: panelInfo.smallFont,
                    colour: panelInfo.smallStyle
                }));
                $sprites.push(new TextSprite({
                    ctx: $ctx,
                    position: { x: 495, y: 286 },
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
                    text: '●',
                    font: panelInfo.smallFont,
                    colour: panelInfo.smallStyle
                }));
                $sprites.push(new TextSprite({
                    ctx: $ctx,
                    position: { x: 520, y: 286 },
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
                    maxOpacity: 0.3,
                    text: '●',
                    font: panelInfo.smallFont,
                    colour: panelInfo.smallStyle
                }));
                $sprites.push(new TextSprite({
                    ctx: $ctx,
                    position: { x: 544, y: 286 },
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
                    maxOpacity: 0.3,
                    text: '●',
                    font: panelInfo.smallFont,
                    colour: panelInfo.smallStyle
                }));
            } ());

            // Reach Panel #2
            panelInfo.start = panelInfo.start + panelInfo.duration;
            panelInfo.startPosY = panelInfo.StartPosYDefault;
            (function () {
                $sprites.push(new ImageSprite({
                    ctx: $ctx,
                    position: { x: 460, y: 15 },
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
                    maxOpacity: 1,
                    imageSource: params.logoLS
                }));
                $sprites.push(new TextSprite({
                    ctx: $ctx,
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
                    position: { x: panelInfo.startPosX, y: panelInfo.startPosY - 110 },
                    text: 'Luminosity',
                    font: '24pt Oswald',
                    colour: panelInfo.largeStyle
                }));
                $sprites.push(new TextSprite({
                    ctx: $ctx,
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
                    position: { x: panelInfo.startPosX, y: panelInfo.startPosY - 75 },
                    text: 'Lightshow',
                    font: '24pt Oswald',
                    colour: panelInfo.largeStyle
                }));
                $sprites.push(new TextSprite({
                    ctx: $ctx,
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
                    position: { x: panelInfo.startPosX, y: panelInfo.startPosY += panelInfo.largeSpace },
                    text: 'Software simulations for application training',
                    font: panelInfo.largeFont,
                    colour: panelInfo.largeStyle
                }));
                $sprites.push(new TextSprite({
                    ctx: $ctx,
                    position: { x: panelInfo.startPosX, y: panelInfo.startPosY += panelInfo.smallSpace },
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
                    text: 'For cloud, mobile, tablet and desktop applications',
                    font: panelInfo.smallFont,
                    colour: panelInfo.smallStyle
                }));
                $sprites.push(new TextSprite({
                    ctx: $ctx,
                    position: { x: 495, y: 286 },
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
                    maxOpacity: 0.3,
                    text: '●',
                    font: panelInfo.smallFont,
                    colour: panelInfo.smallStyle
                }));
                $sprites.push(new TextSprite({
                    ctx: $ctx,
                    position: { x: 520, y: 286 },
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
                    text: '●',
                    font: panelInfo.smallFont,
                    colour: panelInfo.smallStyle
                }));
                $sprites.push(new TextSprite({
                    ctx: $ctx,
                    position: { x: 544, y: 286 },
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
                    maxOpacity: 0.3,
                    text: '●',
                    font: panelInfo.smallFont,
                    colour: panelInfo.smallStyle
                }));
            } ());

            // Reach Panel #3
            panelInfo.start = panelInfo.start + panelInfo.duration;
            panelInfo.startPosY = panelInfo.StartPosYDefault;
            (function () {
                $sprites.push(new TextSprite({
                    ctx: $ctx,
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
                    position: { x: panelInfo.startPosX, y: panelInfo.startPosY - 110 },
                    text: 'Luminosity',
                    font: '24pt Oswald',
                    colour: panelInfo.largeStyle
                }));
                $sprites.push(new TextSprite({
                    ctx: $ctx,
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
                    position: { x: panelInfo.startPosX, y: panelInfo.startPosY - 75 },
                    text: 'Reach',
                    font: '24pt Oswald',
                    colour: panelInfo.largeStyle
                }));
                $sprites.push(new TextSprite({
                    ctx: $ctx,
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
                    position: { x: panelInfo.startPosX, y: panelInfo.startPosY += panelInfo.largeSpace },
                    text: 'Learning management made simple',
                    font: panelInfo.largeFont,
                    colour: panelInfo.largeStyle
                }));
                $sprites.push(new TextSprite({
                    ctx: $ctx,
                    position: { x: panelInfo.startPosX, y: panelInfo.startPosY += panelInfo.smallSpace },
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
                    text: 'Instantly deliver eLearning across your organisation and beyond',
                    font: panelInfo.smallFont,
                    colour: panelInfo.smallStyle
                }));
                $sprites.push(new TextSprite({
                    ctx: $ctx,
                    position: { x: 495, y: 286 },
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
                    maxOpacity: 0.3,
                    text: '●',
                    font: panelInfo.smallFont,
                    colour: panelInfo.smallStyle
                }));
                $sprites.push(new TextSprite({
                    ctx: $ctx,
                    position: { x: 520, y: 286 },
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
                    maxOpacity: 0.3,
                    text: '●',
                    font: panelInfo.smallFont,
                    colour: panelInfo.smallStyle
                }));
                $sprites.push(new TextSprite({
                    ctx: $ctx,
                    position: { x: 544, y: 286 },
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
                    text: '●',
                    font: panelInfo.smallFont,
                    colour: panelInfo.smallStyle
                }));
				$sprites.push(new ImageSprite({
                    ctx: $ctx,
                    position: { x: 505, y: 15 },
                    lifeTime: { from: panelInfo.start, duration: panelInfo.duration },
                    maxOpacity: 1,
                    imageSource: params.logoRE
                }));
            } ());

            // Start game loop
            startGameLoop();
        }
    };
};
