(function (factory) {
    'use strict';

    if (typeof define === 'function' && define.amd) {
        define(['jquery'], factory);
    } else if (typeof module === 'object' && module.exports) {
        module.exports = factory(require('jquery'));
    } else {
        factory(window.jQuery);
    }
}
(function ($) {
    'use strict';

    function imageAdjustedHeight(heightInputValue, imageOriginalWidth, imageOriginalHeight) {
        return parseInt(heightInputValue * (imageOriginalHeight / imageOriginalWidth), 10);
    }

    function imageAdjustedWidth(widthInputValue, imageOriginalWidth, imageOriginalHeight) {
        return parseInt(widthInputValue * (imageOriginalWidth / imageOriginalHeight), 10);
    }

    $.extend(true, $.summernote.lang, {
        'en-US': {
            imageAttributes: {
                edit: 'Edit Attributes',
                titleLabel: 'Title',
                altLabel: 'Alternative Text',
                linkLabel: 'Link',
                targetLabel: 'Open in a new window/tab?',
                tooltip: 'Edit Image',
                dialogSaveBtnMessage: 'Save',
                dialogTitle: 'Change Image Attributes',
                widthLabel: 'Width',
                heightLabel: 'Height',
                imageLockLabel: 'Lock',
                resizeLabel: 'Resize'
            }
        }
    });

    $.extend($.summernote.options, {
        imageAttributes: {
            icon: '<i class="note-icon-pencil" />',
            linkClass: 'note-link',
            manageAspectRatio: true // true = Lock the Image Width/Height, Default to true
        }
    });

    $.extend($.summernote.plugins, {
        'imageAttributes': function (context) {
            var self = this;
            var ui = $.summernote.ui,
                $editable = context.layoutInfo.editable,
                options = context.options,
                $editor = context.layoutInfo.editor,
                lang = options.langInfo,
                $note = context.layoutInfo.note;

            context.memo('button.imageAttributes', function () {
                var button = ui.button({
                    contents: options.imageAttributes.icon,
                    container: false,
                    tooltip: lang.imageAttributes.tooltip,
                    click: function () {
                        context.invoke('imageAttributes.show');
                    }
                });
                return button.render();
            });

            this.initialize = function () {
                // Determine whether the modal appends in Body or Inside the Editor
                var $container = options.imageAttributes.dialogsInBody ? $(document.body) : $editor;

                var body = '<div style="padding: 15px 30px">' +
                    '<div class="form-group">' +
                        '<label class="note-form-label">' + lang.imageAttributes.linkLabel + '</label>' +
                        '<input class="form-control note-input note-image-link" type="text" />' +
                    '</div>' +
                    '<div class="form-group">' +
                        '<label class="note-form-label">' +
                            '<input class="note-input note-image-link-target" type="checkbox" />' +
                            '<span style="font-weight: normal; padding-left: 10px">' +
                                lang.imageAttributes.targetLabel +
                            '</span>' +
                        '</label>' +
                    '</div>' +
                    '<div class="form-group">' +
                        '<label class="note-form-label">' + lang.imageAttributes.altLabel + '</label>' +
                        '<input class="form-control note-input note-image-alt-text" type="text" />' +
                    '</div>' +
                    '<div class="row">' +
                        '<div class="form-group col-sm-4">' +
                            '<label class="note-form-label">' + lang.imageAttributes.widthLabel +'</label>' +
                            '<input class="form-control note-input note-image-width" type="number" />' +
                        '</div>' +
                        '<div class="form-group col-sm-4">' +
                            '<label class="note-form-label">' + lang.imageAttributes.heightLabel + '</label>' +
                            '<input class="form-control note-input note-image-height" type="number" />' +
                        '</div>' +
                        '<div class="form-group col-sm-4">' +
                            '<label class="note-form-label">' + lang.imageAttributes.imageLockLabel + '</label>' +
                            '<div class="btn-group btn-group-sm" style="display: block; margin: 3px 0 0 5px;">' +
                                '<button type="button" class="btn btn-default lock-button" style="height:30px;">' +
                                    '<span class="fa fa-lock" aria-hidden="false"></span>' +
                                    '<span class="fa fa-unlock hide" aria-hidden="true"></span>' +
                                '</button>' +
                                '<button type="button" ' +
                                   'class="btn btn-default reset-size-buttton" ' +
                                    'aria-label="Resize" data-toggle="tooltip" ' +
                                    'title="' + lang.imageAttributes.resizeLabel + '">' +
                                    '<span class="fa fa-repeat" aria-hidden="false"></span>' +
                                '</button>' +
                            '</div>' +
                        '</div>' +
                    '</div>' +
                '</div>';

                var footer = '<button href="#" class="btn btn-primary note-image-title-btn note-btn">' +
                             lang.imageAttributes.dialogSaveBtnMessage +
                             '</button>';

                this.$dialog = ui.dialog({
                    title: lang.imageAttributes.dialogTitle,
                    body: body,
                    footer: footer
                }).render().appendTo($container);

            };

            this.destroy = function () {
                ui.hideDialog(this.$dialog);
                this.$dialog.remove();
            };

            this.bindEnterKey = function ($input, $btn) {
                $input.on('keypress', function (event) {
                    if (event.keyCode === 13) {
                        $btn.trigger('click');
                    }
                });
            };

            this.show = function () {
                var $img = $($editable.data('target'));
                var _imgInfo = {
                    alt: $img.attr('alt'),
                    link: $img.parent('a').attr('href'),
                    target: $img.parent('a').attr('target') === 'blank',
                    width: $img.width(),
                    height: $img.height()
                };

                var img = new Image();
                img.onload = function () {
                    _imgInfo.naturalWidth = img.width;
                    _imgInfo.naturalHeight = img.height;
                };
                img.src = $img.attr('src');

                this.showLinkDialog(_imgInfo)
                    .then(function (imgInfo) {
                        ui.hideDialog(self.$dialog);
                        var isAnyChangeMade = false;

                        // NOTE: Must add more conditions if any new field is being added!
                        if (
                            _imgInfo.link !== imgInfo.link ||
                            _imgInfo.target !== imgInfo.target ||
                            _imgInfo.alt !== imgInfo.alt ||
                            _imgInfo.width !== imgInfo.width ||
                            _imgInfo.height !== imgInfo.height
                        ) {
                            isAnyChangeMade = true;
                        }

                        if (imgInfo.alt) {
                            $img.attr('alt', imgInfo.alt);
                        }
                        else {
                            $img.removeAttr('alt');
                        }

                        if (imgInfo.title) {
                            $img.attr('title', imgInfo.title);
                        }
                        else {
                            $img.removeAttr('title');
                        }

                        if (imgInfo.width) {
                            $img.css('width', imgInfo.width);
                        }

                        if (imgInfo.height) {
                            $img.css('height', imgInfo.height);
                        }

                        var $parentAnchorLink = $img.parent();
                        var isUpdateLink = (imgInfo.link !== _imgInfo.link);

                        if (! imgInfo.link.length) {
                            $parentAnchorLink.children().first().unwrap();
                        }

                        var $newLink;
                        if (imgInfo.link && isUpdateLink) {
                            if ($parentAnchorLink.is('a')) {
                                $newLink = $parentAnchorLink.attr('href', imgInfo.link);
                            } else {
                                $newLink = $img.wrap('<a href="' + imgInfo.link + '"></a>').parent();
                            }
                        }

                        if (imgInfo.target) {
                            $img.parent('a').attr('target', '_blank').addClass(options.imageAttributes.linkClass);
                        } else {
                            $img.parent('a').removeAttr('target', '_blank').addClass(options.imageAttributes.linkClass);
                        }

                        if (isAnyChangeMade) {
                            var _content = context.invoke('code');

                            $note.val(_content);
                            $note.trigger('summernote.change', _content);
                        }
                    });
            };

            this.showLinkDialog = function (imgInfo) {
                return $.Deferred(function (deferred) {
                    var $imageTitle = self.$dialog.find('.note-image-title-text');
                    var $imageLink = self.$dialog.find('.note-image-link');
                    var $imageTarget = self.$dialog.find('.note-image-link-target');
                    var $imageAlt = self.$dialog.find('.note-image-alt-text');
                    var $editBtn = self.$dialog.find('.note-image-title-btn');
                    var $imageWidthInput = self.$dialog.find('.note-image-width');
                    var $imageHeightInput = self.$dialog.find('.note-image-height');
                    var $lockButton = self.$dialog.find('.lock-button');
                    var $resetSizeButton = self.$dialog.find('.reset-size-buttton');
                    var $unlockIcon = $lockButton.find('.fa-unlock');
                    var $lockIcon = $lockButton.find('.fa-lock');

                    var isLocked = (typeof options.imageAttributes.manageAspectRatio === 'undefined') ?
                        true : options.imageAttributes.manageAspectRatio;

                    if (isLocked){
                        $unlockIcon.addClass('hide').removeClass('show');
                        $lockIcon.addClass('show').removeClass('hide');
                    } else {
                        $unlockIcon.addClass('show').removeClass('hide');
                        $lockIcon.addClass('hide').removeClass('show');
                    }

                    $lockButton.on('click', function (event) {
                        event.preventDefault();
                        isLocked = !isLocked;

                        if (isLocked) {
                            $unlockIcon.addClass('hide').removeClass('show');
                            $lockIcon.addClass('show').removeClass('hide');

                            $imageHeightInput.val(
                                imageAdjustedHeight($imageWidthInput.val(), imgInfo.naturalWidth, imgInfo.naturalHeight
                                )
                            );
                        } else {
                            $unlockIcon.addClass('show').removeClass('hide');
                            $lockIcon.addClass('hide').removeClass('show');
                        }
                    });

                    $resetSizeButton.on('click', function (event) {
                        event.preventDefault();
                        $imageWidthInput.val(imgInfo.width);
                        $imageHeightInput.val(imgInfo.height);
                    });

                    $imageHeightInput.on('input', function () {
                        if (isLocked) {
                            $imageWidthInput.val(
                                imageAdjustedWidth(this.value, imgInfo.naturalWidth, imgInfo.naturalHeight)
                            );
                        }
                    });

                    $imageWidthInput.on('input', function () {
                        if (isLocked) {
                            $imageHeightInput.val(
                                imageAdjustedHeight(this.value, imgInfo.naturalWidth, imgInfo.naturalHeight)
                            );
                        }
                    });

                    ui.onDialogShown(self.$dialog, function () {
                        context.triggerEvent('dialog.shown');

                        $editBtn.on('click', function (event) {
                            event.preventDefault();
                            deferred.resolve({
                                title: $imageTitle.val(),
                                alt: $imageAlt.val(),
                                link: $imageLink.val(),
                                target: $imageTarget.is(':checked'),
                                width: $imageWidthInput.val(),
                                height: $imageHeightInput.val()
                            });
                        });

                        $imageTitle.val(imgInfo.title);
                        self.bindEnterKey($imageTitle, $editBtn);

                        $imageAlt.val(imgInfo.alt);
                        self.bindEnterKey($imageAlt, $editBtn);

                        $imageLink.val(imgInfo.link);
                        self.bindEnterKey($imageLink, $editBtn);

                        $imageTarget.prop('checked', imgInfo.target);

                        $imageWidthInput.val(imgInfo.width);
                        self.bindEnterKey($imageWidthInput, $editBtn);

                        $imageHeightInput.val(imgInfo.height);
                        self.bindEnterKey($imageHeightInput, $editBtn);

                    });

                    ui.onDialogHidden(self.$dialog, function () {
                        $editBtn.off('click');
                        $imageWidthInput.off('input');
                        $imageHeightInput.off('input');
                        $lockButton.off('click');
                        $resetSizeButton.off('click');
                        $unlockIcon.off('click');
                        $lockIcon.off('click');

                        if (deferred.state() === 'pending') {
                            deferred.reject();
                        }
                    });
                    ui.showDialog(self.$dialog);
                });
            };
        }
    });
}));