window.Mediasite = window.Mediasite || {};
Mediasite.Player = Mediasite.Player || {};
Mediasite.Player.SingleImageButton = (function () {
    
    function BlurBackground(element, options) {
        var self = this;
        var debug = false;
        var canvasSupport = !!window.HTMLCanvasElement;

        var blurContainer, image, background, backgroundDouble;
        var sourceImage;

        var defaultOptions = {
            src: '',
            ratio: undefined,   // natural size / css px size
            width: undefined,   // image's dimensions in css px (no unit)
            height: undefined,
            padding: 10, // whitespace around image in css px  (no unit)
            blurRadius: 6,  // in css px (no unit); will be multipled by image's ratio when generating blur
            doubleBackground: true,
            elementClass: 'ui-blur-background',
            blurContainerClass: 'ui-blur-image',
            noCanvasClass: 'no-canvas',
            foregroundClass: 'foreground',
            backgroundClass: 'background',
            doubleBackgroundClass: 'double-background'
        };

        options = $.extend({}, defaultOptions, options);


        function init() {
            fillOptionsFromCss();
            populateElements();
            applyBaseStyle();

            sourceImage = new Image();
            sourceImage.addEventListener("load", function () {
                clearTimeout(sourceImage.fakeOnLoad);
                onLoadImage();
            });


            // If image is already loaded, then onload may not fire
            sourceImage.fakeOnLoad = setTimeout(function () {
                if (sourceImage.width) {
                    onLoadImage();
                }
            }, 1);

            sourceImage.src = options.src;
        }

        function fillOptionsFromCss() {
            if (!options.width) {
                // Get element's CSS-enforced size for setting dimensions/ratio on image later

                options.width = element.width();
                options.height = element.height();

                // This is a little fragile, since it depends on this.element currently having CSS applied to it
                // which determines the image's dimensions
            }

            if (!options.src) {
                var background = element.css('background-image').match(/^url\(['"]?([^"|^']+)['"]?\)$/);
                if (background) {
                    element.css('background-image', 'none');
                    options.src = background[1];
                }
            }
        }

        function populateElements() {
            blurContainer = $("<span />").addClass(options.blurContainerClass);
            element.prepend(blurContainer);

            image = $("<img />").addClass(options.foregroundClass);
            image.attr('src', options.src);
            image.appendTo(blurContainer);

            background = $("<img />").addClass(options.backgroundClass);
            if (options.doubleBackground) {
                backgroundDouble = background.clone().addClass(options.doubleBackgroundClass).appendTo(element);
                background = background.add(backgroundDouble);
            }

            background.appendTo(blurContainer);
        }

        function applyBaseStyle() {
            element.addClass(options.elementClass);
            element.css({
                'position': 'relative',
                'border': 'none',
                'background': 'none'
            });

            background.hide();

            applyStyle();
        }

        function applyStyle() {
            blurContainer.css({
                width: options.width + 'px',
                height: options.height + 'px'
            });

            var padding = (0 - options.padding) + 'px';
            var width = (options.width + options.padding * 2) + 'px';
            var height = (options.height + options.padding * 2) + 'px';

            background.css({
                'position': 'absolute',
                'top': padding,
                'left': padding,
                'right': padding,
                'bottom': padding,
                'width': width,
                'height': height
            });
        }

        function onLoadImage() {
            if (!options.ratio) {
                var displayWidth = options.width;
                var naturalWidth = sourceImage.width;
                options.ratio = naturalWidth / displayWidth || 1;
                debug && window.console && console.log(["Ratio:", this.options.ratio, '=', naturalWidth, '/', displayWidth, '--', this.options.src].join(" "));
            }

            setBlurBackground();
        }

        function setBlurBackground() {
            var backgroundBlur;
            try {
                var dimensions = { padding: options.padding * options.ratio };
                backgroundBlur = generateBlur(sourceImage, dimensions);
            } catch (e) {
                // If drawing the canvas throws weird errors  regarding dimensions, cannot find pixels, etc.
                // then make sure either the ratio is set or the dimensions make sense

                if (debug && window.console) {
                    console.warn(e);
                    console.error(e.stack);
                }
            }


            if (backgroundBlur) {
                background.attr('src', backgroundBlur).show();
            } else {
                element.addClass(options.noCanvasClass);
                background.hide();
            }
        }

        function generateBlur(image, dimensions) {
            if (!canvasSupport) return;
            var filtered = stackBlur(image, dimensions);

            var canvas = document.createElement('canvas');
            canvas.width = filtered.imageData.width;
            canvas.height = filtered.imageData.height;

            var context = canvas.getContext('2d');
            context.scale(options.ratio, options.ratio);

            context.putImageData(filtered.imageData, 0, 0);

            var dataUrl = canvas.toDataURL();
            return dataUrl;
        }

        function stackBlur(image, dimensions) {
            var filter = Mediasite.Filters.stackBlur;
            var radius = options.blurRadius * options.ratio;

            var data = Mediasite.Filters.filterImage(filter, image, dimensions, radius);
            return data;
        };



        init();
    }

    function SingleImageButton(element, options) {
        var self = this;
        var isDisabled = false;
        var labelText;
        var clickAction;

        options = (typeof options === "object") && options || {};


        Object.defineProperty(self, "title", {
            set: function (titleText) {
                if (titleText) {
                    element.setAttribute("title", titleText);
                } else {
                    element.removeAttribute("title");
                }
            },
            get: function () {
                return element.getAttribute("title");
            }
        });

        Object.defineProperty(self, "label", {
            set: function (value) {
                labelText = value;
                setLabelElementText(element, labelText);
            },
            get: function () {
                return labelText;
            }
        });

        Object.defineProperty(self, "disabled", {
            set: function (value) {
                isDisabled = value;
                if (isDisabled) {
                    element.className = addClassName(element.className, "ui-state-disabled");
                } else {
                    element.className = removeClassName(element.className, "ui-state-disabled");
                }
            },
            get: function () {
                return isDisabled;
            }
        });

        self.clickHandler = function (e) { }; // default no-op.

        self.applyOptions = function (options) {
            applyOptions(options);
        }


        function init() {
            element.className = addClassName(element.className, "ui-button");
            element.className = addClassName(element.className, "ui-corner-all");
            element.className = addClassName(element.className, "ui-widget");

            var preexistingText = element.textContent;
            element.innerText = "";

            if (preexistingText && preexistingText.trim()) {
                self.label = preexistingText;
            }

            applyOptions(options);

            new BlurBackground($(element), options); 

            element.addEventListener("click", function (e) {
                if (typeof self.clickHandler === "function") {
                    self.clickHandler(e);
                }
            });
        }

        function applyOptions(options) {
            if (options.hasOwnProperty("label")) {
                self.label = options.label;
            }

            if (options.hasOwnProperty("title")) {
                self.title = options.title;
            }

            if (options.hasOwnProperty("disabled")) {
                self.disabled = options.disabled;
            }

            if (options.hasOwnProperty("click")) {
                self.clickHandler = options.click;
            }
        }


        init();

    }


    var LABEL_ELEMENT_CLASS = "ui-button-text";


    function setLabelElementText(button, text) {
        var labelSpan = button.querySelector("." + LABEL_ELEMENT_CLASS);
        if (text) {
            if (!labelSpan) {
                labelSpan = document.createElement("span");
                labelSpan.className = LABEL_ELEMENT_CLASS;
                button.insertBefore(labelSpan, button.firstChild);
            }
            labelSpan.textContent = text;
        } else {
            if (labelSpan) {
                button.removeChild(labelSpan);
            }
        }
    }

    function addClassName(allNames, name) {
        var result = allNames || "";
        result = removeClassName(allNames, name);
        result += " " + name;
        return result.trim();
    }

    function removeClassName(allNames, name) {
        var parts, result;
        var splitExpression = /\s/;

        allNames = allNames || "";
        parts = allNames.split(splitExpression);

        function reducer(accumulator, currentValue) {
            if (currentValue === name) {
                return accumulator;
            } else {
                return accumulator + " " + currentValue;
            }
        }

        result = parts.reduce(reducer, "");
        return result.trim();
    }


    return SingleImageButton;
})();
