"use strict";

const {strict: assert} = require("assert");

const {$t} = require("../zjsunit/i18n");
const {mock_esm, set_global, zrequire} = require("../zjsunit/namespace");
const {run_test} = require("../zjsunit/test");
const blueslip = require("../zjsunit/zblueslip");
const $ = require("../zjsunit/zjquery");
const {page_params} = require("../zjsunit/zpage_params");

const noop = () => {};

const realm_icon = mock_esm("../../static/js/realm_icon");

const channel = mock_esm("../../static/js/channel");
const overlays = mock_esm("../../static/js/overlays");

mock_esm("../../static/js/csrf", {csrf_token: "token-stub"});
mock_esm("../../static/js/list_widget", {
    create: () => ({init: noop}),
});
mock_esm("../../static/js/loading", {
    make_indicator: noop,
    destroy_indicator: noop,
});
mock_esm("../../static/js/ui_report", {
    success(msg, $elem) {
        $elem.val(msg);
    },

    error(msg, xhr, $elem) {
        $elem.val(msg);
    },
});

set_global(
    "FormData",
    class FormData {
        append(field, val) {
            this[field] = val;
        }
    },
);

const settings_config = zrequire("settings_config");
const settings_bots = zrequire("settings_bots");
const stream_settings_data = zrequire("stream_settings_data");
const settings_account = zrequire("settings_account");
const settings_org = zrequire("settings_org");
const dropdown_list_widget = zrequire("dropdown_list_widget");

function test(label, f) {
    run_test(label, ({override, override_rewire, mock_template}) => {
        $("#realm-icon-upload-widget .upload-spinner-background").css = () => {};
        page_params.is_admin = false;
        page_params.realm_domains = [
            {domain: "example.com", allow_subdomains: true},
            {domain: "example.org", allow_subdomains: false},
        ];
        page_params.realm_authentication_methods = {};
        settings_org.reset();
        f({override, override_rewire, mock_template});
    });
}

test("unloaded", () => {
    // This test mostly gets us line coverage, and makes
    // sure things don't explode before set_up is called.

    settings_org.reset();
    settings_org.populate_realm_domains();
    settings_org.populate_auth_methods();
});

function simulate_realm_domains_table() {
    const $tr_stub = $.create("realm-tr-stub");
    $("#realm_domains_table tbody").set_find_results("tr", $tr_stub);
    $tr_stub.remove = () => {};

    let appended;
    $("#realm_domains_table tbody").append = (html) => {
        appended = true;
        assert.equal(html, "stub-domains-list");
    };

    return function verify() {
        assert.ok(appended);
    };
}

function test_realms_domain_modal(override, add_realm_domain) {
    const $info = $(".realm_domains_info");

    $("#add-realm-domain-widget").set_find_results(
        ".new-realm-domain",
        $.create("new-realm-domain-stub"),
    );

    $("#add-realm-domain-widget").set_find_results(
        ".new-realm-domain-allow-subdomains",
        $.create("new-realm-domain-allow-subdomains-stub"),
    );

    let posted;
    let success_callback;
    let error_callback;
    override(channel, "post", (req) => {
        posted = true;
        assert.equal(req.url, "/json/realm/domains");
        success_callback = req.success;
        error_callback = req.error;
    });

    add_realm_domain();

    assert.ok(posted);

    success_callback();
    assert.equal($info.val(), "translated HTML: Added successfully!");

    error_callback({});
    assert.equal($info.val(), "translated HTML: Failed");
}

function createSaveButtons(subsection) {
    const $stub_save_button_header = $(`#org-${CSS.escape(subsection)}`);
    const $save_button_controls = $(".save-button-controls");
    const $stub_save_button = $(`#org-submit-${CSS.escape(subsection)}`);
    const $stub_discard_button = $(`#org-discard-${CSS.escape(subsection)}`);
    const $stub_save_button_text = $(".save-discard-widget-button-text");
    $stub_save_button_header.set_find_results(
        ".subsection-failed-status p",
        $("<failed-status-stub>"),
    );
    $stub_save_button.closest = () => $stub_save_button_header;
    $save_button_controls.set_find_results(".save-button", $stub_save_button);
    $stub_save_button.set_find_results(".save-discard-widget-button-text", $stub_save_button_text);
    $stub_save_button_header.set_find_results(".save-button-controls", $save_button_controls);
    $stub_save_button_header.set_find_results(
        ".subsection-changes-discard button",
        $(`#org-discard-${CSS.escape(subsection)}`),
    );
    $save_button_controls.set_find_results(".discard-button", $stub_discard_button);
    const props = {};
    props.hidden = false;
    $save_button_controls.fadeIn = () => {
        props.hidden = false;
    };
    $save_button_controls.fadeOut = () => {
        props.hidden = true;
    };
    return {
        props,
        $save_button: $stub_save_button,
        $discard_button: $stub_discard_button,
        $save_button_header: $stub_save_button_header,
        $save_button_controls,
        $save_button_text: $stub_save_button_text,
    };
}

function test_submit_settings_form(override, submit_form) {
    Object.assign(page_params, {
        realm_bot_creation_policy: settings_bots.bot_creation_policy_values.restricted.code,
        realm_email_address_visibility:
            settings_config.email_address_visibility_values.admins_only.code,
        realm_add_custom_emoji_policy: settings_config.common_policy_values.by_admins_only.code,
        realm_waiting_period_threshold: 1,
        realm_default_language: '"es"',
        realm_invite_to_stream_policy: settings_config.common_policy_values.by_admins_only.code,
        realm_create_private_stream_policy: settings_config.common_policy_values.by_members.code,
        realm_create_public_stream_policy: settings_config.common_policy_values.by_members.code,
        realm_invite_to_realm_policy: settings_config.common_policy_values.by_members.code,
    });

    override(global, "setTimeout", (func) => func());
    const ev = {
        preventDefault: noop,
        stopPropagation: noop,
    };

    let patched;
    let data;
    let success_callback;
    override(channel, "patch", (req) => {
        patched = true;
        assert.equal(req.url, "/json/realm");
        data = req.data;
        success_callback = req.success;
    });

    let subsection = "other-permissions";
    ev.currentTarget = `#org-submit-${CSS.escape(subsection)}`;
    let stubs = createSaveButtons(subsection);
    let $save_button = stubs.$save_button;
    $save_button.attr("id", `org-submit-${subsection}`);

    $("#id_realm_waiting_period_threshold").val(10);

    const $invite_to_stream_policy_elem = $("#id_realm_invite_to_stream_policy");
    $invite_to_stream_policy_elem.val("1");
    $invite_to_stream_policy_elem.attr("id", "id_realm_invite_to_stream_policy");
    $invite_to_stream_policy_elem.data = () => "number";

    const $create_public_stream_policy_elem = $("#id_realm_create_public_stream_policy");
    $create_public_stream_policy_elem.val("2");
    $create_public_stream_policy_elem.attr("id", "id_realm_create_public_stream_policy");
    $create_public_stream_policy_elem.data = () => "number";

    const $create_private_stream_policy_elem = $("#id_realm_create_private_stream_policy");
    $create_private_stream_policy_elem.val("2");
    $create_private_stream_policy_elem.attr("id", "id_realm_create_private_stream_policy");
    $create_private_stream_policy_elem.data = () => "number";

    const $add_custom_emoji_policy_elem = $("#id_realm_add_custom_emoji_policy");
    $add_custom_emoji_policy_elem.val("1");
    $add_custom_emoji_policy_elem.attr("id", "id_realm_add_custom_emoji_policy");
    $add_custom_emoji_policy_elem.data = () => "number";

    const $bot_creation_policy_elem = $("#id_realm_bot_creation_policy");
    $bot_creation_policy_elem.val("1");
    $bot_creation_policy_elem.attr("id", "id_realm_bot_creation_policy");
    $bot_creation_policy_elem.data = () => "number";
    const $email_address_visibility_elem = $("#id_realm_email_address_visibility");
    $email_address_visibility_elem.val("1");
    $email_address_visibility_elem.attr("id", "id_realm_email_address_visibility");
    $email_address_visibility_elem.data = () => "number";

    const $invite_to_realm_policy_elem = $("#id_realm_invite_to_realm_policy");
    $invite_to_realm_policy_elem.val("2");
    $invite_to_realm_policy_elem.attr("id", "id_realm_invite_to_realm_policy");
    $invite_to_realm_policy_elem.data = () => "number";

    let $subsection_elem = $(`#org-${CSS.escape(subsection)}`);
    $subsection_elem.closest = () => $subsection_elem;
    $subsection_elem.set_find_results(".prop-element", [
        $bot_creation_policy_elem,
        $email_address_visibility_elem,
        $add_custom_emoji_policy_elem,
        $create_public_stream_policy_elem,
        $create_private_stream_policy_elem,
        $invite_to_realm_policy_elem,
        $invite_to_stream_policy_elem,
    ]);

    patched = false;
    submit_form(ev);
    assert.ok(patched);

    let expected_value = {
        bot_creation_policy: 1,
        invite_to_realm_policy: 2,
        invite_to_stream_policy: 1,
        email_address_visibility: 1,
        add_custom_emoji_policy: 1,
        create_public_stream_policy: 2,
        create_private_stream_policy: 2,
    };
    assert.deepEqual(data, expected_value);

    subsection = "user-defaults";
    ev.currentTarget = `#org-submit-${CSS.escape(subsection)}`;
    stubs = createSaveButtons(subsection);
    $save_button = stubs.$save_button;
    $save_button.attr("id", `org-submit-${subsection}`);

    const $realm_default_language_elem = $("#id_realm_default_language");
    $realm_default_language_elem.val("en");
    $realm_default_language_elem.attr("id", "id_realm_default_language");
    $realm_default_language_elem.data = () => "string";

    $subsection_elem = $(`#org-${CSS.escape(subsection)}`);
    $subsection_elem.closest = () => $subsection_elem;
    $subsection_elem.set_find_results(".prop-element", [$realm_default_language_elem]);

    submit_form(ev);
    assert.ok(patched);

    expected_value = {
        default_language: "en",
    };
    assert.deepEqual(data, expected_value);

    // Testing only once for since callback is same for all cases
    success_callback();
    assert.equal(stubs.props.hidden, true);
    assert.equal($save_button.attr("data-status"), "saved");
    assert.equal(stubs.$save_button_text.text(), "translated: Saved");
}

function test_change_save_button_state() {
    const {$save_button_controls, $save_button_text, $save_button, $discard_button, props} =
        createSaveButtons("msg-editing");
    $save_button.attr("id", "org-submit-msg-editing");

    {
        settings_org.change_save_button_state($save_button_controls, "unsaved");
        assert.equal($save_button_text.text(), "translated: Save changes");
        assert.equal(props.hidden, false);
        assert.equal($save_button.attr("data-status"), "unsaved");
        assert.equal($discard_button.visible(), true);
    }
    {
        settings_org.change_save_button_state($save_button_controls, "saved");
        assert.equal($save_button_text.text(), "translated: Save changes");
        assert.equal(props.hidden, true);
        assert.equal($save_button.attr("data-status"), "");
    }
    {
        settings_org.change_save_button_state($save_button_controls, "saving");
        assert.equal($save_button_text.text(), "translated: Saving");
        assert.equal($save_button.attr("data-status"), "saving");
        assert.equal($save_button.hasClass("saving"), true);
        assert.equal($discard_button.visible(), false);
    }
    {
        settings_org.change_save_button_state($save_button_controls, "discarded");
        assert.equal(props.hidden, true);
    }
    {
        settings_org.change_save_button_state($save_button_controls, "succeeded");
        assert.equal(props.hidden, true);
        assert.equal($save_button.attr("data-status"), "saved");
        assert.equal($save_button_text.text(), "translated: Saved");
    }
    {
        settings_org.change_save_button_state($save_button_controls, "failed");
        assert.equal(props.hidden, false);
        assert.equal($save_button.attr("data-status"), "failed");
        assert.equal($save_button_text.text(), "translated: Save changes");
    }
}

function test_upload_realm_icon(override, upload_realm_logo_or_icon) {
    const file_input = [{files: ["image1.png", "image2.png"]}];

    let posted;
    override(channel, "post", (req) => {
        posted = true;
        assert.equal(req.url, "/json/realm/icon");
        assert.equal(req.data.csrfmiddlewaretoken, "token-stub");
        assert.equal(req.data["file-0"], "image1.png");
        assert.equal(req.data["file-1"], "image2.png");
    });

    upload_realm_logo_or_icon(file_input, null, true);
    assert.ok(posted);
}

function test_change_allow_subdomains(change_allow_subdomains) {
    const ev = {
        stopPropagation: noop,
    };

    const $info = $(".realm_domains_info");
    $info.fadeOut = noop;
    const domain = "example.com";
    let allow = true;

    let success_callback;
    let error_callback;
    channel.patch = (req) => {
        assert.equal(req.url, "/json/realm/domains/example.com");
        assert.equal(req.data.allow_subdomains, JSON.stringify(allow));
        success_callback = req.success;
        error_callback = req.error;
    };

    const $domain_obj = $.create("domain object");
    $domain_obj.text(domain);

    const $elem_obj = $.create("<elem html>");
    const $parents_obj = $.create("parents object");

    $elem_obj.set_parents_result("tr", $parents_obj);
    $parents_obj.set_find_results(".domain", $domain_obj);
    $elem_obj.prop("checked", allow);

    change_allow_subdomains.call($elem_obj, ev);

    success_callback();
    assert.equal(
        $info.val(),
        "translated HTML: Update successful: Subdomains allowed for example.com",
    );

    error_callback({});
    assert.equal($info.val(), "translated HTML: Failed");

    allow = false;
    $elem_obj.prop("checked", allow);
    change_allow_subdomains.call($elem_obj, ev);
    success_callback();
    assert.equal(
        $info.val(),
        "translated HTML: Update successful: Subdomains no longer allowed for example.com",
    );
}

function test_extract_property_name() {
    $("#id_realm_allow_message_editing").attr("id", "id_realm_allow_message_editing");
    assert.equal(
        settings_org.extract_property_name($("#id_realm_allow_message_editing")),
        "realm_allow_message_editing",
    );

    $("#id_realm_message_content_edit_limit_minutes_label").attr(
        "id",
        "id_realm_message_content_edit_limit_minutes_label",
    );
    assert.equal(
        settings_org.extract_property_name($("#id_realm_message_content_edit_limit_minutes_label")),
        "realm_message_content_edit_limit_minutes_label",
    );

    $("#id-realm-allow-message-deleting").attr("id", "id-realm-allow-message-deleting");
    assert.equal(
        settings_org.extract_property_name($("#id-realm-allow-message-deleting")),
        "realm_allow_message_deleting",
    );
}

function test_sync_realm_settings() {
    overlays.settings_open = () => true;

    {
        /* Test invalid settings property sync */
        const $property_elem = $("#id_realm_invalid_settings_property");
        $property_elem.attr("id", "id_realm_invalid_settings_property");
        $property_elem.length = 1;

        blueslip.expect(
            "error",
            "Element refers to unknown property realm_invalid_settings_property",
        );
        settings_org.sync_realm_settings("invalid_settings_property");
    }

    function test_common_policy(property_name) {
        const $property_elem = $(`#id_realm_${CSS.escape(property_name)}`);
        $property_elem.length = 1;
        $property_elem.attr("id", `id_realm_${CSS.escape(property_name)}`);

        /* Each policy is initialized to 'by_members' and then all the values are tested
        in the following order - by_admins_only, by_moderators_only, by_full_members,
        by_members. */

        page_params[`realm_${property_name}`] =
            settings_config.common_policy_values.by_members.code;
        $property_elem.val(settings_config.common_policy_values.by_members.code);

        for (const policy_value of Array.from(
            Object.values(settings_config.common_policy_values),
        )) {
            page_params[`realm_${property_name}`] = policy_value.code;
            settings_org.sync_realm_settings(property_name);
            assert.equal($property_elem.val(), policy_value.code);
        }
    }

    test_common_policy("create_private_stream_policy");
    test_common_policy("create_public_stream_policy");
    test_common_policy("invite_to_stream_policy");
    test_common_policy("invite_to_realm_policy");

    {
        /* Test message content edit limit minutes sync */
        const $property_elem = $("#id_realm_message_content_edit_limit_minutes");
        $property_elem.length = 1;
        $property_elem.attr("id", "id_realm_message_content_edit_limit_minutes");

        page_params.realm_create_public_stream_policy = 1;
        page_params.realm_message_content_edit_limit_seconds = 120;

        settings_org.sync_realm_settings("message_content_edit_limit_seconds");
        assert.equal($("#id_realm_message_content_edit_limit_minutes").val(), "2");
    }

    {
        /* Test message content edit limit dropdown value sync */
        const $property_elem = $("#id_realm_msg_edit_limit_setting");
        $property_elem.length = 1;
        $property_elem.attr("id", "id_realm_msg_edit_limit_setting");

        page_params.realm_allow_message_editing = false;
        page_params.realm_message_content_edit_limit_seconds = 120;
        settings_org.sync_realm_settings("allow_message_editing");
        assert.equal($("#id_realm_msg_edit_limit_setting").val(), "never");

        page_params.realm_allow_message_editing = true;

        page_params.realm_message_content_edit_limit_seconds = 120;
        settings_org.sync_realm_settings("allow_message_editing");
        assert.equal($("#id_realm_msg_edit_limit_setting").val(), "upto_two_min");

        page_params.realm_message_content_edit_limit_seconds = 130;
        settings_org.sync_realm_settings("allow_message_editing");
        assert.equal($("#id_realm_msg_edit_limit_setting").val(), "custom_limit");
    }

    {
        /* Test message content edit limit minutes sync */
        const $property_elem = $("#id_realm_message_content_edit_limit_minutes");
        $property_elem.length = 1;
        $property_elem.attr("id", "id_realm_message_content_edit_limit_minutes");

        page_params.realm_create_public_stream_policy = 1;
        page_params.realm_message_content_edit_limit_seconds = 120;

        settings_org.sync_realm_settings("message_content_edit_limit_seconds");
        assert.equal($("#id_realm_message_content_edit_limit_minutes").val(), "2");
    }

    {
        /* Test organization joining restrictions settings sync */
        const $property_elem = $("#id_realm_org_join_restrictions");
        $property_elem.length = 1;
        $property_elem.attr("id", "id_realm_org_join_restrictions");

        page_params.realm_emails_restricted_to_domains = true;
        page_params.realm_disallow_disposable_email_addresses = false;
        settings_org.sync_realm_settings("emails_restricted_to_domains");
        assert.equal($("#id_realm_org_join_restrictions").val(), "only_selected_domain");

        page_params.realm_emails_restricted_to_domains = false;

        page_params.realm_disallow_disposable_email_addresses = true;
        settings_org.sync_realm_settings("emails_restricted_to_domains");
        assert.equal($("#id_realm_org_join_restrictions").val(), "no_disposable_email");

        page_params.realm_disallow_disposable_email_addresses = false;
        settings_org.sync_realm_settings("emails_restricted_to_domains");
        assert.equal($("#id_realm_org_join_restrictions").val(), "no_restriction");
    }
}

function test_parse_time_limit() {
    const $elem = $("#id_realm_message_content_edit_limit_minutes");
    const test_function = (value, expected_value = value) => {
        $elem.val(value);
        page_params.realm_message_content_edit_limit_seconds = settings_org.parse_time_limit($elem);
        assert.equal(
            settings_org.get_realm_time_limits_in_minutes(
                "realm_message_content_edit_limit_seconds",
            ),
            expected_value,
        );
    };

    test_function("0.01", "0");
    test_function("0.1");
    test_function("0.122", "0.1");
    test_function("0.155", "0.2");
    test_function("0.150", "0.1");
    test_function("0.5");
    test_function("1");
    test_function("1.1");
    test_function("10.5");
    test_function("50.3");
    test_function("100");
    test_function("100.1");
    test_function("127.79", "127.8");
    test_function("201.1");
    test_function("501.15", "501.1");
    test_function("501.34", "501.3");
}

function test_discard_changes_button(discard_changes) {
    const ev = {
        preventDefault: noop,
        stopPropagation: noop,
        target: "#org-discard-msg-editing",
    };

    page_params.realm_allow_edit_history = true;
    page_params.realm_edit_topic_policy =
        settings_config.common_message_policy_values.by_everyone.code;
    page_params.realm_allow_message_editing = true;
    page_params.realm_message_content_edit_limit_seconds = 3600;
    page_params.realm_delete_own_message_policy =
        settings_config.common_message_policy_values.by_everyone.code;
    page_params.realm_message_content_delete_limit_seconds = 120;

    const $allow_edit_history = $("#id_realm_allow_edit_history").prop("checked", false);
    const $edit_topic_policy = $("#id_realm_edit_topic_policy").val(
        settings_config.common_message_policy_values.by_admins_only.code,
    );
    const $msg_edit_limit_setting = $("#id_realm_msg_edit_limit_setting").val("custom_limit");
    const $message_content_edit_limit_minutes = $(
        "#id_realm_message_content_edit_limit_minutes",
    ).val(130);
    const $msg_delete_limit_setting = $("#id_realm_msg_delete_limit_setting").val("custom_limit");
    const $message_content_delete_limit_minutes = $(
        "#id_realm_message_content_delete_limit_minutes",
    ).val(130);

    $allow_edit_history.attr("id", "id_realm_allow_edit_history");
    $msg_edit_limit_setting.attr("id", "id_realm_msg_edit_limit_setting");
    $msg_delete_limit_setting.attr("id", "id_realm_msg_delete_limit_setting");
    $edit_topic_policy.attr("id", "id_realm_edit_topic_policy");
    $message_content_edit_limit_minutes.attr("id", "id_realm_message_content_edit_limit_minutes");
    $message_content_delete_limit_minutes.attr(
        "id",
        "id_realm_message_content_delete_limit_minutes",
    );

    const $discard_button_parent = $(".org-subsection-parent");
    $discard_button_parent.find = () => [
        $allow_edit_history,
        $msg_edit_limit_setting,
        $msg_delete_limit_setting,
        $edit_topic_policy,
        $message_content_edit_limit_minutes,
        $message_content_delete_limit_minutes,
    ];

    $("#org-discard-msg-editing").closest = () => $discard_button_parent;

    const stubbed_function = settings_org.change_save_button_state;
    settings_org.__Rewire__("change_save_button_state", (save_button_controls, state) => {
        assert.equal(state, "discarded");
    });

    discard_changes(ev);

    assert.equal($allow_edit_history.prop("checked"), true);
    assert.equal(
        $edit_topic_policy.val(),
        settings_config.common_message_policy_values.by_everyone.code,
    );
    assert.equal($msg_edit_limit_setting.val(), "upto_one_hour");
    assert.equal($message_content_edit_limit_minutes.val(), "60");
    assert.equal($msg_delete_limit_setting.val(), "upto_two_min");
    assert.equal($message_content_delete_limit_minutes.val(), "2");

    settings_org.__Rewire__("change_save_button_state", stubbed_function);
}

test("set_up", ({override, override_rewire, mock_template}) => {
    mock_template("settings/admin_realm_domains_list.hbs", false, () => "stub-domains-list");

    const verify_realm_domains = simulate_realm_domains_table();
    page_params.realm_available_video_chat_providers = {
        jitsi_meet: {
            id: 1,
            name: "Jitsi Meet",
        },
        zoom: {
            id: 3,
            name: "Zoom",
        },
        big_blue_button: {
            id: 4,
            name: "BigBlueButton",
        },
    };

    let upload_realm_logo_or_icon;
    realm_icon.build_realm_icon_widget = (f) => {
        upload_realm_logo_or_icon = f;
    };

    override_rewire(dropdown_list_widget, "DropdownListWidget", () => ({
        setup: noop,
        render: noop,
        update: noop,
    }));
    $("#id_realm_message_content_edit_limit_minutes").set_parent(
        $.create("<stub edit limit parent>"),
    );
    $("#id_realm_message_content_delete_limit_minutes").set_parent(
        $.create("<stub delete limit parent>"),
    );
    $("#id_realm_message_retention_days").set_parent($.create("<stub retention period parent>"));
    $("#message_content_in_email_notifications_label").set_parent(
        $.create("<stub in-content setting checkbox>"),
    );
    $("#enable_digest_emails_label").set_parent($.create("<stub digest setting checkbox>"));
    $("#id_realm_digest_weekday").set_parent($.create("<stub digest weekday setting dropdown>"));
    $("#allowed_domains_label").set_parent($.create("<stub-allowed-domain-label-parent>"));
    const $waiting_period_parent_elem = $.create("waiting-period-parent-stub");
    $("#id_realm_waiting_period_threshold").set_parent($waiting_period_parent_elem);
    $("#id_realm_create_web_public_stream_policy").set_parent(
        $.create("<stub-create-web-public-stream-policy-parent>"),
    );

    // TEST set_up() here, but this mostly just allows us to
    // get access to the click handlers.
    override_rewire(settings_org, "maybe_disable_widgets", noop);
    settings_org.set_up();

    verify_realm_domains();

    test_realms_domain_modal(override, () => $("#submit-add-realm-domain").trigger("click"));
    test_submit_settings_form(
        override,
        $(".admin-realm-form").get_on_handler(
            "click",
            ".subsection-header .subsection-changes-save button",
        ),
    );
    test_upload_realm_icon(override, upload_realm_logo_or_icon);
    test_change_allow_subdomains(
        $("#realm_domains_table").get_on_handler("change", ".allow-subdomains"),
    );
    test_extract_property_name();
    test_change_save_button_state();
    test_sync_realm_settings();
    test_parse_time_limit();
    test_discard_changes_button(
        $(".admin-realm-form").get_on_handler(
            "click",
            ".subsection-header .subsection-changes-discard button",
        ),
    );
});

test("test get_organization_settings_options", () => {
    const sorted_option_values = settings_org.get_organization_settings_options();
    const sorted_common_policy_values = sorted_option_values.common_policy_values;
    const expected_common_policy_values = [
        {
            key: "by_admins_only",
            order: 1,
            code: 2,
            description: $t({defaultMessage: "Admins"}),
        },
        {
            key: "by_moderators_only",
            order: 2,
            code: 4,
            description: $t({defaultMessage: "Admins and moderators"}),
        },
        {
            key: "by_full_members",
            order: 3,
            code: 3,
            description: $t({defaultMessage: "Admins, moderators and full members"}),
        },
        {
            key: "by_members",
            order: 4,
            code: 1,
            description: $t({defaultMessage: "Admins, moderators and members"}),
        },
    ];
    assert.deepEqual(sorted_common_policy_values, expected_common_policy_values);
});

test("test get_sorted_options_list", () => {
    const option_values_1 = {
        by_admins_only: {
            order: 3,
            code: 2,
            description: $t({defaultMessage: "Admins"}),
        },
        by_members: {
            order: 2,
            code: 1,
            description: $t({defaultMessage: "Admins, moderators and members"}),
        },
        by_full_members: {
            order: 1,
            code: 3,
            description: $t({defaultMessage: "Admins, moderators and full members"}),
        },
    };
    let expected_option_values = [
        {
            key: "by_full_members",
            order: 1,
            code: 3,
            description: $t({defaultMessage: "Admins, moderators and full members"}),
        },
        {
            key: "by_members",
            order: 2,
            code: 1,
            description: $t({defaultMessage: "Admins, moderators and members"}),
        },
        {
            key: "by_admins_only",
            order: 3,
            code: 2,
            description: $t({defaultMessage: "Admins"}),
        },
    ];
    assert.deepEqual(settings_org.get_sorted_options_list(option_values_1), expected_option_values);

    const option_values_2 = {
        by_admins_only: {
            code: 1,
            description: $t({defaultMessage: "Admins"}),
        },
        by_members: {
            code: 2,
            description: $t({defaultMessage: "Admins, moderators and members"}),
        },
        by_full_members: {
            code: 3,
            description: $t({defaultMessage: "Admins, moderators and full members"}),
        },
    };
    expected_option_values = [
        {
            key: "by_admins_only",
            code: 1,
            description: $t({defaultMessage: "Admins"}),
        },
        {
            key: "by_full_members",
            code: 3,
            description: $t({defaultMessage: "Admins, moderators and full members"}),
        },
        {
            key: "by_members",
            code: 2,
            description: $t({defaultMessage: "Admins, moderators and members"}),
        },
    ];
    assert.deepEqual(settings_org.get_sorted_options_list(option_values_2), expected_option_values);
});

test("misc", ({override_rewire}) => {
    page_params.is_admin = false;

    const $stub_notification_disable_parent = $.create("<stub notification_disable parent");
    $stub_notification_disable_parent.set_find_results(
        ".dropdown_list_reset_button",
        $.create("<disable link>"),
    );

    page_params.realm_name_changes_disabled = false;
    page_params.server_name_changes_disabled = false;
    settings_account.update_name_change_display();
    assert.ok(!$("#full_name").prop("disabled"));
    assert.equal($(".change_name_tooltip").is(":visible"), false);

    page_params.realm_name_changes_disabled = true;
    page_params.server_name_changes_disabled = false;
    settings_account.update_name_change_display();
    assert.ok($("#full_name").prop("disabled"));
    assert.ok($(".change_name_tooltip").is(":visible"));

    page_params.realm_name_changes_disabled = true;
    page_params.server_name_changes_disabled = true;
    settings_account.update_name_change_display();
    assert.ok($("#full_name").prop("disabled"));
    assert.ok($(".change_name_tooltip").is(":visible"));

    page_params.realm_name_changes_disabled = false;
    page_params.server_name_changes_disabled = true;
    settings_account.update_name_change_display();
    assert.ok($("#full_name").prop("disabled"));
    assert.ok($(".change_name_tooltip").is(":visible"));

    page_params.realm_email_changes_disabled = false;
    settings_account.update_email_change_display();
    assert.ok(!$("#change_email").prop("disabled"));

    page_params.realm_email_changes_disabled = true;
    settings_account.update_email_change_display();
    assert.ok($("#change_email").prop("disabled"));

    page_params.realm_avatar_changes_disabled = false;
    page_params.server_avatar_changes_disabled = false;
    settings_account.update_avatar_change_display();
    assert.ok($("#user-avatar-upload-widget .image_upload_button").is(":visible"));
    page_params.realm_avatar_changes_disabled = true;
    page_params.server_avatar_changes_disabled = false;
    settings_account.update_avatar_change_display();
    assert.ok(!$("#user-avatar-upload-widget .image_upload_button").is(":visible"));
    page_params.realm_avatar_changes_disabled = false;
    page_params.server_avatar_changes_disabled = true;
    settings_account.update_avatar_change_display();
    assert.ok(!$("#user-avatar-upload-widget .image_upload_button").is(":visible"));
    page_params.realm_avatar_changes_disabled = true;
    page_params.server_avatar_changes_disabled = true;
    settings_account.update_avatar_change_display();
    assert.ok(!$("#user-avatar-upload-widget .image_upload_button").is(":visible"));

    // If organization admin, these UI elements are never disabled.
    page_params.is_admin = true;
    settings_account.update_name_change_display();
    assert.ok(!$("#full_name").prop("disabled"));
    assert.equal($(".change_name_tooltip").is(":visible"), false);

    settings_account.update_email_change_display();
    assert.ok(!$("#change_email").prop("disabled"));

    override_rewire(stream_settings_data, "get_streams_for_settings_page", () => [
        {name: "some_stream", stream_id: 75},
        {name: "some_stream", stream_id: 42},
    ]);

    // Set stubs for dropdown_list_widget:
    const widget_settings = [
        "realm_notifications_stream_id",
        "realm_signup_notifications_stream_id",
        "realm_default_code_block_language",
    ];
    const $dropdown_list_parent = $.create("<list parent>");
    $dropdown_list_parent.set_find_results(
        ".dropdown_list_reset_button",
        $.create("<disable button>"),
    );
    for (const name of widget_settings) {
        const $elem = $.create(`#${CSS.escape(name)}_widget #${CSS.escape(name)}_name`);
        $elem.closest = () => $dropdown_list_parent;
    }

    // We do not define any settings we need in page_params yet, but we don't need to for this test.
    blueslip.expect(
        "warn",
        "dropdown-list-widget: Called without a default value; using null value",
        3,
    );
    settings_org.init_dropdown_widgets();

    let setting_name = "realm_notifications_stream_id";
    let $elem = $(`#${CSS.escape(setting_name)}_widget #${CSS.escape(setting_name)}_name`);
    $elem.closest = () => $stub_notification_disable_parent;
    settings_org.notifications_stream_widget.render(42);
    assert.equal($elem.text(), "#some_stream");
    assert.ok(!$elem.hasClass("text-warning"));

    settings_org.notifications_stream_widget.render(undefined);
    assert.equal($elem.text(), "translated: Disabled");
    assert.ok($elem.hasClass("text-warning"));

    setting_name = "realm_signup_notifications_stream_id";
    $elem = $(`#${CSS.escape(setting_name)}_widget #${CSS.escape(setting_name)}_name`);
    $elem.closest = () => $stub_notification_disable_parent;
    settings_org.signup_notifications_stream_widget.render(75);
    assert.equal($elem.text(), "#some_stream");
    assert.ok(!$elem.hasClass("text-warning"));

    settings_org.signup_notifications_stream_widget.render(undefined);
    assert.equal($elem.text(), "translated: Disabled");
    assert.ok($elem.hasClass("text-warning"));
});
