const render_more_topics = require('../templates/more_topics.hbs');
const render_more_topics_spinner = require('../templates/more_topics_spinner.hbs');
const render_topic_list_item = require('../templates/topic_list_item.hbs');
const topic_list_data = require('./topic_list_data');

/*
    Track all active widgets with a Map.

    (We have at max one for now, but we may
    eventually allow multiple streams to be
    expanded.)
*/

const active_widgets = new Map();

// We know whether we're zoomed or not.
let zoomed = false;

exports.update = function () {
    for (const widget of active_widgets.values()) {
        widget.build();
    }
};

exports.clear = function () {
    stream_popover.hide_topic_popover();

    for (const widget of active_widgets.values()) {
        widget.remove();
    }

    active_widgets.clear();
};

exports.close = function () {
    zoomed = false;
    exports.clear();
};

exports.zoom_out = function () {
    zoomed = false;

    const stream_ids = Array.from(active_widgets.keys());

    if (stream_ids.length !== 1) {
        blueslip.error('Unexpected number of topic lists to zoom out.');
        return;
    }

    const stream_id = stream_ids[0];
    const widget = active_widgets.get(stream_id);
    const parent_widget = widget.get_parent();

    exports.rebuild(parent_widget, stream_id);
};

exports.keyed_topic_li = (convo) => {
    const render = () => {
        return render_topic_list_item(convo);
    };

    const eq = (other) => {
        return _.isEqual(convo, other.convo);
    };

    const key = 't:' + convo.topic_name;

    return {
        key: key,
        render: render,
        convo: convo,
        eq: eq,
    };
};

exports.more_li = (more_topics_unreads) => {
    const render = () => {
        return render_more_topics({
            more_topics_unreads: more_topics_unreads,
        });
    };

    const eq = (other) => {
        return other.more_items &&
            more_topics_unreads === other.more_topics_unreads;
    };

    const key = 'more';

    return {
        key: key,
        more_items: true,
        more_topics_unreads: more_topics_unreads,
        render: render,
        eq: eq,
    };
};

exports.spinner_li = () => {
    const render = () => {
        return render_more_topics_spinner();
    };

    const eq = (other) => {
        return other.spinner;
    };

    const key = 'more';

    return {
        key: key,
        spinner: true,
        render: render,
        eq: eq,
    };
};

exports.widget = function (parent_elem, my_stream_id) {
    const self = {};

    self.prior_dom = undefined;

    self.build_list = function (spinner) {
        const list_info = topic_list_data.get_list_info(
            my_stream_id, zoomed);

        const num_possible_topics = list_info.num_possible_topics;
        const more_topics_unreads = list_info.more_topics_unreads;

        const is_showing_all_possible_topics =
            list_info.items.length === num_possible_topics &&
            stream_topic_history.is_complete_for_stream_id(my_stream_id);

        const attrs = [
            ['class', 'topic-list'],
        ];

        const nodes = list_info.items.map(exports.keyed_topic_li);

        if (spinner) {
            nodes.push(exports.spinner_li());
        } else if (!is_showing_all_possible_topics) {
            nodes.push(exports.more_li(more_topics_unreads));
        }

        const dom = vdom.ul({
            attrs: attrs,
            keyed_nodes: nodes,
        });

        return dom;
    };

    self.get_parent = function () {
        return parent_elem;
    };

    self.get_stream_id = function () {
        return my_stream_id;
    };

    self.remove = function () {
        parent_elem.find('.topic-list').remove();
        self.prior_dom = undefined;
    };

    self.build = function (spinner) {
        const new_dom = self.build_list(spinner);

        function replace_content(html) {
            self.remove();
            parent_elem.append(html);
        }

        function find() {
            return parent_elem.find('.topic-list');
        }

        vdom.update(replace_content, find, new_dom, self.prior_dom);

        self.prior_dom = new_dom;
    };

    return self;
};

exports.active_stream_id = function () {
    const stream_ids = Array.from(active_widgets.keys());

    if (stream_ids.length !== 1) {
        return;
    }

    return stream_ids[0];
};

exports.get_stream_li = function () {
    const widgets = Array.from(active_widgets.values());

    if (widgets.length !== 1) {
        return;
    }

    const stream_li = widgets[0].get_parent();
    return stream_li;
};

exports.rebuild = function (stream_li, stream_id) {
    const active_widget = active_widgets.get(stream_id);

    if (active_widget) {
        active_widget.build();
        return;
    }

    exports.clear();
    const widget = exports.widget(stream_li, stream_id);
    widget.build();

    active_widgets.set(stream_id, widget);
};

// For zooming, we only do topic-list stuff here...let stream_list
// handle hiding/showing the non-narrowed streams
exports.zoom_in = function () {
    zoomed = true;

    const stream_id = exports.active_stream_id();
    if (!stream_id) {
        blueslip.error('Cannot find widget for topic history zooming.');
        return;
    }

    const active_widget = active_widgets.get(stream_id);

    function on_success() {
        if (!active_widgets.has(stream_id)) {
            blueslip.warn('User re-narrowed before topic history was returned.');
            return;
        }

        if (!zoomed) {
            blueslip.warn('User zoomed out before topic history was returned.');
            // Note that we could attempt to re-draw the zoomed out topic list
            // here, given that we have more history, but that might be more
            // confusing than helpful to a user who is likely trying to browse
            // other streams.
            return;
        }

        active_widget.build();
    }

    ui.get_scroll_element($('#stream-filters-container')).scrollTop(0);

    const spinner = true;
    active_widget.build(spinner);

    stream_topic_history.get_server_history(stream_id, on_success);
};

exports.initialize = function () {
    $('#stream_filters').on('click', '.topic-box', function (e) {
        if (e.metaKey || e.ctrlKey) {
            return;
        }
        if ($(e.target).closest('.show-more-topics').length > 0) {
            return;
        }

        // In a more componentized world, we would delegate some
        // of this stuff back up to our parents.

        const stream_row = $(e.target).parents('.narrow-filter');
        const stream_id = parseInt(stream_row.attr('data-stream-id'), 10);
        const sub = stream_data.get_sub_by_id(stream_id);
        const topic = $(e.target).parents('li').attr('data-topic-name');

        narrow.activate([
            {operator: 'stream', operand: sub.name},
            {operator: 'topic', operand: topic}],
                        {trigger: 'sidebar'});

        e.preventDefault();
    });
};


window.topic_list = exports;
