zrequire('compose_ui');
zrequire('people');
zrequire('user_status');

set_global('document', {
    execCommand: function () { return false; },
});

set_global('$', global.make_zjquery());

const alice = {
    email: 'alice@zulip.com',
    user_id: 101,
    full_name: 'Alice',
};
const bob = {
    email: 'bob@zulip.com',
    user_id: 102,
    full_name: 'Bob',
};

people.add(alice);
people.add(bob);

function make_textbox(s) {
    // Simulate a jQuery textbox for testing purposes.
    const widget = {};

    widget.s = s;
    widget.focused = false;

    widget.caret = function (arg) {
        if (typeof arg === 'number') {
            widget.pos = arg;
            return;
        }

        if (arg) {
            widget.insert_pos = widget.pos;
            widget.insert_text = arg;
            const before = widget.s.slice(0, widget.pos);
            const after = widget.s.slice(widget.pos);
            widget.s = before + arg + after;
            widget.pos += arg.length;
            return;
        }

        return widget.pos;
    };

    widget.focus = function () {
        widget.focused = true;
    };

    widget.blur = function () {
        widget.focused = false;
    };

    widget.val = function (new_val) {
        if (new_val) {
            widget.s = new_val;
        } else {
            return widget.s;
        }
    };

    widget.trigger = function () {
        return;
    };

    return widget;
}

run_test('insert_syntax_and_focus', () => {
    $('#compose-textarea').val("xyz ");
    $('#compose-textarea').caret = function (syntax) {
        if (syntax !== undefined) {
            $('#compose-textarea').val($('#compose-textarea').val() + syntax);
        } else {
            return 4;
        }
    };
    compose_ui.insert_syntax_and_focus(':octopus:');
    assert.equal($('#compose-textarea').caret(), 4);
    assert.equal($('#compose-textarea').val(), 'xyz :octopus: ');
    assert($("#compose-textarea").is_focused());

});

run_test('smart_insert', () => {
    let textbox = make_textbox('abc');
    textbox.caret(4);

    compose_ui.smart_insert(textbox, ':smile:');
    assert.equal(textbox.insert_pos, 4);
    assert.equal(textbox.insert_text, ' :smile: ');
    assert.equal(textbox.val(), 'abc :smile: ');
    assert(textbox.focused);

    textbox.blur();
    compose_ui.smart_insert(textbox, ':airplane:');
    assert.equal(textbox.insert_text, ':airplane: ');
    assert.equal(textbox.val(), 'abc :smile: :airplane: ');
    assert(textbox.focused);

    textbox.caret(0);
    textbox.blur();
    compose_ui.smart_insert(textbox, ':octopus:');
    assert.equal(textbox.insert_text, ':octopus: ');
    assert.equal(textbox.val(), ':octopus: abc :smile: :airplane: ');
    assert(textbox.focused);

    textbox.caret(textbox.val().length);
    textbox.blur();
    compose_ui.smart_insert(textbox, ':heart:');
    assert.equal(textbox.insert_text, ':heart: ');
    assert.equal(textbox.val(), ':octopus: abc :smile: :airplane: :heart: ');
    assert(textbox.focused);

    // Test handling of spaces for ```quote
    textbox = make_textbox('');
    textbox.caret(0);
    textbox.blur();
    compose_ui.smart_insert(textbox, '```quote\nquoted message\n```\n');
    assert.equal(textbox.insert_text, '```quote\nquoted message\n```\n');
    assert.equal(textbox.val(), '```quote\nquoted message\n```\n');
    assert(textbox.focused);

    textbox = make_textbox('');
    textbox.caret(0);
    textbox.blur();
    compose_ui.smart_insert(textbox, "[Quoting…]\n");
    assert.equal(textbox.insert_text, '[Quoting…]\n');
    assert.equal(textbox.val(), '[Quoting…]\n');
    assert(textbox.focused);

    textbox = make_textbox('abc');
    textbox.caret(3);
    textbox.blur();
    compose_ui.smart_insert(textbox, " test with space");
    assert.equal(textbox.insert_text, ' test with space ');
    assert.equal(textbox.val(), 'abc test with space ');
    assert(textbox.focused);

    // Note that we don't have any special logic for strings that are
    // already surrounded by spaces, since we are usually inserting things
    // like emojis and file links.
});

run_test('replace_syntax', () => {
    $('#compose-textarea').val('abcabc');

    compose_ui.replace_syntax('a', 'A');
    assert.equal($('#compose-textarea').val(), 'Abcabc');

    compose_ui.replace_syntax(/b/g, 'B');
    assert.equal($('#compose-textarea').val(), 'ABcaBc');

    // Verify we correctly handle `$`s in the replacement syntax
    compose_ui.replace_syntax('Bca', '$$\pi$$');
    assert.equal($('#compose-textarea').val(), 'A$$\pi$$Bc');
});

run_test('compute_placeholder_text', () => {
    let opts = {
        message_type: 'stream',
        stream: '',
        topic: '',
        private_message_recipient: '',
    };

    // Stream narrows
    assert.equal(compose_ui.compute_placeholder_text(opts), i18n.t("Compose your message here"));

    opts.stream = "all";
    assert.equal(compose_ui.compute_placeholder_text(opts), i18n.t("Message #all"));

    opts.topic = "Test";
    assert.equal(compose_ui.compute_placeholder_text(opts), i18n.t("Message #all > Test"));

    // PM Narrows
    opts = {
        message_type: 'private',
        stream: '',
        topic: '',
        private_message_recipient: '',
    };
    assert.equal(compose_ui.compute_placeholder_text(opts), i18n.t("Compose your message here"));

    opts.private_message_recipient = 'bob@zulip.com';
    user_status.set_status_text({
        user_id: bob.user_id,
        status_text: 'out to lunch',
    });
    assert.equal(compose_ui.compute_placeholder_text(opts), i18n.t("Message Bob (out to lunch)"));

    opts.private_message_recipient = 'alice@zulip.com';
    user_status.set_status_text({
        user_id: alice.user_id,
        status_text: '',
    });
    assert.equal(compose_ui.compute_placeholder_text(opts), i18n.t("Message Alice"));

    // Group PM
    opts.private_message_recipient = 'alice@zulip.com,bob@zulip.com';
    assert.equal(compose_ui.compute_placeholder_text(opts), i18n.t("Message Alice, Bob"));
});
