odoo.define('website_links.website_links', function (require) {
'use strict';

var core = require('web.core');
var publicWidget = require('web.public.widget');

var _t = core._t;

var SelectBox = publicWidget.Widget.extend({
    xmlDependencies: ['/website_links/static/src/xml/recent_link.xml'],
    events: {
        'change': '_onChange',
    },

    /**
     * @constructor
     * @param {Object} parent
     * @param {Object} obj
     * @param {String} placeholder
     */
    init: function (parent, obj, placeholder) {
        this._super.apply(this, arguments);
        this.obj = obj;
        this.placeholder = placeholder;
    },
    /**
     * @override
     */
    willStart: function () {
        var self = this;
        var defs = [this._super.apply(this, arguments)];
        defs.push(this._rpc({
            model: this.obj,
            method: 'search_read',
        }).then(function (result) {
            self.objects = _.map(result, function (val) {
                return {id: val.id, text: val.name};
            });
        }));
        return $.when.apply($, defs);
    },
    /**
     * @override
     */
    start: function () {
        var self = this;
        this.$el.select2({
            placeholder: self.placeholder,
            allowClear: true,
            createSearchChoice: function (term) {
                if (self._objectExists(term)) {
                    return null;
                }
                return {id: term, text: _.str.sprintf("Create '%s'", term)};
            },
            createSearchChoicePosition: 'bottom',
            multiple: false,
            data: self.objects,
        });
    },

    //--------------------------------------------------------------------------
    // Private
    //--------------------------------------------------------------------------

    /**
     * @private
     * @param {String} query
     */
    _objectExists: function (query) {
        return _.find(this.objects, function (val) {
            return val.text.toLowerCase() === query.toLowerCase();
        }) !== undefined;
    },
    /**
     * @private
     * @param {String} name
     */
    _createObject: function (name) {
        var self = this;
        return this._rpc({
            model: this.obj,
            method: 'create',
            args: [{name: name}],
        }).then(function (record) {
            self.$el.attr('value', record);
            self.objects.push({'id': record, 'text': name});
        });
    },

    //--------------------------------------------------------------------------
    // Handlers
    //--------------------------------------------------------------------------

    /**
     * @private
     * @param {Object} ev
     */
    _onChange: function (ev) {
        if (!ev.added || !_.isString(ev.added.id)) {
            return;
        }
        this._createObject(ev.added.id);
    },
});

var RecentLinkBox = publicWidget.Widget.extend({
    template: 'website_links.RecentLink',
    events: {
        'click .btn_shorten_url_clipboard': '_toggleCopyButton',
        'click .o_website_links_edit_code': '_editCode',
        'click .o_website_links_ok_edit': '_onLinksOkClick',
        'click .o_website_links_cancel_edit': '_onLinksCancelClick',
        'submit #o_website_links_edit_code_form': '_onSubmitCode',
    },

    /**
     * @constructor
     * @param {Object} parent
     * @param {Object} obj
     */
    init: function (parent, obj) {
        this._super.apply(this, arguments);
        this.link_obj = obj;
        this.animating_copy = false;
    },
    /**
     * @override
     */
    start: function () {
        new ClipboardJS(this.$('.btn_shorten_url_clipboard').get(0));
        return this._super.apply(this, arguments);
    },

    //--------------------------------------------------------------------------
    // Private
    //--------------------------------------------------------------------------

    /**
     * @private
     */
    _toggleCopyButton: function () {
        if (this.animating_copy) {
            return;
        }

        var self = this;
        this.animating_copy = true;
        var top = this.$('.o_website_links_short_url').position().top;
        this.$('.o_website_links_short_url').clone()
            .css('position', 'absolute')
            .css('left', 15)
            .css('top', top - 2)
            .css('z-index', 2)
            .removeClass('o_website_links_short_url')
            .addClass('animated-link')
            .insertAfter(this.$('.o_website_links_short_url'))
            .animate({
                opacity: 0,
                top: '-=20',
            }, 500, function () {
                self.$('.animated-link').remove();
                self.animating_copy = false;
            });
    },
    /**
     * @private
     * @param {String} message
     */
    _notification: function (message) {
        this.$('.notification').append('<strong>' + message + '</strong>');
    },
    /**
     * @private
     */
    _editCode: function () {
        var initCode = this.$('#o_website_links_code').html();
        this.$('#o_website_links_code').html('<form style="display:inline;" id="o_website_links_edit_code_form"><input type="hidden" id="init_code" value="' + initCode + '"/><input type="text" id="new_code" value="' + initCode + '"/></form>');
        this.$('.o_website_links_edit_code').hide();
        this.$('.copy-to-clipboard').hide();
        this.$('.o_website_links_edit_tools').show();
    },
    /**
     * @private
     */
    _cancelEdit: function () {
        this.$('.o_website_links_edit_code').show();
        this.$('.copy-to-clipboard').show();
        this.$('.o_website_links_edit_tools').hide();
        this.$('.o_website_links_code_error').hide();

        var oldCode = this.$('#o_website_links_edit_code_form #init_code').val();
        this.$('#o_website_links_code').html(oldCode);

        this.$('#code-error').remove();
        this.$('#o_website_links_code form').remove();
    },
    /**
     * @private
     */
    _submitCode: function () {
        var self = this;

        var initCode = this.$('#o_website_links_edit_code_form #init_code').val();
        var newCode = this.$('#o_website_links_edit_code_form #new_code').val();

        if (newCode === '') {
            self.$('.o_website_links_code_error').html(_t("The code cannot be left empty"));
            self.$('.o_website_links_code_error').show();
            return;
        }

        function showNewCode(newCode) {
            self.$('.o_website_links_code_error').html('');
            self.$('.o_website_links_code_error').hide();

            self.$('#o_website_links_code form').remove();

            // Show new code
            var host = self.$('#o_website_links_host').html();
            self.$('#o_website_links_code').html(newCode);

            // Update button copy to clipboard
            self.$('.btn_shorten_url_clipboard').attr('data-clipboard-text', host + newCode);

            // Show action again
            self.$('.o_website_links_edit_code').show();
            self.$('.copy-to-clipboard').show();
            self.$('.o_website_links_edit_tools').hide();
        }

        if (initCode === newCode) {
            showNewCode(newCode);
        } else {
            this._rpc({
                route: '/website_links/add_code',
                params: {
                    init_code: initCode,
                    new_code: newCode,
                },
            }).then(function (result) {
                showNewCode(result[0].code);
            }, function () {
                self.$('.o_website_links_code_error').show();
                self.$('.o_website_links_code_error').html(_t("This code is already taken"));
            });
        }
    },

    //--------------------------------------------------------------------------
    // Handlers
    //--------------------------------------------------------------------------

    /**
     * @private
     * @param {Event} ev
     */
    _onLinksOkClick: function (ev) {
        ev.preventDefault();
        this._submitCode();
    },
    /**
     * @private
     * @param {Event} ev
     */
    _onLinksCancelClick: function (ev) {
        ev.preventDefault();
        this._cancelEdit();
    },
    /**
     * @private
     * @param {Event} ev
     */
    _onSubmitCode: function (ev) {
        ev.preventDefault();
        this._submitCode();
    },
});

var RecentLinks = publicWidget.Widget.extend({

    //--------------------------------------------------------------------------
    // Private
    //--------------------------------------------------------------------------

    /**
     * @private
     */
    getRecentLinks: function (filter) {
        var self = this;
        return this._rpc({
            route: '/website_links/recent_links',
            params: {
                filter: filter,
                limit: 20,
            },
        }).then(function (result) {
            _.each(result.reverse(), function (link) {
                self._addLink(link);
            });
            self._updateNotification();
        }, function () {
            var message = _t("Unable to get recent links");
            self.$el.append('<div class="alert alert-danger">' + message + '</div>');
        });
    },
    /**
     * @private
     */
    _addLink: function (link) {
        var nbLinks = this.getChildren().length;
        var recentLinkBox = new RecentLinkBox(this, link);
        recentLinkBox.prependTo(this.$el);
        $('.link-tooltip').tooltip();

        if (nbLinks === 0) {
            this._updateNotification();
        }
    },
    /**
     * @private
     */
    removeLinks: function () {
        _.invoke(this.getChildren(), 'destroy');
    },
    /**
     * @private
     */
    _updateNotification: function () {
        if (this.getChildren().length === 0) {
            var message = _t("You don't have any recent links.");
            $('.o_website_links_recent_links_notification').html('<div class="alert alert-info">' + message + '</div>');
        } else {
            $('.o_website_links_recent_links_notification').empty();
        }
    },
});

publicWidget.registry.websiteLinks = publicWidget.Widget.extend({
    selector: '.o_website_links_create_tracked_url',
    events: {
        'click #filter-newest-links': '_onFilterNewestLinksClick',
        'click #filter-most-clicked-links': '_onFilterMostClickedLinksClick',
        'click #filter-recently-used-links': '_onFilterRecentlyUsedLinksClick',
        'click #generated_tracked_link a': '_onGeneratedTrackedLinkClick',
        'keyup #url': '_onUrlKeyUp',
        'click #btn_shorten_url': '_onShortenUrlButtonClick',
        'submit #o_website_links_link_tracker_form': '_onFormSubmit',
    },

    /**
     * @override
     */
    start: function () {
        var defs = [this._super.apply(this, arguments)];

        // UTMS selects widgets
        var campaignSelect = new SelectBox(this, 'utm.campaign', _t("e.g. Promotion of June, Winter Newsletter, .."));
        defs.push(campaignSelect.attachTo($('#campaign-select')));

        var mediumSelect = new SelectBox(this, 'utm.medium', _t("e.g. Newsletter, Social Network, .."));
        defs.push(mediumSelect.attachTo($('#channel-select')));

        var sourceSelect = new SelectBox(this, 'utm.source', _t("e.g. Search Engine, Website page, .."));
        defs.push(sourceSelect.attachTo($('#source-select')));

        // Recent Links Widgets
        this.recentLinks = new RecentLinks();
        defs.push(this.recentLinks.appendTo($('#o_website_links_recent_links')));
        this.recentLinks.getRecentLinks('newest');

        // Clipboard Library
        new ClipboardJS($('#btn_shorten_url').get(0));

        this.url_copy_animating = false;

        $('[data-toggle="tooltip"]').tooltip();

        return $.when.apply($, defs);
    },

    //--------------------------------------------------------------------------
    // Handlers
    //--------------------------------------------------------------------------

    /**
     * @private
     */
    _onFilterNewestLinksClick: function () {
        this.recentLinks.removeLinks();
        this.recentLinks.getRecentLinks('newest');
    },
    /**
     * @private
     */
    _onFilterMostClickedLinksClick: function () {
        this.recentLinks.removeLinks();
        this.recentLinks.getRecentLinks('most-clicked');
    },
    /**
     * @private
     */
    _onFilterRecentlyUsedLinksClick: function () {
        this.recentLinks.removeLinks();
        this.recentLinks.getRecentLinks('recently-used');
    },
    /**
     * @private
     */
    _onGeneratedTrackedLinkClick: function () {
        $('#generated_tracked_link a').text(_t("Copied")).removeClass('btn-primary').addClass('btn-success');
        setTimeout(function () {
            $('#generated_tracked_link a').text(_t("Copy")).removeClass('btn-success').addClass('btn-primary');
        }, 5000);
    },
    /**
     * @private
     * @param {Event} ev
     */
    _onUrlKeyUp: function (ev) {
        if (!$('#btn_shorten_url').hasClass('btn-copy') || ev.which === 13) {
            return;
        }

        $('#btn_shorten_url').removeClass('btn-success btn-copy').addClass('btn-primary').html('Get tracked link');
        $('#generated_tracked_link').css('display', 'none');
        $('.o_website_links_utm_forms').show();
    },
    /**
     * @private
     */
    _onShortenUrlButtonClick: function () {
        if (!$('#btn_shorten_url').hasClass('btn-copy') || this.url_copy_animating) {
            return;
        }

        var self = this;
        this.url_copy_animating = true;
        $('#generated_tracked_link').clone()
            .css('position', 'absolute')
            .css('left', '78px')
            .css('bottom', '8px')
            .css('z-index', 2)
            .removeClass('#generated_tracked_link')
            .addClass('url-animated-link')
            .appendTo($('#generated_tracked_link'))
            .animate({
                opacity: 0,
                bottom: '+=20',
            }, 500, function () {
                $('.url-animated-link').remove();
                self.url_copy_animating = false;
            });
    },
    /**
     * Add the RecentLinkBox widget and send the form when the user generate the link
     *
     * @private
     * @param {Event} ev
     */
    _onFormSubmit: function (ev) {
        ev.preventDefault();

        if ($('#btn_shorten_url').hasClass('btn-copy')) {
            return;
        }

        ev.stopPropagation();

        // Get URL and UTMs
        var campaignID = $('#campaign-select').attr('value');
        var mediumID = $('#channel-select').attr('value');
        var sourceID = $('#source-select').attr('value');

        var params = {};
        params.url = $('#url').val();
        if (campaignID !== '') {
            params.campaign_id = parseInt(campaignID);
        }
        if (mediumID !== '') {
            params.medium_id = parseInt(mediumID);
        }
        if (sourceID !== '') {
            params.source_id = parseInt(sourceID);
        }

        $('#btn_shorten_url').text(_t("Generating link..."));

        this._rpc({
            route: '/website_links/new',
            params: params,
        }).then(function (result) {
            if ('error' in result) {
                // Handle errors
                if (result.error === 'empty_url') {
                    $('.notification').html('<div class="alert alert-danger">The URL is empty.</div>');
                } else if (result.error === 'url_not_found') {
                    $('.notification').html('<div class="alert alert-danger">URL not found (404)</div>');
                } else {
                    $('.notification').html('<div class="alert alert-danger">An error occur while trying to generate your link. Try again later.</div>');
                }
            } else {
                // Link generated, clean the form and show the link
                var link = result[0];

                $('#btn_shorten_url').removeClass('btn-primary').addClass('btn-success btn-copy').html('Copy');
                $('#btn_shorten_url').attr('data-clipboard-text', link.short_url);

                $('.notification').html('');
                $('#generated_tracked_link').html(link.short_url);
                $('#generated_tracked_link').css('display', 'inline');

                this.recentLinks._addLink(link);

                // Clean URL and UTM selects
                $('#campaign-select').select2('val', '');
                $('#channel-select').select2('val', '');
                $('#source-select').select2('val', '');

                $('.o_website_links_utm_forms').hide();
            }
        });
    },
});

return {
    SelectBox: SelectBox,
    RecentLinkBox: RecentLinkBox,
    RecentLinks: RecentLinks,
};
});
