/* Copyright 2013 Mozilla Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/* globals HTMLCanvasElement */

'use strict';

(function(root, factory) {
    if (typeof define === 'function' && define.amd) {
        define('pdfjs-web/mozPrintCallback_polyfill', ['exports'], factory);
    } else if (typeof exports !== 'undefined') {
        factory(exports);
    } else {
        factory((root.pdfjsWebMozPrintCallbackPolyfill = {}));
    }
}(this, function(exports) {
//#if !(FIREFOX || MOZCENTRAL)
    if ('mozPrintCallback' in document.createElement('canvas')) {
        return;
    }

    // Cause positive result on feature-detection:
    HTMLCanvasElement.prototype.mozPrintCallback = undefined;

    var canvases;   // During print task: non-live NodeList of <canvas> elements
    var index;      // Index of <canvas> element that is being processed

    var print = window.print;
    window.print = function print() {
        if (canvases) {
            console.warn('Ignored window.print() because of a pending print job.');
            return;
        }
        try {
            dispatchEvent('beforeprint');
        } finally {
            canvases = document.querySelectorAll('canvas');
            index = -1;
            next();
        }
    };

    function dispatchEvent(eventType) {
        var event = document.createEvent('CustomEvent');
        event.initCustomEvent(eventType, false, false, 'custom');
        window.dispatchEvent(event);
    }

    function next() {
        if (!canvases) {
            return; // Print task cancelled by user (state reset in abort())
        }

        renderProgress();
        if (++index < canvases.length) {
            var canvas = canvases[index];
            if (typeof canvas.mozPrintCallback === 'function') {
                canvas.mozPrintCallback({
                    context : canvas.getContext('2d'),
                    abort   : abort,
                    done    : next
                });
            } else {
                next();
            }
        } else {
            renderProgress();
            print.call(window);
            setTimeout(abort, 20); // Tidy-up
        }
    }

    function abort() {
        if (canvases) {
            canvases = null;
            renderProgress();
            dispatchEvent('afterprint');
        }
    }

    function renderProgress() {
        var progressContainer = document.getElementById('mozPrintCallback-shim');
        if (canvases && canvases.length) {
            var progress = Math.round(100 * index / canvases.length);
            var progressBar = progressContainer.querySelector('progress');
            var progressPerc = progressContainer.querySelector('.relative-progress');
            progressBar.value = progress;
            progressPerc.textContent = progress + '%';
            progressContainer.removeAttribute('hidden');
            progressContainer.onclick = abort;
        } else {
            progressContainer.setAttribute('hidden', '');
        }
    }

    var hasAttachEvent = !!document.attachEvent;

    window.addEventListener('keydown', function(event) {
        // Intercept Cmd/Ctrl + P in all browsers.
        // Also intercept Cmd/Ctrl + Shift + P in Chrome and Opera
        if (event.keyCode === 80/*P*/ && (event.ctrlKey || event.metaKey) &&
            !event.altKey && (!event.shiftKey || window.chrome || window.opera)) {
            window.print();
            if (hasAttachEvent) {
                // Only attachEvent can cancel Ctrl + P dialog in IE <=10
                // attachEvent is gone in IE11, so the dialog will re-appear in IE11.
                return;
            }
            event.preventDefault();
            if (event.stopImmediatePropagation) {
                event.stopImmediatePropagation();
            } else {
                event.stopPropagation();
            }
            return;
        }
        if (event.keyCode === 27 && canvases) { // Esc
            abort();
        }
    }, true);
    if (hasAttachEvent) {
        document.attachEvent('onkeydown', function(event) {
            event = event || window.event;
            if (event.keyCode === 80/*P*/ && event.ctrlKey) {
                event.keyCode = 0;
                return false;
            }
        });
    }

    if ('onbeforeprint' in window) {
        // Do not propagate before/afterprint events when they are not triggered
        // from within this polyfill. (FF/IE).
        var stopPropagationIfNeeded = function(event) {
            if (event.detail !== 'custom' && event.stopImmediatePropagation) {
                event.stopImmediatePropagation();
            }
        };
        window.addEventListener('beforeprint', stopPropagationIfNeeded, false);
        window.addEventListener('afterprint', stopPropagationIfNeeded, false);
    }
//#endif
}));
