/**
 * @license Highcharts JS v6.1.3 (2018-09-12)
 * Client side exporting module
 *
 * (c) 2015 Torstein Honsi / Oystein Moseng
 *
 * License: www.highcharts.com/license
 */
'use strict';
(function (factory) {
	if (typeof module === 'object' && module.exports) {
		module.exports = factory;
	} else if (typeof define === 'function' && define.amd) {
		define(function () {
			return factory;
		});
	} else {
		factory(Highcharts);
	}
}(function (Highcharts) {
	(function (Highcharts) {
		/**
		 * Client side exporting module
		 *
		 * (c) 2015 Torstein Honsi / Oystein Moseng
		 *
		 * License: www.highcharts.com/license
		 */

		/* global MSBlobBuilder */

		var addEvent = Highcharts.addEvent,
		    merge = Highcharts.merge,
		    win = Highcharts.win,
		    nav = win.navigator,
		    doc = win.document,
		    each = Highcharts.each,
		    domurl = win.URL || win.webkitURL || win,
		    isMSBrowser = /Edge\/|Trident\/|MSIE /.test(nav.userAgent),
		    isEdgeBrowser = /Edge\/\d+/.test(nav.userAgent),
		    // Milliseconds to defer image load event handlers to offset IE bug
		    loadEventDeferDelay = isMSBrowser ? 150 : 0;

		// Dummy object so we can reuse our canvas-tools.js without errors
		Highcharts.CanVGRenderer = {};


		/**
		 * Downloads a script and executes a callback when done.
		 * @param {String} scriptLocation
		 * @param {Function} callback
		 */
		function getScript(scriptLocation, callback) {
		    var head = doc.getElementsByTagName('head')[0],
		        script = doc.createElement('script');

		    script.type = 'text/javascript';
		    script.src = scriptLocation;
		    script.onload = callback;
		    script.onerror = function () {
		        Highcharts.error('Error loading script ' + scriptLocation);
		    };

		    head.appendChild(script);
		}

		// Convert dataURL to Blob if supported, otherwise returns undefined
		Highcharts.dataURLtoBlob = function (dataURL) {
		    if (
		        win.atob &&
		        win.ArrayBuffer &&
		        win.Uint8Array &&
		        win.Blob &&
		        domurl.createObjectURL
		    ) {
		        // Try to convert data URL to Blob
		        var parts = dataURL.match(/data:([^;]*)(;base64)?,([0-9A-Za-z+/]+)/),
		            binStr = win.atob(parts[3]), // Assume base64 encoding
		            buf = new win.ArrayBuffer(binStr.length),
		            binary = new win.Uint8Array(buf),
		            blob;

		        for (var i = 0; i < binary.length; ++i) {
		            binary[i] = binStr.charCodeAt(i);
		        }

		        blob = new win.Blob([binary], { 'type': parts[1] });
		        return domurl.createObjectURL(blob);
		    }
		};

		// Download contents by dataURL/blob
		Highcharts.downloadURL = function (dataURL, filename) {
		    var a = doc.createElement('a'),
		        windowRef;

		    // IE specific blob implementation
		    // Don't use for normal dataURLs
		    if (
		        typeof dataURL !== 'string' &&
		        !(dataURL instanceof String) &&
		        nav.msSaveOrOpenBlob
		    ) {
		        nav.msSaveOrOpenBlob(dataURL, filename);
		        return;
		    }

		    // Some browsers have limitations for data URL lengths. Try to convert to
		    // Blob or fall back. Edge always needs that blob.
		    if (isEdgeBrowser || dataURL.length > 2000000) {
		        dataURL = Highcharts.dataURLtoBlob(dataURL);
		        if (!dataURL) {
		            throw 'Data URL length limit reached';
		        }
		    }

		    // Try HTML5 download attr if supported
		    if (a.download !== undefined) {
		        a.href = dataURL;
		        a.download = filename; // HTML5 download attribute
		        doc.body.appendChild(a);
		        a.click();
		        doc.body.removeChild(a);
		    } else {
		        // No download attr, just opening data URI
		        try {
		            windowRef = win.open(dataURL, 'chart');
		            if (windowRef === undefined || windowRef === null) {
		                throw 'Failed to open window';
		            }
		        } catch (e) {
		            // window.open failed, trying location.href
		            win.location.href = dataURL;
		        }
		    }
		};

		// Get blob URL from SVG code. Falls back to normal data URI.
		Highcharts.svgToDataUrl = function (svg) {
		    // Webkit and not chrome
		    var webKit = (
		        nav.userAgent.indexOf('WebKit') > -1 &&
		        nav.userAgent.indexOf('Chrome') < 0
		    );
		    try {
		        // Safari requires data URI since it doesn't allow navigation to blob
		        // URLs. Firefox has an issue with Blobs and internal references,
		        // leading to gradients not working using Blobs (#4550)
		        if (!webKit && nav.userAgent.toLowerCase().indexOf('firefox') < 0) {
		            return domurl.createObjectURL(new win.Blob([svg], {
		                type: 'image/svg+xml;charset-utf-16'
		            }));
		        }
		    } catch (e) {
		        // Ignore
		    }
		    return 'data:image/svg+xml;charset=UTF-8,' + encodeURIComponent(svg);
		};

		// Get data:URL from image URL
		// Pass in callbacks to handle results. finallyCallback is always called at the
		// end of the process. Supplying this callback is optional. All callbacks
		// receive four arguments: imageURL, imageType, callbackArgs and scale.
		// callbackArgs is used only by callbacks and can contain whatever.
		Highcharts.imageToDataUrl = function (
		    imageURL,
		    imageType,
		    callbackArgs,
		    scale,
		    successCallback,
		    taintedCallback,
		    noCanvasSupportCallback,
		    failedLoadCallback,
		    finallyCallback
		) {
		    var img = new win.Image(),
		        taintedHandler,
		        loadHandler = function () {
		            setTimeout(function () {
		                var canvas = doc.createElement('canvas'),
		                    ctx = canvas.getContext && canvas.getContext('2d'),
		                    dataURL;
		                try {
		                    if (!ctx) {
		                        noCanvasSupportCallback(
		                            imageURL,
		                            imageType,
		                            callbackArgs,
		                            scale
		                        );
		                    } else {
		                        canvas.height = img.height * scale;
		                        canvas.width = img.width * scale;
		                        ctx.drawImage(img, 0, 0, canvas.width, canvas.height);

		                        // Now we try to get the contents of the canvas.
		                        try {
		                            dataURL = canvas.toDataURL(imageType);
		                            successCallback(
		                                dataURL,
		                                imageType,
		                                callbackArgs,
		                                scale
		                            );
		                        } catch (e) {
		                            taintedHandler(
		                                imageURL,
		                                imageType,
		                                callbackArgs,
		                                scale
		                            );
		                        }
		                    }
		                } finally {
		                    if (finallyCallback) {
		                        finallyCallback(
		                            imageURL,
		                            imageType,
		                            callbackArgs,
		                            scale
		                        );
		                    }
		                }
		            // IE bug where image is not always ready despite calling load
		            // event.
		            }, loadEventDeferDelay);
		        },
		        // Image load failed (e.g. invalid URL)
		        errorHandler = function () {
		            failedLoadCallback(imageURL, imageType, callbackArgs, scale);
		            if (finallyCallback) {
		                finallyCallback(imageURL, imageType, callbackArgs, scale);
		            }
		        };

		    // This is called on load if the image drawing to canvas failed with a
		    // security error. We retry the drawing with crossOrigin set to Anonymous.
		    taintedHandler = function () {
		        img = new win.Image();
		        taintedHandler = taintedCallback;
		        // Must be set prior to loading image source
		        img.crossOrigin = 'Anonymous';
		        img.onload = loadHandler;
		        img.onerror = errorHandler;
		        img.src = imageURL;
		    };

		    img.onload = loadHandler;
		    img.onerror = errorHandler;
		    img.src = imageURL;
		};

		/**
		 * Get data URL to an image of an SVG and call download on it
		 *
		 * options object:
		 * - filename: Name of resulting downloaded file without extension
		 * - type: File type of resulting download
		 * - scale: Scaling factor of downloaded image compared to source
		 * - libURL: URL pointing to location of dependency scripts to download on
		 *   demand
		 */
		Highcharts.downloadSVGLocal = function (
		    svg,
		    options,
		    failCallback,
		    successCallback
		) {
		    var svgurl,
		        blob,
		        objectURLRevoke = true,
		        finallyHandler,
		        libURL = options.libURL || Highcharts.getOptions().exporting.libURL,
		        dummySVGContainer = doc.createElement('div'),
		        imageType = options.type || 'image/png',
		        filename = (
		            (options.filename || 'chart') +
		            '.' +
		            (imageType === 'image/svg+xml' ? 'svg' : imageType.split('/')[1])
		        ),
		        scale = options.scale || 1;

		    // Allow libURL to end with or without fordward slash
		    libURL = libURL.slice(-1) !== '/' ? libURL + '/' : libURL;

		    function svgToPdf(svgElement, margin) {
		        var width = svgElement.width.baseVal.value + 2 * margin,
		            height = svgElement.height.baseVal.value + 2 * margin,
		            pdf = new win.jsPDF( // eslint-disable-line new-cap
		                'l',
		                'pt',
		                [width, height]
		            );

		        // Workaround for #7090, hidden elements were drawn anyway. It comes
		        // down to https://github.com/yWorks/svg2pdf.js/issues/28. Check this
		        // later.
		        each(
		            svgElement.querySelectorAll('*[visibility="hidden"]'),
		            function (node) {
		                node.parentNode.removeChild(node);
		            }
		        );

		        win.svg2pdf(svgElement, pdf, { removeInvalid: true });
		        return pdf.output('datauristring');
		    }

		    function downloadPDF() {
		        dummySVGContainer.innerHTML = svg;
		        var textElements = dummySVGContainer.getElementsByTagName('text'),
		            titleElements,
		            svgData,
		            // Copy style property to element from parents if it's not there.
		            // Searches up hierarchy until it finds prop, or hits the chart
		            // container.
		            setStylePropertyFromParents = function (el, propName) {
		                var curParent = el;
		                while (curParent && curParent !== dummySVGContainer) {
		                    if (curParent.style[propName]) {
		                        el.style[propName] = curParent.style[propName];
		                        break;
		                    }
		                    curParent = curParent.parentNode;
		                }
		            };

		        // Workaround for the text styling. Making sure it does pick up settings
		        // for parent elements.
		        each(textElements, function (el) {
		            // Workaround for the text styling. making sure it does pick up the
		            // root element
		            each(['font-family', 'font-size'], function (property) {
		                setStylePropertyFromParents(el, property);
		            });
		            el.style['font-family'] = (
		                el.style['font-family'] &&
		                el.style['font-family'].split(' ').splice(-1)
		            );

		            // Workaround for plotband with width, removing title from text
		            // nodes
		            titleElements = el.getElementsByTagName('title');
		            each(titleElements, function (titleElement) {
		                el.removeChild(titleElement);
		            });
		        });
		        svgData = svgToPdf(dummySVGContainer.firstChild, 0);
		        try {
		            Highcharts.downloadURL(svgData, filename);
		            if (successCallback) {
		                successCallback();
		            }
		        } catch (e) {
		            failCallback(e);
		        }
		    }

		    // Initiate download depending on file type
		    if (imageType === 'image/svg+xml') {
		        // SVG download. In this case, we want to use Microsoft specific Blob if
		        // available
		        try {
		            if (nav.msSaveOrOpenBlob) {
		                blob = new MSBlobBuilder();
		                blob.append(svg);
		                svgurl = blob.getBlob('image/svg+xml');
		            } else {
		                svgurl = Highcharts.svgToDataUrl(svg);
		            }
		            Highcharts.downloadURL(svgurl, filename);
		            if (successCallback) {
		                successCallback();
		            }
		        } catch (e) {
		            failCallback(e);
		        }
		    } else if (imageType === 'application/pdf') {
		        if (win.jsPDF && win.svg2pdf) {
		            downloadPDF();
		        } else {
		            // Must load pdf libraries first. // Don't destroy the object URL
		            // yet since we are doing things asynchronously. A cleaner solution
		            // would be nice, but this will do for now.
		            objectURLRevoke = true;
		            getScript(libURL + 'jspdf.js', function () {
		                getScript(libURL + 'svg2pdf.js', function () {
		                    downloadPDF();
		                });
		            });
		        }
		    } else {
		        // PNG/JPEG download - create bitmap from SVG

		        svgurl = Highcharts.svgToDataUrl(svg);
		        finallyHandler = function () {
		            try {
		                domurl.revokeObjectURL(svgurl);
		            } catch (e) {
		                // Ignore
		            }
		        };
		        // First, try to get PNG by rendering on canvas
		        Highcharts.imageToDataUrl(
		            svgurl,
		            imageType,
		            {},
		            scale,
		            function (imageURL) {
		                // Success
		                try {
		                    Highcharts.downloadURL(imageURL, filename);
		                    if (successCallback) {
		                        successCallback();
		                    }
		                } catch (e) {
		                    failCallback(e);
		                }
		            }, function () {
		                // Failed due to tainted canvas
		                // Create new and untainted canvas
		                var canvas = doc.createElement('canvas'),
		                    ctx = canvas.getContext('2d'),
		                    imageWidth = svg.match(
		                        /^<svg[^>]*width\s*=\s*\"?(\d+)\"?[^>]*>/
		                    )[1] * scale,
		                    imageHeight = svg.match(
		                        /^<svg[^>]*height\s*=\s*\"?(\d+)\"?[^>]*>/
		                    )[1] * scale,
		                    downloadWithCanVG = function () {
		                        ctx.drawSvg(svg, 0, 0, imageWidth, imageHeight);
		                        try {
		                            Highcharts.downloadURL(
		                                nav.msSaveOrOpenBlob ?
		                                    canvas.msToBlob() :
		                                    canvas.toDataURL(imageType),
		                                filename
		                            );
		                            if (successCallback) {
		                                successCallback();
		                            }
		                        } catch (e) {
		                            failCallback(e);
		                        } finally {
		                            finallyHandler();
		                        }
		                    };

		                canvas.width = imageWidth;
		                canvas.height = imageHeight;
		                if (win.canvg) {
		                    // Use preloaded canvg
		                    downloadWithCanVG();
		                } else {
		                    // Must load canVG first. // Don't destroy the object URL
		                    // yet since we are doing things asynchronously. A cleaner
		                    // solution would be nice, but this will do for now.
		                    objectURLRevoke = true;
		                    // Get RGBColor.js first, then canvg
		                    getScript(libURL + 'rgbcolor.js', function () {
		                        getScript(libURL + 'canvg.js', function () {
		                            downloadWithCanVG();
		                        });
		                    });
		                }
		            },
		            // No canvas support
		            failCallback,
		            // Failed to load image
		            failCallback,
		            // Finally
		            function () {
		                if (objectURLRevoke) {
		                    finallyHandler();
		                }
		            }
		        );
		    }
		};

		// Get SVG of chart prepared for client side export. This converts embedded
		// images in the SVG to data URIs. The options and chartOptions arguments are
		// passed to the getSVGForExport function.
		Highcharts.Chart.prototype.getSVGForLocalExport = function (
		    options,
		    chartOptions,
		    failCallback,
		    successCallback
		) {
		    var chart = this,
		        images,
		        imagesEmbedded = 0,
		        chartCopyContainer,
		        chartCopyOptions,
		        el,
		        i,
		        l,
		        // After grabbing the SVG of the chart's copy container we need to do
		        // sanitation on the SVG
		        sanitize = function (svg) {
		            return chart.sanitizeSVG(svg, chartCopyOptions);
		        },
		        // Success handler, we converted image to base64!
		        embeddedSuccess = function (imageURL, imageType, callbackArgs) {
		            ++imagesEmbedded;

		            // Change image href in chart copy
		            callbackArgs.imageElement.setAttributeNS(
		                'http://www.w3.org/1999/xlink',
		                'href',
		                imageURL
		            );

		            // When done with last image we have our SVG
		            if (imagesEmbedded === images.length) {
		                successCallback(sanitize(chartCopyContainer.innerHTML));
		            }
		        };

		    // Hook into getSVG to get a copy of the chart copy's container (#8273)
		    chart.unbindGetSVG = addEvent(chart, 'getSVG', function (e) {
		        chartCopyOptions = e.chartCopy.options;
		        chartCopyContainer = e.chartCopy.container.cloneNode(true);
		    });

		    // Trigger hook to get chart copy
		    chart.getSVGForExport(options, chartOptions);
		    images = chartCopyContainer.getElementsByTagName('image');

		    try {
		        // If there are no images to embed, the SVG is okay now.
		        if (!images.length) {
		            // Use SVG of chart copy
		            successCallback(sanitize(chartCopyContainer.innerHTML));
		            return;
		        }

		        // Go through the images we want to embed
		        for (i = 0, l = images.length; i < l; ++i) {
		            el = images[i];
		            Highcharts.imageToDataUrl(el.getAttributeNS(
		                'http://www.w3.org/1999/xlink',
		                'href'
		            ), 'image/png', { imageElement: el }, options.scale,
		                embeddedSuccess,
		                // Tainted canvas
		                failCallback,
		                // No canvas support
		                failCallback,
		                // Failed to load source
		                failCallback
		            );
		        }
		    } catch (e) {
		        failCallback(e);
		    }

		    // Clean up
		    chart.unbindGetSVG();
		};

		/**
		 * Exporting and offline-exporting modules required. Export a chart to an image
		 * locally in the user's browser.
		 *
		 * @param  {Object} exportingOptions
		 *         Exporting options, the same as in {@link
		 *         Highcharts.Chart#exportChart}.
		 * @param  {Options} chartOptions
		 *         Additional chart options for the exported chart. For example a
		 *         different background color can be added here, or `dataLabels`
		 *         for export only.
		 */
		Highcharts.Chart.prototype.exportChartLocal = function (
		    exportingOptions,
		    chartOptions
		) {
		    var chart = this,
		        options = Highcharts.merge(chart.options.exporting, exportingOptions),
		        fallbackToExportServer = function (err) {
		            if (options.fallbackToExportServer === false) {
		                if (options.error) {
		                    options.error(options, err);
		                } else {
		                    Highcharts.error(28, true); // Fallback disabled
		                }
		            } else {
		                chart.exportChart(options);
		            }
		        },
		        svgSuccess = function (svg) {
		            // If SVG contains foreignObjects all exports except SVG will fail,
		            // as both CanVG and svg2pdf choke on this. Gracefully fall back.
		            if (
		                svg.indexOf('<foreignObject') > -1 &&
		                options.type !== 'image/svg+xml'
		            ) {
		                fallbackToExportServer(
		                    'Image type not supported for charts with embedded HTML'
		                );
		            } else {
		                Highcharts.downloadSVGLocal(
		                    svg,
		                    options,
		                    fallbackToExportServer
		                );
		            }
		        };

		    // If we are on IE and in styled mode, add a whitelist to the renderer for
		    // inline styles that we want to pass through. There are so many styles by
		    // default in IE that we don't want to blacklist them all.
    

		    // Always fall back on:
		    // - MS browsers: Embedded images JPEG/PNG, or any PDF
		    // - Embedded images and PDF
		    if (
		        (
		            isMSBrowser &&
		            (
		                options.type === 'application/pdf' ||
		                chart.container.getElementsByTagName('image').length &&
		                options.type !== 'image/svg+xml'
		            )
		        ) || (
		            options.type === 'application/pdf' &&
		            chart.container.getElementsByTagName('image').length
		        )
		    ) {
		        fallbackToExportServer(
		            'Image type not supported for this chart/browser.'
		        );
		        return;
		    }

		    chart.getSVGForLocalExport(
		        options,
		        chartOptions,
		        fallbackToExportServer,
		        svgSuccess
		    );
		};

		// Extend the default options to use the local exporter logic
		merge(true, Highcharts.getOptions().exporting, {
		    libURL: 'https://code.highcharts.com/6.1.3/lib/',

		    // When offline-exporting is loaded, redefine the menu item definitions
		    // related to download.
		    menuItemDefinitions: {
		        downloadPNG: {
		            textKey: 'downloadPNG',
		            onclick: function () {
		                this.exportChartLocal();
		            }
		        },
		        downloadJPEG: {
		            textKey: 'downloadJPEG',
		            onclick: function () {
		                this.exportChartLocal({
		                    type: 'image/jpeg'
		                });
		            }
		        },
		        downloadSVG: {
		            textKey: 'downloadSVG',
		            onclick: function () {
		                this.exportChartLocal({
		                    type: 'image/svg+xml'
		                });
		            }
		        },
		        downloadPDF: {
		            textKey: 'downloadPDF',
		            onclick: function () {
		                this.exportChartLocal({
		                    type: 'application/pdf'
		                });
		            }
		        }

		    }
		});

	}(Highcharts));
	return (function () {


	}());
}));
