// Used to populate dynamic content in the ticket and recurring ticket add modals based on selected client

// Not every modal that loads this script has every dropdown, and a modal opened
// from a contact page has no client selector at all - the client arrives as a
// hidden field. Everything below therefore checks that an element exists before
// touching it, rather than assuming the full set is present.

// Client selected listener
//  We seem to have to use jQuery to listen for events, as the client input is a select2 component?

// Wrapped in an IIFE because a modal can be opened, closed and opened again in one
// page load, which re-runs this file - a top-level const would throw on the second
// run and take the whole script with it.

(function () {

    const clientSelectDropdown = document.getElementById("changeClientSelect"); // Define client selector

    if (clientSelectDropdown) {

        // If the client selector is disabled, we must be on a client-specific page instead. Trigger the lists to update.
        if (clientSelectDropdown.disabled) {

            let client_id = clientSelectDropdown.value;

            populateLists(client_id);
        }

        // Listener for client selection. Populate select lists when a client is selected
        clientSelectDropdown.addEventListener('change', function () {
            let client_id = this.value;

            // Update the dependent dropdown lists
            populateLists(client_id);

        });

    } else {

        // No client selector - the modal was opened from a contact page, where the
        // client is fixed and arrives as a hidden field instead
        const clientIdHiddenField = document.getElementById("clientIdHidden");

        if (clientIdHiddenField && clientIdHiddenField.value) {
            populateLists(clientIdHiddenField.value);
        }

    }

    // Populates dropdowns with dynamic content based on the client ID
    //  Called when the client select dropdown is used or if the client select is disabled
    function populateLists(client_id) {

        populateContactsDropdown(client_id);

        populateAssetsDropdowns(client_id);

        populateLocationsDropdown(client_id);

        populateVendorsDropdown(client_id);

        populateProjectsDropdown(client_id);
    }

    // Empties a dropdown and adds its placeholder, returning the element - or null if
    // this modal doesn't have it. Pass null as the label for a multi-select, which has
    // no placeholder option of its own.
    function resetDropdown(id, placeholderLabel, placeholderValue) {

        const dropdown = document.getElementById(id);

        if (!dropdown) {
            return null;
        }

        // innerHTML rather than removing options one by one, which leaves empty optgroups behind
        dropdown.innerHTML = '';

        // A multi-select keeps showing its old selections until select2 is told the value changed
        clearTomSelect(dropdown);

        if (placeholderLabel !== null) {
            dropdown[dropdown.length] = new Option(placeholderLabel, placeholderValue);
        }

        return dropdown;
    }

    // Redraws a select2 component after its options have been replaced
    function refreshDropdown(dropdown) {
        if (dropdown) {
            refreshTomSelect(dropdown);
        }
    }

    // Re-applies the value the modal was opened with (e.g. ticket_add.php?project_id=4),
    // which can only be selected once the options it refers to exist
    function applyPreselection(dropdown) {

        if (!hasPreselection(dropdown)) {
            return;
        }

        dropdown.value = dropdown.dataset.selected;
    }

    // True when the modal was opened with a specific value for this dropdown.
    // '0' is the "none selected" value every one of these dropdowns uses, and is
    // truthy as a string - so it has to be excluded explicitly.
    function hasPreselection(dropdown) {
        return Boolean(dropdown && dropdown.dataset.selected && dropdown.dataset.selected !== '0');
    }

    // Adds an optgroup to a dropdown and returns it, so options can be appended into it
    function appendOptionGroup(dropdown, label) {

        if (!dropdown) {
            return null;
        }

        const group = document.createElement("optgroup");
        group.label = label;
        dropdown.appendChild(group);

        return group;
    }

    // Adds an option to an optgroup
    function appendGroupedOption(group, label, value) {

        if (!group) {
            return;
        }

        group.appendChild(new Option(label, value));
    }

    // Builds the asset label as "Name - Make Model - (Contact)", matching how assets read elsewhere
    function buildAssetLabel(asset) {

        let label = asset.asset_name;

        if (asset.asset_make) {
            label = label + " - " + asset.asset_make;

            if (asset.asset_model) {
                label = label + " " + asset.asset_model;
            }
        }

        if (asset.contact_name) {
            label = label + " - (" + asset.contact_name + ")";
        }

        return label;
    }

    // Populate client contacts - one request feeds both the contact picker and the
    // watchers list, as both are built from the same set of people
    function populateContactsDropdown(client_id) {

        if (!document.getElementById("contactSelect") && !document.getElementById("watchersSelect")) {
            return;
        }

        // Send a GET request to ajax.php as ajax.php?get_client_contacts=true&client_id=NUM
        itflowGet(
            "ajax.php",
            {get_client_contacts: 'true', client_id: client_id},
            function(data) {

                // If we get a response from ajax.php, parse it as JSON
                const response = JSON.parse(data);

                // Access the data for contacts (multiple)
                const contacts = response.contacts || [];

                // Contacts dropdown
                const contactSelectDropdown = resetDropdown("contactSelect", '- No One -', '0');

                // Watchers is a tags field - any address can be typed in, these are just the handy ones
                const watchersDropdown = resetDropdown("watchersSelect", null, null);

                // Populate dropdown
                contacts.forEach(contact => {
                    var appendText = "";
                    if (contact.contact_title) {
                        appendText = " - " + contact.contact_title;
                    }
                    if (contact.contact_primary == "1") {
                        appendText = appendText + " (Primary)";
                    } else if (contact.contact_technical == "1") {
                        appendText = appendText + " (Technical)";
                    }

                    if (contactSelectDropdown) {
                        contactSelectDropdown[contactSelectDropdown.length] = new Option(contact.contact_name + appendText, contact.contact_id);
                    }

                    if (watchersDropdown && contact.contact_email) {
                        watchersDropdown[watchersDropdown.length] = new Option(contact.contact_email, contact.contact_email);
                    }
                });

                // Default to the client's primary contact unless the modal was opened for a
                // specific one. Contacts arrive primary-first.
                if (contactSelectDropdown && !hasPreselection(contactSelectDropdown)) {
                    const primaryContact = contacts.find(contact => contact.contact_primary == "1");

                    if (primaryContact) {
                        contactSelectDropdown.value = primaryContact.contact_id;
                    }
                }

                applyPreselection(contactSelectDropdown);

                refreshDropdown(contactSelectDropdown);
                refreshDropdown(watchersDropdown);

            }
        );
    }

    // Populate client assets - feeds both the single asset picker and the additional assets
    // multi-select from one request, as both need the same list
    function populateAssetsDropdowns(client_id) {

        if (!document.getElementById("assetSelect") && !document.getElementById("additionalAssetsSelect")) {
            return;
        }

        itflowGet(
            "ajax.php",
            {get_client_assets: 'true', client_id: client_id},
            function(data) {

                // If we get a response from ajax.php, parse it as JSON
                const response = JSON.parse(data);

                // Access the data for assets (multiple)
                const assets = response.assets || [];

                const assetSelectDropdown = resetDropdown("assetSelect", '- None -', '0');
                const additionalAssetsDropdown = resetDropdown("additionalAssetsSelect", null, null);

                // Assets arrive ordered by type, so a change of type starts a new group
                let currentType = null;
                let assetGroup = null;
                let additionalAssetGroup = null;

                assets.forEach(asset => {
                    const assetType = asset.asset_type || 'Uncategorized';

                    if (assetType !== currentType) {
                        currentType = assetType;
                        assetGroup = appendOptionGroup(assetSelectDropdown, assetType);
                        additionalAssetGroup = appendOptionGroup(additionalAssetsDropdown, assetType);
                    }

                    const assetLabel = buildAssetLabel(asset);

                    appendGroupedOption(assetGroup, assetLabel, asset.asset_id);
                    appendGroupedOption(additionalAssetGroup, assetLabel, asset.asset_id);
                });

                applyPreselection(assetSelectDropdown);

                refreshDropdown(assetSelectDropdown);
                refreshDropdown(additionalAssetsDropdown);

            }
        );
    }

    // Populate client locations
    function populateLocationsDropdown(client_id) {

        if (!document.getElementById("locationSelect")) {
            return;
        }

        itflowGet(
            "ajax.php",
            {get_client_locations: 'true', client_id: client_id},
            function(data) {

                // If we get a response from ajax.php, parse it as JSON
                const response = JSON.parse(data);

                // Access the data for locations (multiple)
                const locations = response.locations || [];

                // Locations dropdown
                const locationSelectDropdown = resetDropdown("locationSelect", '- Location -', '0');

                // Populate dropdown
                locations.forEach(location => {
                    locationSelectDropdown[locationSelectDropdown.length] = new Option(location.location_name, location.location_id);
                });

                applyPreselection(locationSelectDropdown);

                refreshDropdown(locationSelectDropdown);

            }
        );
    }

    // Populate client vendors
    function populateVendorsDropdown(client_id) {

        if (!document.getElementById("vendorSelect")) {
            return;
        }

        itflowGet(
            "ajax.php",
            {get_client_vendors: 'true', client_id: client_id},
            function(data) {

                // If we get a response from ajax.php, parse it as JSON
                const response = JSON.parse(data);

                // Access the data for vendors (multiple)
                const vendors = response.vendors || [];

                // Vendors dropdown
                const vendorSelectDropdown = resetDropdown("vendorSelect", '- Vendor -', '0');

                // Populate dropdown
                vendors.forEach(vendor => {
                    vendorSelectDropdown[vendorSelectDropdown.length] = new Option(vendor.vendor_name, vendor.vendor_id);
                });

                applyPreselection(vendorSelectDropdown);

                refreshDropdown(vendorSelectDropdown);

            }
        );
    }

    // Populate client projects
    function populateProjectsDropdown(client_id) {

        if (!document.getElementById("projectSelect")) {
            return;
        }

        itflowGet(
            "ajax.php",
            {get_client_projects: 'true', client_id: client_id},
            function(data) {

                // If we get a response from ajax.php, parse it as JSON
                const response = JSON.parse(data);

                // Access the data for projects (multiple)
                const projects = response.projects || [];

                // Projects dropdown
                const projectSelectDropdown = resetDropdown("projectSelect", '- Select Project -', '0');

                // Populate dropdown
                projects.forEach(project => {
                    projectSelectDropdown[projectSelectDropdown.length] = new Option(project.project_name, project.project_id);
                });

                applyPreselection(projectSelectDropdown);

                refreshDropdown(projectSelectDropdown);

            }
        );
    }

})();
