<% page_title t('titles.schools'), @school.displayName, t('titles.groups'), t('titles.group_members_mass_edit') %>

<% content_for :javascript do %>
<script>
const SUPERTABLE_WORKER_FILE = "<%= javascript_path 'supertable3_worker' %>";
let GLOBAL_SUPERTABLE_INSTANCE = null;
</script>

<%= javascript_include_tag 'javascripts/modal_popup' %>
<%= javascript_include_tag 'javascripts/supertable3' %>
<% end %>

<%= render 'shared/supertable_controls' %>
<div class="superTable" id="tableGroupMembers"></div>

<% content_for :post_load_javascript do %>
<script>
"use strict;"

<%= render partial: 'shared/supertable_translations', formats: [:js] %>

let GROUPS_LIST = <%= raw JSON.pretty_generate(@initial_groups) %>;

// Localized user role names
const USER_ROLES = {
    owner: "<%= t('organisation_owner_role') %>",
    schooladmin: "<%= t('school_admin_role') %>",
    admin: "<%= t('puavoEduPersonAffiliation_admin') %>",
    teacher: "<%= t('puavoEduPersonAffiliation_teacher') %>",
    student: "<%= t('puavoEduPersonAffiliation_student') %>",
    staff: "<%= t('puavoEduPersonAffiliation_staff') %>",
    testuser: "<%= t('puavoEduPersonAffiliation_testuser') %>",
    parent: "<%= t('puavoEduPersonAffiliation_parent') %>",
    visitor: "<%= t('puavoEduPersonAffiliation_visitor') %>",
    unknown: "<%= t('unknown_role') %>",
};

// Localized group types
const GROUP_TYPES = {
    "teaching group": "<%= t('group_type.teaching group') %>",
    "course group": "<%= t('group_type.course group') %>",
    "year class": "<%= t('group_type.year class') %>",
    "administrative group": "<%= t('group_type.administrative group') %>",
    "archive users": "<%= t('group_type.archive users') %>",
    "other groups": "<%= t('group_type.other groups') %>",
};

const DEFAULT_COLUMNS = ["name", "uid", "role", "locked", "marked", "groups"];
const DEFAULT_SORTING = { column: "uid", dir: ST.SortOrder.ASCENDING };

const COLUMN_ORDER = [
    "id",
    "first",
    "last",
    "name",
    "uid",
    "role",
    "locked",
    "marked",
    "groups",
];

const COLUMN_DEFINITIONS = {
    id: {
        key: "id",
        title: "<%= t('columns.puavoid') %>",
        type: ST.ColumnType.NUMERIC,
    },

    first: {
        key: "first",
        title: "<%= t('columns.users.first_names') %>",
        type: ST.ColumnType.STRING,
        alias: ["first_name", "fn"],
    },

    last: {
        key: "last",
        title: "<%= t('columns.users.last_name') %>",
        type: ST.ColumnType.STRING,
        alias: ["last_name", "ln"],
    },

    name: {
        key: "name",
        title: "<%= t('columns.users.full_name') %>",
        type: ST.ColumnType.STRING,
        transform: entry => {
            return [
                `<a href="/users/${entry.school_id}/users/${entry.id}">${ST.escapeHTML(entry.name)}</a>`,
                entry.name
            ];
        }
    },

    uid: {
        key: "uid",
        title: "<%= t('columns.users.uid') %>",
        type: ST.ColumnType.STRING,
    },

    role: {
        key: "role",
        title: "<%= t('columns.users.role') %>",
        type: ST.ColumnType.STRING,
        transform: entry => {
            let values = [];

            // Translate user roles
            for (let i = 0; i < entry.role.length; i++) {
                const r = entry.role[i];

                values.push((r in USER_ROLES) ? USER_ROLES[r] : USER_ROLES['unknown']);
            }

            return [
                values.join("<br>"),
                entry.role.join()
            ];
        }
    },

    locked: {
        key: "locked",
        title: "<%= t('columns.users.is_locked') %>",
        type: ST.ColumnType.BOOL,
    },

    marked: {
        key: "marked",
        title: "<%= t('columns.users.rrt') %>",
        type: ST.ColumnType.UNIXTIME,
    },

    groups: {
        key: "groups",
        title: "<%= t('columns.groups.member_groups') %>",
        type: ST.ColumnType.STRING,
        transform: entry => {
            let values = [],
                plain = [];

            for (const g of entry.groups) {
                values.push(`<a href="${g.link}">${g.title}</a> <small>[${g.school}]</small>`);
                plain.push(g.title);
            }

            return [
                values.join("<br>"),
                plain.join(","),
                plain.join(","),
            ];
        }
    },
};

// Common base class for group operations
class GroupOperationBase extends ST.MassOperation {
    constructor(parent, container)
    {
        super(parent, container);
        this.groupIDs = [];
    }

    _buildInterface(preamble)
    {
        this.container.innerHTML = preamble + this.buildGroupsList();
        this.fillGroupsList();
        this.setupEvents();
    }

    canProceed()
    {
        if (this.getGroupItems(true).length == 0) {
            window.alert("<%= t('groups.index.mass_operations.select_something') %>");
            return false;
        }

        return true;
    }

    start()
    {
        this.groupIDs = [];

        for (const i of this.getGroupItems(true))
            this.groupIDs.push(parseInt(i.dataset.id, 10));

        console.log(this.groupIDs);
    }

    getOperationParameters()
    {
        return {
            groups: this.groupIDs,
        };
    }

    prepareItem(item)
    {
        return {
            state: "ready"
        };
    }

    buildGroupsList()
    {
        const html =
`<div class="flex-cols gap-5px">
    <div class="flex-rows gap-5px checkboxScrollListOuter">
        <input type="search" spellcheck="false" placeholder="<%= t('groups.index.mass_operations.search_placeholder') %>">
        <div id="groupList" class="checkboxScrollList" style="width: 30em; height: 20em;"></div>
    </div>
    <div>
        <button id="reloadGroups"><%= t('groups.index.mass_operations.reload') %></button>
    </div>
</div>`;

        return html;
    }

    fillGroupsList()
    {
        let html = "";

        for (const g of GROUPS_LIST) {
            const type = g.type ? GROUP_TYPES[g.type] : "(?)";

            html += `<div class="item" data-id="${g.id}" data-filter="${g.name.toLowerCase()}">`;
            html += `<input type="checkbox"></input>${g.name} (${g.abbr}), ${type}</div>`;
        }

        this.container.querySelector("div#groupList").innerHTML = html;
    }

    getGroupItems(selected)
    {
        let path = "div#groupList > div.item";

        if (selected)
            path += ".selected";

        return this.container.querySelectorAll(path);
    }

    onReloadGroups()
    {
        const csrf = document.querySelector("meta[name='csrf-token']");

        for (const i of this.container.querySelectorAll("input"))
            i.disabled = true;

        for (const i of this.container.querySelectorAll("button"))
            i.disabled = true;

        for (const i of this.getGroupItems())
            i.classList.add("disabled");

        fetch("/users/<%= @school.id %>/groups/update_groups_list", {
            method: "GET",
            mode: "cors",
            headers: {
                "Content-Type": "application/json; charset=utf-8",
                "X-CSRF-Token": csrf ? csrf.content : "",
            }
        }).then(function(response) {
            if (!response.ok)
                throw response;

            return response.text();
        }).then(data => {
            let parsed = null;

            try {
                parsed = JSON.parse(data);
            } catch (e) {
                console.log(data);
                console.error(e);
                window.alert("<%= t('groups.index.mass_operations.invalid_response') %>");
                return;
            }

            GROUPS_LIST = parsed;

            this.fillGroupsList();
            this.onFilter();
            this.setupEvents(false);    // re-set the list entry click handlers
        }).catch(error => {
            console.error(error);
            window.alert("<%= t('groups.index.mass_operations.network_error') %>");
            return;
        }).finally(() => {
            for (const i of this.container.querySelectorAll("input"))
                i.disabled = false;

            for (const i of this.container.querySelectorAll("button"))
                i.disabled = false;

            for (const i of this.getGroupItems())
                i.classList.remove("disabled");
        });
    }

    // Filter the group list
    onFilter()
    {
        const search = this.container.querySelector(`input[type="search"]`).value.trim().toLowerCase();

        for (const i of this.getGroupItems()) {
            const title = i.dataset.filter;

            // Hide, don't remove. Preserves selections.
            if (search && title.indexOf(search) == -1)
                i.classList.add("hidden");
            else i.classList.remove("hidden");
        }
    }

    // Select/deselect group
    onToggleGroup(target)
    {
        if (target.classList.contains("disabled"))
            return;

        if (target.classList.contains("selected")) {
            target.classList.remove("selected");
            target.childNodes[0].checked = false;
        } else {
            target.classList.add("selected");
            target.childNodes[0].checked = true;
        }
    }

    setupEvents(initial=true)
    {
        if (initial) {
            this.container.querySelector(`input[type="search"]`)
                .addEventListener("input", e => this.onFilter());

            this.container.querySelector(`button#reloadGroups`)
                .addEventListener("click", () => this.onReloadGroups());
        }

        for (const i of this.getGroupItems())
            i.addEventListener("click", e => this.onToggleGroup(e.target));
    }
}

class AddToGroup extends GroupOperationBase {
    buildInterface()
    {
        this._buildInterface("<%= t('groups.index.mass_operations.add.help') %>");
    }
};

class RemoveFromGroup extends GroupOperationBase {
    buildInterface()
    {
        this._buildInterface("<%= t('groups.index.mass_operations.remove.help') %>");
    }
};

const MASS_OPERATIONS = [
    {
        operation: "add_to_group",
        title: "<%= t('groups.index.mass_operations.add.title') %>",
        haveSettings: true,
        cls: AddToGroup
    },

    {
        operation: "remove_from_group",
        title: "<%= t('groups.index.mass_operations.remove.title') %>",
        haveSettings: true,
        cls: RemoveFromGroup
    },
];

const MASS_SELECTS = [
    ["uid", "<%= t('columns.users.uid') %>"],
    ["name", "<%= t('columns.users.full_name') %>"],
];

// "Unpack" the condensed user/group data into full rows
function* synthesizeData(raw)
{
    for (const [_, u] of Object.entries(raw.users)) {
        let u2 = {...u};

        // These fields don't exist in the data, generate them on-the-fly
        u2.school_id = <%= @school.id %>;
        u2.name = `${u.first} ${u.last}`;

        // Rewrite group information in-place. Group information is highly repetitive
        // and verbose, so it has been stored in a more compact format and we must
        // "expand" it to full rows for the table.
        for (let i = 0; i < u2.groups.length; i++) {
            const gid = u2.groups[i],
                  group = raw.groups[gid],
                  school = raw.schools[group.school];

            const type = group.type ? GROUP_TYPES[group.type] : "(?)"

            u2.groups[i] = {
                title: `${group.name} (${group.abbr}, ${type})`,
                link: `/users/${school.id}/groups/${gid}`,
                school: school.name,
            };
        }

        yield u2;
    }
}

document.addEventListener("DOMContentLoaded", () => {
    modalPopup.setupGlobalEvents();

    GLOBAL_SUPERTABLE_INSTANCE = new ST.SuperTable(
        // Main container DIV
        document.getElementById("tableGroupMembers"),

        // Settings
        {
            id: "groupMembersTable",
            locale: "<%= supertable_sorting_locale %>",
            csvPrefix: `<%= LdapOrganisation.current.o %>-<%= @school.cn %>-members`,
            enableExport: false,
            columnDefinitions: COLUMN_DEFINITIONS,
            columnOrder: COLUMN_ORDER,
            massSelects: MASS_SELECTS,
            massOperations: MASS_OPERATIONS,
            massOperationsEndpoint: "<%= groups_mass_operations_path %>",
            defaultColumns: DEFAULT_COLUMNS,
            defaultSorting: DEFAULT_SORTING,
            dynamicData: "/users/<%= @school.id %>/groups/get_all_groups_members",
            preFilterFunction: synthesizeData,
        }
    );
});

</script>
<% end %>
