﻿//--------------------------------------------------------------------------
// <copyright file="ActivePanel-CustomerLogoPanel.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
//       background: 'white',                       : Background colour (default: white)
//       border: '#cccccc',                         : Border colour (default: #ccc)
//       font: '16pt Georgia',                      : Preloader typeface (default: 16pt Arial)
//       maxWidth: 150,                             : Maximum scale width of a logo (default: 150px)
//       maxHeight: 65,                             : Maximum scale height of a logo (default: 65px)
//       padding: 20,                               : Horizontal Padding between logos (default: 20px)
//       fadeEdges: true,                           : Fades the horizontal edges (default: false)
//       viewPort: { width: 555, height: 125 },     : Desired size of the visualisation
//       logoPaths: [                               : Array of relative paths
//            'Logos/customer1.png',
//            'Logos/customer2.png',
//            'Logos/customer3.png',
//        ]
//   };
//
//--------------------------------------------------------------------------

//--------------------------------------------------------------------------

// Define namespace
if (!ActivePanel) { var ActivePanel = {}; }

//--------------------------------------------------------------------------

// CM Active Panel Component
ActivePanel.CustomerLogoPanel = function (params) {
    var $ctx, $canvas, $handle, $downloadCount,
        $defaults = {
            background: 'white',
            border: '#ccc',
            font: '16pt Arial',
            height: 65,
            padding: 20,
            width: 150,
            fadeEdges: false
        };

    // ---------------------------------------------------------------------
    // .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
        };
    }

    // ---------------------------------------------------------------------
    // Renders the background for the control
    var renderBackground = function () {
        $ctx.fillStyle = params.background || $defaults.background;
        $ctx.fillRect(0, 0, $ctx.canvas.width, $ctx.canvas.height);
    };

    // ---------------------------------------------------------------------
    // Renders a preloader message
    var renderPreloader = function () {
        $ctx.font = params.font || $defaults.font;
        $ctx.fillStyle = params.border || $defaults.border;
        $ctx.fillText('Loading logos, please wait.....', 20, 40);
    };

    // ---------------------------------------------------------------------
    // Renders the border for the control
    var renderBorder = function () {
        $ctx.strokeStyle = params.border || $defaults.border;
        $ctx.strokeRect(0, 0, $ctx.canvas.width, $ctx.canvas.height);
    };

    // ---------------------------------------------------------------------
    // Renders faded edges on the panel
    var renderGradientEdges = function () {
        var lGrad, rGrad, width = $ctx.canvas.width;

        lGrad = $ctx.createLinearGradient(0, 0, 50, 0);
        lGrad.addColorStop(0, 'rgba(255, 255, 255, 255)');
        lGrad.addColorStop(1, 'rgba(255, 255, 255, 0)');
        rGrad = $ctx.createLinearGradient(width - 50, 0, width, 0);
        rGrad.addColorStop(0, 'rgba(255, 255, 255, 0)');
        rGrad.addColorStop(1, 'rgba(255, 255, 255, 255)');

        $ctx.save();
        $ctx.fillStyle = lGrad;
        $ctx.fillRect(0, 0, 50, $ctx.canvas.height);
        $ctx.fillStyle = rGrad;
        $ctx.fillRect(width - 50, 0, 50, $ctx.canvas.height);
        $ctx.restore();
    };

    // ---------------------------------------------------------------------
    // Renders all the logos
    var renderLogos = function () {
        var i, logo;
        for (i = 0; i < params.logoPaths.length; i++) {
            logo = params.logos[params.logoPaths[i]];
            if (logo.isVisible) {
                $ctx.drawImage(
                    logo.imageSource,
                    logo.location.x, logo.location.y,
                    logo.size.width, logo.size.height);
            }
        }
    };

    // ---------------------------------------------------------------------
    // Loads images async
    var loadImages = function (callback) {
        var i, img, path;

        // -----------------------------------------------------------------
        // Calculates the locations for the logo's
        var calculateLogoLocations = function () {
            var j, logo,
                padding = (params.padding || $defaults.padding), x = padding;
            for (j = 0; j < params.logoPaths.length; j++) {
                logo = params.logos[params.logoPaths[j]];
                logo.location.x = x;
                x += logo.size.width + padding;
            }
        };

        // -----------------------------------------------------------------
        // Calculates the render size of an image
        var calculateSize = function (i) {
            var w, r, h;

            if (i.width > i.height) {
                w = (params.maxWidth || $defaults.width);
                r = w / i.width;
                h = i.height * r;
            }
            else {
                h = (params.maxHeight || $defaults.height);
                r = h / i.height;
                w = i.width * r;
            }

            return { width: w, height: h };
        };

        // -----------------------------------------------------------------
        // Create a logo object from an image instance
        var createLogo = function (k, c) {
            var size, logo;

            size = calculateSize(this);
            logo = {
                imageSource: this,
                size: size,
                location: { x: 0, y: (params.viewPort.height / 2) - (size.height / 2) },
                isVisible: false,
                key: k
            };
            params.logos[logo.key] = logo;

            $downloadCount++;
            if ($downloadCount === params.logoPaths.length) {
                calculateLogoLocations();
                c(); // Callback
            }
        };

        // -----------------------------------------------------------------
        // Create a logo object from an image instance
        var createOnLoadCallback = function () {
            var p = path, c = callback; // capture instance vars
            return function () {
                createLogo.call(this, p, c);
            };
        };

        // State management
        $downloadCount = 0;
        params.logos = {};

        // Load the images
        for (i = 0; i < params.logoPaths.length; i++) {
            path = params.logoPaths[i];
            params.logos[path] = null;
            img = new Image();
            img.onload = createOnLoadCallback();
            img.src = path;
        }
    };

    // ---------------------------------------------------------------------
    // Updates the state of control before the draw method is called
    var update = function () {
        var i, logo, prevLogo = params.logos[params.logoPaths[params.logoPaths.length - 1]];
        for (i = 0; i < params.logoPaths.length; i++) {
            logo = params.logos[params.logoPaths[i]];
            logo.location.x -= 1;

            if ((logo.location.x + logo.size.width) < 0) {
                logo.location.x =
                    prevLogo.location.x +
                    prevLogo.size.width +
                    (params.padding || $defaults.padding);
            }

            logo.isVisible = (logo.location.x < params.viewPort.width);
            prevLogo = logo;
        }
    };

    // ---------------------------------------------------------------------
    // Draws the visible elements
    var draw = function () {
        renderBackground();
        renderLogos();
        renderBorder();

        if (params.fadeEdges) {
            renderGradientEdges();
        }
    };

    //-----------------------------------------------------------------------
    // Public interface
    return {
        render: function () {
            renderBackground();
            renderPreloader();
            renderBorder();

            loadImages(function () { /* callback */
                $handle = setInterval(function () {
                    update();
                    draw();
                }, 1000 / 30); // 60fps
            });
        }
    };
};

//--------------------------------------------------------------------------
