define([
    'jquery',
    'underscore',
    'moment',
    '../../UI/ai/ai_overview/application-template.tmpl',
    '../../UI/ai/ai_overview/application-popover-template.tmpl',
    '../../UI/ai/ai_overview/citation-template.tmpl',
    '../../UI/ai/ai_overview/citation-popover-template.tmpl'
], function ($, _, moment, applicationTemplate, applicationPopoverTemplate, citationTemplate, citationPopoverTemplate) {

    var AiSearchOverview = function () {
        var self = this;

        this.SHOW_MORE_TOKEN = '[SHOW_MORE]';

        this.$ai_search = null;
        this.$loader = null;
        this.$content = null;
        this.$inner = null;
        this.$show_more_container = null;
        this.$applications = null;
        this.search_hash = '';

        this.initialize = function (config) {
            self.$ai_search = $('#ai-search');
            self.$loader = self.$ai_search.find('.js-ai-skeleton');
            self.$content = self.$ai_search.find('.js-ai-content');
            self.$inner = self.$ai_search.find('.js-ai-content-inner');
            self.$show_more_container = self.$ai_search.find('.js-ai-show-more-container');
            self.$applications = self.$ai_search.find('.js-ai-search-applications');

            self.app_codes = config.app_codes;
            self.search_hash = config.search_hash;

            self.events();
            self.submit();
        };

        this.events = function () {
            self.$show_more_container.on('click', '.js-ai-show-more', function () {
                var $hidden = self.$inner.find('.js-ai-show-more-content');

                $hidden.removeClass('hide');

                // Need to immediately update the DOM so it can process our content grow animation below
                $hidden[0].offsetHeight;

                $hidden.addClass('ai-expanded');

                self.$show_more_container.fadeOut(150, function () {
                    $(this).remove();
                });
            });
        };

        this.showLoading = function (loading) {
            if (loading) {
                self.$content.addClass('hide');
                self.$loader.show();
            } else {
                self.$content.removeClass('hide');
                self.$loader.hide();
            }
        };

        this.drawApplications = function(citations) {
            self.$applications.empty();

            // Group citations by type
            var groups = {};
            citations.forEach(function(citation) {
                if (!groups[citation.type]) groups[citation.type] = [];

                citation.app_icon_used = false;
                if (citation.image === '') {
                    citation.image = self.app_codes[citation.type].url;
                    citation.app_icon_used = true;
                }

                if (citation.date_created) {
                    citation.date_created = moment(citation.date_created).format(cla_locale.date_format_long);
                }

                groups[citation.type].push(citation);
            });

            // Append badges and initialize popovers
            for (var type in groups) {
                (function(currentType, citationsForType) {
                    var $badge = $(applicationTemplate({
                        application: self.app_codes[currentType],
                        citations: citationsForType
                    }));

                    $badge.popover({
                        html: true,
                        trigger: 'manual',
                        container: $badge,
                        placement: 'bottom',
                        template: '<div class="popover" role="tooltip"><div class="arrow"></div><div class="popover-body p-0"></div></div>',
                        content: function() {
                            return applicationPopoverTemplate({ citations: citationsForType });
                        }
                    });

                    $badge.on('mouseenter focus', function () {
                        var $this = $(this);
                        $this.popover('show');

                        var popoverId = $this.attr('aria-describedby');
                        var $popover = $('#' + popoverId);

                        $popover.on('mouseenter focusin', function () {
                            clearTimeout($this.data('timeout'));
                        }).on('mouseleave focusout', function (e) {
                            var popoverContext = this;
                            $this.data('timeout', setTimeout(function () {
                                if (!$(popoverContext).find(':focus').length) {
                                    $this.popover('hide');
                                }
                            }, 150));
                        });

                    }).on('mouseleave blur', function () {
                        var $this = $(this);

                        $this.data('timeout', setTimeout(function () {
                            var popoverId = $this.attr('aria-describedby');
                            if (!$('#' + popoverId).find(':focus').length) {
                                $this.popover('hide');
                            }
                        }, 150));
                    });

                    self.$applications.append($badge);
                })(type, groups[type]);
            }
        };


        this.drawOverview = function (overview, citations) {
            var mappedCitations = {};
            citations.forEach(function (c) { mappedCitations[c.id] = c; });

            // Replace all citation IDs with rendered template
            overview = overview.replace(/\[ID:(\d+)\]/g, function(match, id) {
                var citation = mappedCitations[id];
                if (!citation) {
                    return '';
                }

                return citationTemplate({ citation: citation });
            });

            // Handle SHOW_MORE token
            var hasShowMore = overview.indexOf(self.SHOW_MORE_TOKEN) !== -1;
            var beforeShowMore = overview;
            var afterShowMore = '';
            if (hasShowMore) {
                var parts = overview.split(self.SHOW_MORE_TOKEN);
                beforeShowMore = parts[0];
                afterShowMore = parts[1] || '';
                self.$show_more_container.show();
            } else {
                self.$show_more_container.remove();
            }

            var finalHtml = beforeShowMore;
            if (hasShowMore) {
                finalHtml += '<div class="ai-show-more-content js-ai-show-more-content hide">' + afterShowMore + '</div>';
            }

            self.$inner.html(finalHtml);

            $('.ai-citation-popover').popover({
                html: true,
                container: 'body',
                trigger: 'hover focus',
                placement: 'top',
                delay: {
                    show: 100,
                    hide: 300
                },
                template: '<div class="popover ai-citation-popover" role="tooltip"><div class="arrow"></div><div class="popover-body pb-2"></div></div>',
                content: function() {
                    return citationPopoverTemplate({
                        image_url: $(this).data('img-url'),
                        title: $(this).data('title'),
                        date_created: $(this).data('date-created')
                    });
                }
            });
        };

        this.submit = function () {
            self.showLoading(true);

            $.post('/api/ai/generate-text', {
                module: 'search',
                metadata: {
                    search_hash: self.search_hash
                }
            })
                .done(function (response) {
                    var data = response.content;

                    if (!data.overview) {
                        self.$ai_search.remove();
                        return;
                    }

                    self.drawApplications(data.citations);
                    self.drawOverview(data.overview, data.citations);
                })
                .fail(function (xhr, status, error) {
                    self.$ai_search.remove();
                })
                .always(function () {
                    self.showLoading(false);
                });
        };
    };

    return new AiSearchOverview();
});
