/*
 * jQuery File Upload Image Resize Plugin 1.1.2
 * https://github.com/blueimp/jQuery-File-Upload
 *
 * Copyright 2013, Sebastian Tschan
 * https://blueimp.net
 *
 * Licensed under the MIT license:
 * http://www.opensource.org/licenses/MIT
 */

/*jslint nomen: true, unparam: true, regexp: true */
/*global define, window */

(function (factory) {
    'use strict';
    if (typeof define === 'function' && define.amd) {
        // Register as an anonymous AMD module:
        define([
            'jquery',
            'load-image',
            'canvas-to-blob',
            './jquery.fileupload-process'
        ], factory);
    } else {
        // Browser globals:
        factory(
            window.jQuery,
            window.loadImage
        );
    }
}(function ($, loadImage) {
    'use strict';

    // Prepend to the default processQueue:
    $.blueimp.fileupload.prototype.options.processQueue.unshift(
        {
            action: 'loadImage',
            fileTypes: '@loadImageFileTypes',
            maxFileSize: '@loadImageMaxFileSize',
            noRevoke: '@loadImageNoRevoke',
            disabled: '@disableImageLoad'
        },
        {
            action: 'resizeImage',
            maxWidth: '@imageMaxWidth',
            maxHeight: '@imageMaxHeight',
            minWidth: '@imageMinWidth',
            minHeight: '@imageMinHeight',
            crop: '@imageCrop',
            disabled: '@disableImageResize'
        },
        {
            action: 'saveImage',
            disabled: '@disableImageResize'
        },
        {
            action: 'resizeImage',
            maxWidth: '@previewMaxWidth',
            maxHeight: '@previewMaxHeight',
            minWidth: '@previewMinWidth',
            minHeight: '@previewMinHeight',
            crop: '@previewCrop',
            canvas: '@previewAsCanvas',
            disabled: '@disableImagePreview'
        },
        {
            action: 'setImage',
            // The name of the property the resized image
            // is saved as on the associated file object:
            name: 'preview',
            disabled: '@disableImagePreview'
        }
    );

    // The File Upload Resize plugin extends the fileupload widget
    // with image resize functionality:
    $.widget('blueimp.fileupload', $.blueimp.fileupload, {

        options: {
            // The regular expression for the types of images to load:
            // matched against the file type:
            loadImageFileTypes: /^image\/(gif|jpeg|png)$/,
            // The maximum file size of images to load:
            loadImageMaxFileSize: 5000000, // 5MB
            // The maximum width of resized images:
            imageMaxWidth: 1920,
            // The maximum height of resized images:
            imageMaxHeight: 1080,
            // Define if resized images should be cropped or only scaled:
            imageCrop: false,
            // Disable the resize image functionality by default:
            disableImageResize: true,
            // The maximum width of the preview images:
            previewMaxWidth: 80,
            // The maximum height of the preview images:
            previewMaxHeight: 80,
            // Define if preview images should be cropped or only scaled:
            previewCrop: false,
            // Define if preview images should be resized as canvas elements:
            previewAsCanvas: true
        },

        processActions: {

            // Loads the image given via data.files and data.index
            // as img element if the browser supports canvas.
            // Accepts the options fileTypes (regular expression)
            // and maxFileSize (integer) to limit the files to load:
            loadImage: function (data, options) {
                if (options.disabled) {
                    return data;
                }
                var that = this,
                    file = data.files[data.index],
                    dfd = $.Deferred();
                if (($.type(options.maxFileSize) === 'number' &&
                            file.size > options.maxFileSize) ||
                        (options.fileTypes &&
                            !options.fileTypes.test(file.type)) ||
                        !loadImage(
                            file,
                            function (img) {
                                if (!img.src) {
                                    return dfd.rejectWith(that, [data]);
                                }
                                data.img = img;
                                dfd.resolveWith(that, [data]);
                            },
                            options
                        )) {
                    dfd.rejectWith(that, [data]);
                }
                return dfd.promise();
            },

            // Resizes the image given as data.canvas or data.img
            // and updates data.canvas or data.img with the resized image.
            // Accepts the options maxWidth, maxHeight, minWidth,
            // minHeight, canvas and crop:
            resizeImage: function (data, options) {
                options = $.extend({canvas: true}, options);
                var img = (options.canvas && data.canvas) || data.img,
                    canvas;
                if (img && !options.disabled) {
                    canvas = loadImage.scale(img, options);
                    if (canvas && (canvas.width !== img.width ||
                            canvas.height !== img.height)) {
                        data[canvas.getContext ? 'canvas' : 'img'] = canvas;
                    }
                }
                return data;
            },

            // Saves the processed image given as data.canvas
            // inplace at data.index of data.files:
            saveImage: function (data, options) {
                if (!data.canvas || options.disabled) {
                    return data;
                }
                var that = this,
                    file = data.files[data.index],
                    name = file.name,
                    dfd = $.Deferred(),
                    callback = function (blob) {
                        if (!blob.name) {
                            if (file.type === blob.type) {
                                blob.name = file.name;
                            } else if (file.name) {
                                blob.name = file.name.replace(
                                    /\..+$/,
                                    '.' + blob.type.substr(6)
                                );
                            }
                        }
                        // Store the created blob at the position
                        // of the original file in the files list:
                        data.files[data.index] = blob;
                        dfd.resolveWith(that, [data]);
                    };
                // Use canvas.mozGetAsFile directly, to retain the filename, as
                // Gecko doesn't support the filename option for FormData.append:
                if (data.canvas.mozGetAsFile) {
                    callback(data.canvas.mozGetAsFile(
                        (/^image\/(jpeg|png)$/.test(file.type) && name) ||
                            ((name && name.replace(/\..+$/, '')) ||
                                'blob') + '.png',
                        file.type
                    ));
                } else if (data.canvas.toBlob) {
                    data.canvas.toBlob(callback, file.type);
                } else {
                    return data;
                }
                return dfd.promise();
            },

            // Sets the resized version of the image as a property of the
            // file object, must be called after "saveImage":
            setImage: function (data, options) {
                var img = data.canvas || data.img;
                if (img && !options.disabled) {
                    data.files[data.index][options.name] = img;
                }
                return data;
            }

        }

    });

}));
