(function ($) {
    var 
        gallery,
        slideshowPreview,
        options,
        globalControls,
        additionalParam,

        saveLoader,
        loadLoader,
        loadLoaderIsShown = true,
        overlay,

        globalData = window.magictoolbox_WordPress_MagicSlideshow_admin_modal_object,
        savedSlideshowData;

    window.ajaxurl = globalData.ajax;

    $(document).on('wplink-open', function(wrap, node) {
        wpLink.refresh();
        wpLink.update();

        $('#wp-link-url').val($(wpLink.textarea).attr('href'));
        $('#wp-link-target').prop('checked', $(wpLink.textarea).attr('new-window') === 'true');
    });

    $(document).on('wplink-close', function(wrap, node) {

    });

    function showOverlay () {
        if (gallery && gallery.slides.length) {
            overlay.addClass('shown');
        }
    }

    function parseOptions(str) {
        var opt = {};

        if (str && str !== 'null') {
            $.each(str.split(';'), function (index, value) {
                value = $.trim(value);
                if (value !== '') {
                    value = value.split(':');

                    opt[$.trim(value[0])] = $.trim(value[1]);
                }
            });    
        }

        return opt;
    }

    function SlideshowPreview () {
        this.container = $('.slideshow-preview');
    }

    $.extend(SlideshowPreview.prototype, {
        makeSlideshow: function() {
            var self = this, slides, slideshowContainer, slideshowOptions, slideshowMobileOptions;
            this.container.css('height', this.container.height() + 'px');

            MagicSlideshow.stop();
            this.container.html('');
            slides = gallery.getHtmlSlides();

            if (slides.length) {
                $('.browser-magictoolbox-technologies').css('visibility', '');
                slideshowOptions = options.getSlideshowOptions();
                slideshowMobileOptions = options.getSlideshowOptions(true);

                slideshowContainer = $('<div>');
                slideshowContainer.addClass('MagicSlideshow');

                slideshowContainer.attr('data-options', slideshowOptions);
                slideshowContainer.attr('data-mobile-options', slideshowMobileOptions);

                $.each(slides, function (index, slide) {
                    slideshowContainer.append(slide);
                });

                this.container.append(slideshowContainer);

                setTimeout(function() {
                    MagicSlideshow.start();
                    self.container.css('height', '');
                }, 0);
            } else {
                this.container.css('height', '');
                $('.browser-magictoolbox-technologies').css('visibility', 'hidden');
            }

            if (overlay) {
                overlay.removeClass('shown');
            }
        }
    });

    function Option (node) {
        this.container = node;
        this.isDisabled = true;
        this.disableOptionsClass = 'disabled-option';
        this.button = this.container.find('button');

        this.actionNode = this.container.find('input');
        if (!this.actionNode.length) {
            this.actionNode = this.container.find('select');
        }

        this.isSwitchControl = this.actionNode.parent().hasClass('switch-control');

        this.name = this.actionNode.attr('name');
        this.type = this.actionNode[0].tagName.toLowerCase();

        this.setEvents();

        this.lastValue = this.actionNode.val();

        if (this.isSwitchControl) {
            this.actionNode.prop('checked', this.lastValue === 'Yes' ? true : false);
        }
    }

    $.extend(Option.prototype, {
        setEvents: function () {
            var self = this;

            this.button.on('click', function (e) {
                e.preventDefault();
                self.changeState();
                self.makeSlideshow();
            });

            this.actionNode.on('change', function (e) {
                if (self.isSwitchControl) {
                    self.actionNode.val(self.actionNode.prop('checked') ? 'Yes': 'No');
                }

                self.makeSlideshow();
            });

            if (this.type === 'input') {
                this.actionNode.on('keyup', function (e) {
                    self.makeSlideshow();
                });
            }
        },

        makeSlideshow: function () {
            var value = this.actionNode.val();
            if (this.lastValue !== value) {
                this.lastValue = value;
                showOverlay();
            }
        },

        changeState: function () {
            if (this.isDisabled) {
                this.isDisabled = false;
                this.container.removeClass(this.disableOptionsClass);
                this.actionNode.prop('disabled', false);
                this.button
                    .attr('title', 'Lock')
                    .removeClass('dashicons-lock')
                    .addClass('dashicons-unlock');
            } else {
                this.isDisabled = true;
                this.container.addClass(this.disableOptionsClass);
                this.actionNode.prop('disabled', true);
                this.button
                    .attr('title', 'Unlock')
                    .removeClass('dashicons-unlock')
                    .addClass('dashicons-lock');

                this.actionNode.val(this.actionNode.attr('data-default-value'));

                if (this.isSwitchControl) {
                    this.actionNode.prop('checked', this.actionNode.attr('data-default-value') === 'Yes' ? true : false);
                }
            }
        },

        getValue: function (corrected, isDefault) {
            var result = null;

            if (!this.isDisabled || isDefault) {
                if (isDefault) {
                    result = this.actionNode.attr('data-default-value');
                } else {
                    result = this.actionNode.val();
                }

                if (corrected) {
                    if (result === 'Yes') {
                        result = true;
                    } else if (result === 'No') {
                        result = false;
                    }
                }
            }

            return result;
        },

        setValue: function (value) {
            if ($.type(value) === 'boolean') {
                value = value ? 'Yes' : 'No';
            } else if ($.type(value) === 'string') {
                if (value === 'true' || value === 'false') {
                    value = value === 'true' ? 'Yes' : 'No';
                }
            }

            this.actionNode.val(value);

            if (this.isSwitchControl) {
                this.actionNode.prop('checked', value === 'Yes' ? true : false);
            }

            this.changeState();
        }
    });

    function Options () {
        this.options = {};
        this.mobileOptions = {};

        this.settings = {
            container: $('#custom-options-container'),
            mobileContainer: $('#custom-mobile-options-container')
        };
    }

    $.extend(Options.prototype, {
        _parse: function (container, obj, currentOpt) {
            var self = this, key;

            $.each(container.find('tbody').find('tr'), function (index, tr) {
                if (!$(tr).hasClass('caption')) {
                    var opt = new Option($(tr));
                    obj[opt.name] = opt;
                }
            });

            for (key in currentOpt) {
                obj[key].setValue(currentOpt[key]);
            }
        },

        parse: function () {
            var key, opt = {};

            this._parse(this.settings.container, this.options, parseOptions(savedSlideshowData.options));
            this._parse(this.settings.mobileContainer, this.mobileOptions, parseOptions(savedSlideshowData.mobileOptions));

            for (key in this.options) {
                opt[key] = this.options[key].getValue(true, true);
            }

            // set global options
            window.MagicSlideshowOptions = opt;
        },

        getSlideshowOptions: function (mobile) {
            var result = null, key, opt = this.options;

            if (mobile) {
                opt = this.mobileOptions;
            }

            for (key in opt) {
                var value = opt[key].getValue(true);
                if (value !== null) {
                    if (result === null) { result = ''; }
                    result += (key + ':' + value + ';');
                }
            }

            return result;
        }
    });

    function Slide (data) {
        this.type = 'image';
        this.data = data;
        this.container = null;
        this.image = null;
        this.isLoaded = false;
        this.removeButton = null;
        this.timer = null;

        this.title = {
            node: null,
            input: $('<input type="text">').val(this.data.title)
        };

        this.caption = {
            node: null,
            input: $('<input type="text">').val(this.data.caption)
        };

        this.link = {
            node: null,
            input: null,
            inputId: 'wplink-' + this.data.id,
            control: null
        };

        this.isLoading = false;

        this.container = $('<li>');
        this.container.attr('data-item-id', this.data.id);
        this.container.addClass("ui-state-default");
    }

    $.extend(Slide.prototype, {
        checkSlide: function (id) {
            return id === this.data.id;
        },

        makeSlideshow: function () {
            clearTimeout(this.timer);
            this.timer = setTimeout(function () {
                slideshowPreview.makeSlideshow();
            }, 1000);
        },

        getSlideshowHtmlData: function () {
            var result, img,
                title, caption, link;
            switch (this.type) {
                case 'image':
                    title = this.getTitle();
                    caption = this.getCaption();
                    link = this.getLink();

                    img = $('<img>');
                    img.attr('src', this.data.sizes.full.url);

                    if (this.data.alt && $.trim(this.data.alt) !== '') {
                        img.attr('alt', this.data.alt);
                    }

                    if (title.use) {
                        if ($.trim(title.value) !== '') {
                            img.attr('title', title.value);
                        }
                    }

                    if (caption.use) {
                        if ($.trim(caption.value) !== '') {
                            img.attr('data-caption', caption.value);
                        }
                    }

                    if (this.data.sizes && this.data.sizes.thumbnail) {
                        img.attr('data-thumb-image', this.data.sizes.thumbnail.url);
                    }

                    if (link.use && link.url) {
                        result = $('<a>');
                        result.attr('href', link.url);
                        if (link.newWindow) {
                            result.attr('target', '_blank');
                        }

                        result.append(img);
                    } else {
                        result = img;
                    }
                    break;
                case 'video':
                break;
            }

            return result;
        },

        changeCheckboxState: function (type, node) {
            var parent = node.parent().parent(),
                className = 'hidden-block',
                use;

            switch(type) {
                case 'title':
                    use = this.title.node.prop('checked');
                    this.title.input.prop('disabled', !use);
                    break;
                case 'caption':
                    use = this.caption.node.prop('checked');
                    this.caption.input.prop('disabled', !use);
                    break;
                case 'link':
                    use = this.link.node.prop('checked');
                    this.link.input.prop('disabled', !use);
                    this.link.control.prop('disabled', !use);
                    break;
            }

            if (!use) {
                parent.addClass(className);
            } else {
                parent.removeClass(className);
            }
        },

        getTitleControl: function () {
            var self = this, node = $('<div>');
            
            node.addClass('hidden-block');
            this.title.node = $('<input>');
            this.title.node.attr('type', 'checkbox');

            this.title.node.on('change', function (e) {
                e.stopPropagation();
                self.changeCheckboxState('title', $(this));
                self.makeSlideshow();
            });

            this.title.input.prop('disabled', true);

            node
                .append(
                    $('<label>')
                        .append(this.title.node)
                        .append($('<span>').text('Show title'))
                )
                .append(
                    $('<div class="concealed-block">').addClass('shown-value').append(this.title.input)
                );

            return node;

        },

        getCaptionControl: function () {
            var self = this,
                node = $('<div>');

            node.addClass('hidden-block');
            this.caption.node = $('<input>');
            this.caption.node.attr('type', 'checkbox');

            this.caption.node.on('change', function (e) {
                e.stopPropagation();
                self.changeCheckboxState('caption', $(this));
                self.makeSlideshow();
            });

            this.caption.input.prop('disabled', true);

            node
                .append(
                    $('<label>')
                        .append(this.caption.node)
                        .append($('<span>').text('Show caption'))
                )
                .append($('<div class="concealed-block">').addClass('shown-value').append(this.caption.input));

            return node;
        },

        getLinkControl: function () {
            var self = this, node = $('<div>');

            node.addClass('hidden-block');
            this.link.node = $('<input>');
            this.link.node.attr('type', 'checkbox');

            this.link.node.on('change', function (e) {
                e.stopPropagation();
                self.changeCheckboxState('link', $(this));
                self.makeSlideshow();
            });

            this.link.input = $('<input>');
            this.link.input.attr('type', 'text');
            this.link.input.attr('id', this.link.inputId);
            this.link.input.attr('new-window', false);
            this.link.input.prop('disabled', true);

            this.link.input.on('keyup', function (e) {
                e.preventDefault();
                self.link.input.attr('href', self.link.input.val());
                wpLink.refresh();
                wpLink.update();
                self.makeSlideshow();
            });

            this.link.input.on('change', function(wrap, node) {
                var attrs = wpLink.getAttrs();

                if ($.trim(attrs.href) !== '') {
                    $(wrap.target)
                        .attr('href', attrs.href)
                        .val(attrs.href)
                        .attr('new-window', $('#wp-link-target').prop('checked'));

                    self.makeSlideshow();
                } 
            });

            this.link.control = $('<button>');
            this.link.control.addClass('button');
            this.link.control.append($('<i>').addClass('dashicons').addClass('dashicons-admin-generic'));
            this.link.control.prop('disabled', true);

            this.link.control.on('click', function (e) {
                e.stopPropagation();
                wpLink.open(self.link.inputId);
            });

            node
                .append(
                    $('<label>')
                        .append(this.link.node)
                        .append($('<span>').text('Slide link'))
                )
                .append(
                    $('<div class="concealed-block">')
                        .addClass('shown-value')
                        .addClass('link-container')
                        .append(this.link.input)
                        .append(this.link.control)
                );

            return node;
        },

        getRemoveButton: function () {
            var self = this;

            if (!this.removeButton) {
                this.removeButton = $('<button>')
                    .addClass('remove-item')
                    .on('click', function (e) {
                        $(self).trigger('removeItem');
                    });
            }

            return this.removeButton;
        },


        getImageHtmlControls: function (size) {
            var node = $('<div>');

            node.addClass('slide-controls');

            node
                .append(this.getTitleControl())
                .append(this.getCaptionControl())
                .append(this.getLinkControl());

            return node;
        },

        loadSlide: function (callback) {
            var self = this;

            if (this.isLoaded || this.isLoading) { return; }
            this.isLoading = true;

            switch (this.type) {
                case 'image':
                    var i, data, image = new Image();

                    image.addEventListener('load', function (e) {
                        self.image = $(image);
                        var imageContainer = $('<div>');

                        imageContainer
                            .append(image)
                            .append(self.getImageHtmlControls())
                            .append(self.getRemoveButton());

                        if (savedSlideshowData.images && savedSlideshowData.images.length) {
                            for (i = 0; i < savedSlideshowData.images.length; i++) {
                                data = savedSlideshowData.images[i];
                                if (self.checkSlide(parseInt(data.id, 10))) {
                                    self.setTitle(data.title);
                                    self.setCaption(data.caption);
                                    self.setLink(data.link);
                                    break;
                                }
                            }
                        }

                        self.container.append(imageContainer);
                        self.isLoaded = true;
                        self.isLoading = false;
                        callback(null);
                    });

                    image.addEventListener('error', function (e) {
                        self.isLoading = false;
                        self.container = null;
                        callback({
                            type: self.type,
                            id: self.data.id,
                            error: e
                        });
                    });

                    if (this.data.sizes && this.data.sizes.thumbnail) {
                        image.src = this.data.sizes.thumbnail.url;
                    } else {
                        image.src = this.data.url;
                    }
                    
                    break;
                case 'video':
                    // TODO
                    break;
            }
        },

        getTitle: function () {
            return { use: this.title.node.prop('checked'), value: this.title.input.val() };
        },

        setTitle: function (data) {
            if (data.use === 'true') {
                this.title.node.prop('checked', true);
                this.changeCheckboxState('title', this.title.node);
            }
            this.title.input.val(data.value);
        },

        getCaption: function () {
            return { use: this.caption.node.prop('checked'), value: this.caption.input.val() };
        },

        setCaption: function (data) {
            if (data.use === 'true') {
                this.caption.node.prop('checked', true);
                this.changeCheckboxState('caption', this.caption.node);
            }

            this.caption.input.val(data.value);
        },

        getLink: function () {
            var value,
                result = { use: this.link.node.prop('checked'), url: null, newWindow: false };

            value = this.link.input.val();
            if ($.trim(value) !== '') {
                result.url = value;
            }

            result.newWindow = this.link.input.attr('new-window') === 'true';

            return result;
        },

        setLink: function (data) {
            if (data.use === 'true') {
                this.link.node.prop('checked', true);
                if (data.url) {
                    this.link.input.val(data.url);
                }

                if (data.newWindow === 'true') {
                    this.link.input.attr('new-window', true);
                }

                this.changeCheckboxState('link', this.link.node);
            }
        },

        getSavingData: function () {
            var result = null;

            switch (this.type) {
                case 'image':
                    result = {
                        type: this.type,
                        id: this.data.id,
                        title: this.getTitle(),
                        caption: this.getCaption(),
                        link: this.getLink()
                    };
                    break;
                case 'video':
                    // TODO
                    break;
            }

            return result;
        },

        destroy: function () {
            this.removeButton.off('click').remove();

            if (this.title.node) {
                this.title.node.off('change');
            }

            if (this.caption.node) {
                this.caption.node.off('change');
            }

            if (this.link.node) {
                this.link.node.off('change');
                this.link.input.off('keyup');
                this.link.input.off('change');
                this.link.control.off('click');
            }

            this.container.remove();
            this.container = null;
            this.image = null;
            this.isLoaded = false;
            this.removeButton = null;
        }
    });

    function Gallery() {
        this.slides = [];
        this.isShown = false;
        this.container = $('.gallery-container ul');

        this.addImagesButton = $('#add-images-button');
        this.removeImagesButton = $('#remove-images-button');
    }

    $.extend(Gallery.prototype, {
        lock: function () {
            this.addImagesButton.prop('disabled', true);
            this.removeImagesButton.prop('disabled', true);

            if (globalControls) {
                globalControls.lock();
            }
        },

        unlock: function () {
            this.addImagesButton.prop('disabled', false);
            this.removeImagesButton.prop('disabled', false);

            if (globalControls) {
                globalControls.unlock();
            }
        },

        setEvents: function () {
            var self = this;

            this.removeImagesButton.on('click', function () {
                self.removeAll();
            });

            this.addImagesButton.on('click', function () {
                self.openImageLibrary();
            });
        },

        openImageLibrary: function () {
            var self = this,
                wp_media;

            wp_media = wp.media({
                title: 'Image for Magic Slideshow',
                library: { type: 'image' },
                multiple: true,
                button: { text: 'Select' }
            });

            wp_media.on('select', function() {
                self.lock();
                self.addNewSlides(wp_media.state().get('selection').toJSON());
            });

            wp_media.open();
        },

        getImagesFromServer: function (callback) {
            var images = '';
            if (savedSlideshowData.images) {
                $.each(savedSlideshowData.images, function (index, img) {
                    images += img.id;
                    if (savedSlideshowData.images.length - 1 !== index) {
                        images += ',';
                    }
                });

                $.post(globalData.ajax, {
                    action: "WordPress_MagicSlideshow_get_images_by_id",
                    nonce: globalData.nonce,
                    images: images
                })
                .success(function(data) {
                    data = JSON.parse(data);

                    if (data.error) {
                        callback(true);
                    } else {
                        callback(null, data.images);
                    }
                })
                .error(function(e) {
                    callback(true);
                });
            } else {
                callback(false, []);
            }
        },

        loadSavedSlideshow: function (callback) {
            var self = this;

            this.getImagesFromServer(function(err, data) {
                if (err || !data.length) {
                    self.setEvents();
                    callback();
                    self.isShown = true;
                } else {
                    self.addNewSlides(data, function () {
                        self.setEvents();
                        callback();
                    });
                    self.isShown = true;
                }
            });
        },

        getHtmlSlides: function () {
            var slides = [];

            if (this.checkLoadingOfSlides()) {
                $.each(this.slides, function (index, slide) {
                    slides.push(slide.getSlideshowHtmlData());
                });
            }

            return slides;
        },

        checkLoadingOfSlides: function () {
            var i, result = true;
            for (i = 0; i < this.slides.length; i++)  {
                if (!this.slides[i].isLoaded) {
                    result = false;
                    break;
                }
            }

            return result;
        },

        findSlideById: function (id) {
            var i, result = null;

            for (i = 0; i < this.slides.length; i++) {
                if (this.slides[i].checkSlide(id)) {
                    result = i;
                    break;
                }
            }

            return result;
        },

        addNewSlide: function (dataOfSlide, callback) {
            var self = this,
                slide = new Slide(dataOfSlide);

            $(slide).on('removeItem', function(e)  {
                self.removeSlide(self.findSlideById(e.target.data.id));
                slideshowPreview.makeSlideshow();
            });

            this.slides.push(slide);
            self.container.append(slide.container);

            slide.loadSlide(function (err, html) {
                if (err) {
                    self.removeSlide(self.findSlideById(err.id));
                }

                if (self.checkLoadingOfSlides()) {
                    self.unlock();
                    if (callback) {
                        callback();
                    } else {
                        slideshowPreview.makeSlideshow();
                    }
                }
            });
        },

        removeSlide: function (index) {
            if (index !== null) {
                this.slides[index].destroy();
                this.slides.splice(index, 1);
            }
        },

        addNewSlides: function (arr, callback) {
            var self = this;
            $.each(arr, function (index, dataOfSlide) {
                if (self.findSlideById(dataOfSlide.id) === null) {
                    self.addNewSlide(dataOfSlide, callback);
                }
            });
        },

        getSavingData: function () {
            var self = this, i, result = [];

            $.each(this.container.find('li'), function (index, node) {
                var id = parseInt($(node).attr('data-item-id'), 10),
                    slide = self.slides[self.findSlideById(id)],
                    data = slide.getSavingData();

                if (data) {
                    result.push(data);
                }
            });

            return result;
        },

        getFirstImageData: function () {
            var result = null, index = 0,
                nodes = this.container.find('li');

            do {
                result = $(nodes[index]);

                try {
                    result = this.slides[this.findSlideById(parseInt(result.attr('data-item-id'), 10))];

                    if (result.type === 'image') {
                        result = result.getSavingData();
                        result = result.id;
                    } else {
                        result = null;
                    }
                } catch (e) {
                    result = null;
                }
                index += 1;
            } while (!result && index < nodes.length);
            
            return result;
        },

        removeAll: function () {
            while (this.slides.length) {
                this.removeSlide(0);
            }
        }
    });

    function GlobalControls () {
        this.saveButtons = $('.save-button');
        this.saveAndCloseButtons = $('.save-and-close-button');
        this.closeButtons = $('.close-button');

        this.setEvents();
    }

    $.extend(GlobalControls.prototype, {
        lock: function () {
            this.saveButtons.prop('disabled', true);
            this.saveAndCloseButtons.prop('disabled', true);
            this.closeButtons.prop('disabled', true);
        },

        unlock: function () {
            this.saveButtons.prop('disabled', false);
            this.saveAndCloseButtons.prop('disabled', false);
            this.closeButtons.prop('disabled', false);
        },

        setEvents: function () {
            var self = this;

            this.saveButtons.on('click', function () {
                self.save(function (err) {
                    if (err) {
                        switch(err) {
                            case 'wordserror':
                                $("html, body").animate({ scrollTop: 0 }, "slow");
                                saveLoader.hide();
                                break;
                            case 'nodata':
                                saveLoader.showNothigToSaveError();
                                break;
                            case 'notunique':
                                $("html, body").animate({ scrollTop: 0 }, "slow");
                                saveLoader.showIsNotUniqueError();
                                break;
                            default:
                            saveLoader.showTryAgainError();
                        }
                    } else {
                        saveLoader.showSuccess();
                    }
                });
            });

            this.saveAndCloseButtons.on('click', function () {
                self.save(function (err) {
                    if (err) {
                        switch(err) {
                            case 'wordserror':
                                $("html, body").animate({ scrollTop: 0 }, "slow");
                                saveLoader.hide();
                                break;
                            case 'nodata':
                                saveLoader.showNothigToSaveError();
                                break;
                            case 'notunique':
                                $("html, body").animate({ scrollTop: 0 }, "slow");
                                saveLoader.showIsNotUniqueError();
                                break;
                            default:
                            saveLoader.showTryAgainError();
                        }
                    } else {
                        saveLoader.hide();
                        self.close();
                    }
                });
            });

            this.closeButtons.on('click', function () {
                self.close();
            });
        },

        getData: function () {
            var result = null,
                additionalOpt = null,
                images = gallery.getSavingData(),
                opt = options.getSlideshowOptions(),
                mobileOpt = options.getSlideshowOptions(true),
                shortcode = additionalParam.getDataForServer(),
                firstImage;

            firstImage = gallery.getFirstImageData();

            if (firstImage) {
                additionalOpt = 'firstImage:' + firstImage + ';';
            }

            if (images.length) {
                result = {
                    shortcode: shortcode,
                    images: images,
                    opt: opt,
                    mobileOpt: mobileOpt,
                    additionalOpt: additionalOpt
                }
            }

            return result;
        },

        save: function (callback) {
            var self = this, timer = null, data;

            if (additionalParam.wordsErrorIsShown) {
                $("html, body").animate({ scrollTop: 0 }, "slow");
                return callback('wordserror');
            }

            data = this.getData();

            if (!data) {
                saveLoader.showNothigToSaveError();
                return callback('nodata');
            }

            this.lock();

            timer = setTimeout(function () {
                saveLoader.show();
            }, 300);

            $.post(globalData.ajax, {
                action: "WordPress_MagicSlideshow_save",
                nonce: globalData.nonce,
                id: savedSlideshowData.id,
                shortcode: data.shortcode,
                images: data.images,
                options: data.opt,
                mobileOptions: data.mobileOpt,
                additionalOptions: data.additionalOpt
            })
            .success(function(_data) {
                clearTimeout(timer);
                var _data = JSON.parse(_data);

                self.unlock();

                if (_data.error === 'notunique') {
                    callback(_data.error);
                } else {
                    savedSlideshowData.id = _data.id;
                    $('#exist-tool')
                        .css('display', 'block')
                        .find('span').html(_data.id);
                    $('#new-tool').css('display', 'none');
                    callback(null);
                }
            })
            .error(function(e) {
                self.unlock();
                callback(e);
            });
        },

        close: function () {
            window.location.href = window.location.origin + window.location.pathname + window.location.search.split('&')[0];
        }
    });

    function AdditionalParam () {
        this.node = $('#tool-shortcode-param');

        this.wordsErrorIsShown = false;
        this.wordsError = $('#shortcode-error');

        if (savedSlideshowData.name) {
            this.node.val(savedSlideshowData.name);
        }

        this.setEvents();
    }

    $.extend(AdditionalParam.prototype, {
        check: function (value) {
            var result = false;

            if (!value) {
                value = this.getValue();
            }

            if (value === '' || /^[A-Za-z][A-Za-z0-9_-]*$/.test(value)) {
                result = true;
            }

            return result;
        },

        setEvents: function () {
            var self = this, timer = null;

            this.node.on('change', function () {

            });

            this.node.on('keyup', function () {
                clearTimeout(timer);
                timer = setTimeout(function () {
                    var value = $.trim(self.node.val());

                    if (self.check(value)) {
                        if (self.wordsErrorIsShown) {
                            self.wordsErrorIsShown = false;
                            self.wordsError.removeClass('shown');
                        }
                    } else {
                        if (!self.wordsErrorIsShown) {
                            self.wordsErrorIsShown = true;
                            self.wordsError.addClass('shown');
                        }
                    }
                }, 100);
            });
        },

        getValue: function () {
            return this.node.val();
        },

        getDataForServer: function () {
            var result = null, value = this.getValue();

            if ($.trim(value) !== '') {
                result = value;
            }

            return result;
        }
    });

    function SaveLoader () {
        this.node = $('#save-loader');
        this.loaderIsShown = false;
        this.animation = $('#loading-animation');
        this.timer = null;

        this.messages = {
            saving: $('#slideshow-is-saving'),
            saved: $('#slideshow-was-saved'),
            shortcodeIsNotUnique: $('#is-not-unique'),
            isNotSaved: $('#is-not-saved'),
            tryAgain: $('#try-again'),
            nothigToSave: $('#nothing-to-save')
        }
    }

    $.extend(SaveLoader.prototype, {
        setSize: function () {
            this.node.css('width', $('.shortcode-container').width() + 'px');
        },

        normalize: function () {
            this.animation.removeClass('hidden');
            this.messages.saving.removeClass('hidden');

            this.messages.saved.addClass('hidden');
            this.messages.shortcodeIsNotUnique.addClass('hidden');
            this.messages.isNotSaved.addClass('hidden');
            this.messages.tryAgain.addClass('hidden');
            this.messages.nothigToSave.addClass('hidden');
        },

        hideBlocks: function () {
            this.animation.addClass('hidden');
            this.messages.saving.addClass('hidden');
        },


        show: function (type) {
            this.loaderIsShown = true;

            clearTimeout(this.timer);
            this.normalize();

            if (type) {
                this.hideBlocks();
            }

            switch(type) {
                case 'shortcodeIsNotUnique':
                    this.messages.isNotSaved.removeClass('hidden');
                    this.messages.shortcodeIsNotUnique.removeClass('hidden');
                    break;
                case 'nothigToSave':
                    this.messages.nothigToSave.removeClass('hidden');
                    break;
                case 'tryAgain':
                    this.messages.isNotSaved.removeClass('hidden');
                    this.messages.tryAgain.removeClass('hidden');
                    break;
                case 'success':
                    this.messages.saved.removeClass('hidden');
                    break;
            }

            this.node.addClass('shown');
        },

        hide: function (delay) {
            var self = this;
            if (this.loaderIsShown) {
                clearTimeout(this.timer);

                if (delay) {
                    this.timer = setTimeout(function () {
                        self.timer = null;
                        self.loaderIsShown = false;
                        self.node.removeClass('shown');
                        self.normalize();
                    }, delay);
                } else {
                    this.loaderIsShown = false;
                    this.node.removeClass('shown');
                    this.normalize();
                }
            }
        },

        showIsNotUniqueError: function () {
            this.show('shortcodeIsNotUnique');
            this.hide(5000);
        },

        showTryAgainError: function () {
            this.show('tryAgain');
            this.hide(5000);
        },

        showNothigToSaveError: function () {
            this.show('nothigToSave');
            this.hide(5000);
        },

        showSuccess: function () {
            this.show('success');
            this.hide(5000);
        }
    });

    $(document).ready(function () {
        var timer;

        savedSlideshowData = window.savedData;

        loadLoader = $('#load-loader');

        saveLoader = new SaveLoader();

        timer = setTimeout(function () {
            loadLoaderIsShown = true;
            loadLoader.addClass('shown');
        }, 300);

        gallery = new Gallery();
        gallery.loadSavedSlideshow(function () {
            slideshowPreview = new SlideshowPreview();

            $(function() {
                $("#sortable").sortable({});
                $("#sortable").disableSelection();
                $("#tabs").tabs({
                    beforeActivate: function(event, ui) {
                        $('.tabs-border').find('div').removeClass('animate');
                        ui.newPanel.find('.tabs-border').find('div').addClass('animate');
                    }
                });
            });

            additionalParam = new AdditionalParam();

            options = new Options();
            options.parse();

            globalControls = new GlobalControls();

            clearTimeout(timer);
            if (loadLoaderIsShown) {
                loadLoaderIsShown = false;
                loadLoader.removeClass('shown');
            }

            $('.shortcode-body').css('display', 'block');
            saveLoader.setSize();
            slideshowPreview.makeSlideshow();

            overlay = $('#overlay');
            overlay.find('button').on('click', function (e) {
                e.preventDefault();
                overlay.removeClass('shown');
                slideshowPreview.makeSlideshow();
            });

            $('#wp-link-text').parent().css({display: 'none'});
        });
    });
})(jQuery);
