<commit_before>var embedTrailers = false;
var alwaysEditingFilms = false;

window.addEventListener('load', function () {
    addNavTab("Films", manageFilms);
});

////////////////////////////////// Films ///////////////////////////////////////

/**
 * Films program entry point.
 * Gets a list of users from the server, then runs the default search.
 */
function manageFilms() {
    // Get info for displaying films
    ajax("GET", "floop/accounts", null, getFilms);
}

/**
 * Gets a list of films from the server.
 * If not all users are selected in the table, a list of selected users will
 * be included in the request.
 * 
 * @param {array(String)} users
 */
function getFilms(users) {
    createFilm(); // Always show new film controls

    var url = "floop/films";

    // If film table has been drawn
    if (isSet(getElem('filmTable'))) {

        // Find selected users
        var selectedUsers = getSelectedUsers(users);
        // Append to url if not all selected
        if (selectedUsers.length < users.length) {
            url += "/viewers/" + selectedUsers.join();
        }
    }

    ajax("GET", url, null, drawFilmTable.bind(null, users));
}

/**
 * Returns an array of the currently selected users
 * 
 * @param {array(String)} users
 * @returns {array(String)}
 */
function getSelectedUsers(users) {
    var selectedUsers = [];
    for (var i = 0; i < users.length; i++) {
        if (getElem('UserCell' + i).checked) {
            selectedUsers.push(users[i]);
        }
    }
    return selectedUsers;
}

/**
 * Creates a new film with the title ""
 */
function createFilm() {
    ajax('POST', 'floop/films', "");
}

/**
 * Draws a table containing an ordered list of films with adding 
 * and editing controls.
 * 
 * @param {array(String)} users
 * @param {array(object)} films
 */
function drawFilmTable(users, films) {
    log();

    // Find or create table
    var table = getElem('filmTable');
    if (!isSet(table)) {
        table = createFilmTable(users);
    } else {

        // Clear table
        log("Clearing film table");
        var i = table.rows.length - 1;
        while (i > 0) {
            table.deleteRow(i);
            i--;
        }
    }


    // Fill table
    log("-----------------------------------------");
    for (var j = 0; j < films.length; j++) {
        displayFilm(films[j], users, table);
    }
}

/**
 * Draws the column headers for the film table.
 * 
 * @param {array(String)} users
 */
function createFilmTable(users) {
    log("Creating film table");

    // Create table and column headers

    var table = newElem('table');
    table.id = "filmTable";

    var row = newElem('tr');

    row.innerHTML = "<th class='TrailerCell'>Trailer</th> \
                     <th class='TitleCell'>Title</th>     \
                     <th class='ProgressCell'>Progress</th>";

    // User name column headers
    for (var i = 0; i < users.length; i++) {
        log("Adding user to table: " + users[i]);

        var ratingCell = newElem('th', 'UserCell Checked');
        ratingCell.innerHTML = users[i];
        ratingCell.id = 'UserCell' + i;
        ratingCell.checked = true;
        ratingCell.onclick = function () {
            this.checked = !this.checked;
            var state = this.checked ? " Checked" : "";
            this.className = 'UserCell' + state;
            getFilms(users);
        };
        row.appendChild(ratingCell);
    }

    var totalCell = newElem('th', 'TotalCell');
    totalCell.innerHTML = 'Total';
    row.appendChild(totalCell);



    // Toggle embedded trailers button
    appendIconBtnCell(row, "./Res/playIcon.png", function () {
        embedTrailers = !embedTrailers;
        getFilms(users);
    });

    // Toggle always editing button
    appendIconBtnCell(row, "./Res/editIcon.png", function () {
        alwaysEditingFilms = !alwaysEditingFilms;
        getFilms(users);
    });


    // Display
    table.appendChild(row);
    clearDisplay();
    appendTo('Display', table);
    return table;
}

/**
 * Displays film in table.
 * Table is passed as a variable as it may not have been drawn to 
 * reduce DOM restructures.
 * 
 * @param {object} film
 * @param {array(String)} users
 * @param {'table'} table
 */
function displayFilm(film, users, table) {
    log("Displaying info for: " + film.title);

    // Edit film if has default values
    if (film.title === "") {
        editFilm(users, table.insertRow(1), film);
        return;
    }
    if (alwaysEditingFilms) {
        editFilm(users, table.insertRow(), film);
        return;
    }

    var row = newElem('TR');

    // Get trailer (use empty string if null)
    displayTrailerOrAuto(row, film, users);


    appendCell(row, film.title, "TitleCell");

    appendCell(row, film.progress, "ProgressCell");

    appendRatings(row, film, users);

    appendFilmButtons(row, film, users, false);

    // Add to table
    table.appendChild(row);

    log(row);
    log("-----------------------------------------");
}

/**
 * Returns HTML code for either a link to or embedded player for the video 
 * located at src URL, depending on global variable 'embedTrailers'.
 * 
 * @param {String} src
 * @returns {String}
 */
function embedTrailer(src) {
    if (embedTrailers) {
        // Database must process YouTube links for embedding
        return '<iframe src=' + src + ' controls=2></iframe>';
    } else {
        return "<a href=" + src + ">\
                <img src='./Res/playIcon.png' class='icon'</img></a>";
    }
}


////////////////////////////// Editing Films ///////////////////////////////////

/**
 * Enbales edit controls for the film provided using the row provided 
 * in the film table.
 * 
 * @param {array(String)} users
 * @param {'tr'} row
 * @param {object} film
 */
function editFilm(users, row, film) {
    row.innerHTML = "";


    if (alwaysEditingFilms) {
        displayTrailerOrAuto(row, film, users);
    } else {
        // Trailer edit controls
        var trailer = isSet(film.trailer) ? film.trailer : "";

        var trailerField = newElem('input', "TableInput", "Trailer", trailer);
        trailerField.onblur = updateFilm.bind(null, film.filmID, "trailer", trailerField);

        var autoTrailerBtn = newIconBtn(icon('search'), function () {
            trailerField.value = "AUTO";
            updateFilm(film.filmID, "trailer", trailerField);
        }, "Mini");

        var trailerCell = appendCell(row);
        trailerCell.appendChild(trailerField);
        trailerCell.appendChild(autoTrailerBtn);
    }


    // Title field
    var titleField = newElem('input', "TableInput", "Title", film.title);
    titleField.onblur = updateFilm.bind(null, film.filmID, "title", titleField,
            function () { // TODO resolve timing race

                if (alwaysEditingFilms) {
                    getAutoTrailer(film.filmID);
                } else {
                    // Get new auto trailer if nessesary
                    if (trailerField.value === "AUTO") {
                        getAutoTrailer(film.filmID);
                    }
                }

            });
    appendCell(row, null, "TitleCell").appendChild(titleField);


    // Progress field
    var progressField = newElem('input', "TableInput", "Progress", film.progress);
    progressField.onblur = updateFilm.bind(null, film.filmID, "progress", progressField);
    appendCell(row, null, "ProgressCell").appendChild(progressField);


    appendRatings(row, film, users);

    appendFilmButtons(row, film, users, true);

    log(row);
    log("-----------------------------------------");
}

/**
 * Sets trailer for film with filmID to auto-find.<commit_msg>Films optimisation and bugfix<commit_after>var embedTrailers = false;
var alwaysEditingFilms = false;

window.addEventListener('load', function () {
    addNavTab("Films", manageFilms);
});

////////////////////////////////// Films ///////////////////////////////////////

/**
 * Films program entry point.
 * Gets a list of users from the server, then runs the default search.
 */
function manageFilms() {
    // Get info for displaying films
    ajax("GET", "floop/accounts", null, getFilms);
}

/**
 * Gets a list of films from the server.
 * If not all users are selected in the table, a list of selected users will
 * be included in the request.
 * 
 * @param {array(String)} users
 */
function getFilms(users) {

    var url = "floop/films";

    // If film table has been drawn
    if (isSet(getElem('filmTable'))) {

        // Find selected users
        var selectedUsers = getSelectedUsers(users);
        // Append to url if not all selected
        if (selectedUsers.length < users.length) {
            url += "/viewers/" + selectedUsers.join();
        }
    }

    ajax("GET", url, null, drawFilmTable.bind(null, users));
}

/**
 * Returns an array of the currently selected users
 * 
 * @param {array(String)} users
 * @returns {array(String)}
 */
function getSelectedUsers(users) {
    var selectedUsers = [];
    for (var i = 0; i < users.length; i++) {
        if (getElem('UserCell' + i).checked) {
            selectedUsers.push(users[i]);
        }
    }
    return selectedUsers;
}

/**
 * Creates a new film with the title ""
 */
function createFilm() {
    ajax('POST', 'floop/films', "");
}

/**
 * Draws a table containing an ordered list of films with adding 
 * and editing controls.
 * 
 * @param {array(String)} users
 * @param {array(object)} films
 */
function drawFilmTable(users, films) {
    log();

    // Find or create table
    var table = getElem('filmTable');
    if (!isSet(table)) {
        table = createFilmTable(users);
    } else {

        // Clear table
        log("Clearing film table");
        var i = table.rows.length - 1;
        while (i > 0) {
            table.deleteRow(i);
            i--;
        }
    }


    // Fill table
    log("-----------------------------------------");
    var hasEditingRow = false;

    for (var j = 0; j < films.length; j++) {
        displayFilm(films[j], users, table);
        if (films[j].title === "") {
            hasEditingRow = true;
        }
    }
    
    // Create blank film and reload if non existent.
    if (!hasEditingRow) {
        createFilm();
        ajax("GET", "floop/films", null, drawFilmTable.bind(null, users));
    }
}

/**
 * Draws the column headers for the film table.
 * 
 * @param {array(String)} users
 */
function createFilmTable(users) {
    log("Creating film table");

    // Create table and column headers

    var table = newElem('table');
    table.id = "filmTable";

    var row = newElem('tr');

    row.innerHTML = "<th class='TrailerCell'>Trailer</th> \
                     <th class='TitleCell'>Title</th>     \
                     <th class='ProgressCell'>Progress</th>";

    // User name column headers
    for (var i = 0; i < users.length; i++) {
        log("Adding user to table: " + users[i]);

        var ratingCell = newElem('th', 'UserCell Checked');
        ratingCell.innerHTML = users[i];
        ratingCell.id = 'UserCell' + i;
        ratingCell.checked = true;
        ratingCell.onclick = function () {
            this.checked = !this.checked;
            var state = this.checked ? " Checked" : "";
            this.className = 'UserCell' + state;
            getFilms(users);
        };
        row.appendChild(ratingCell);
    }

    var totalCell = newElem('th', 'TotalCell');
    totalCell.innerHTML = 'Total';
    row.appendChild(totalCell);



    // Toggle embedded trailers button
    appendIconBtnCell(row, "./Res/playIcon.png", function () {
        embedTrailers = !embedTrailers;
        getFilms(users);
    });

    // Toggle always editing button
    appendIconBtnCell(row, "./Res/editIcon.png", function () {
        alwaysEditingFilms = !alwaysEditingFilms;
        getFilms(users);
    });


    // Display
    table.appendChild(row);
    clearDisplay();
    appendTo('Display', table);
    return table;
}

/**
 * Displays film in table.
 * Table is passed as a variable as it may not have been drawn to 
 * reduce DOM restructures.
 * 
 * @param {object} film
 * @param {array(String)} users
 * @param {'table'} table
 */
function displayFilm(film, users, table) {
    log("Displaying info for: " + film.title);

    // Edit film if has default values
    if (film.title === "") {
        editFilm(users, table.insertRow(1), film);
        return;
    }
    if (alwaysEditingFilms) {
        editFilm(users, table.insertRow(), film);
        return;
    }

    var row = newElem('TR');

    // Get trailer (use empty string if null)
    displayTrailerOrAuto(row, film, users);


    appendCell(row, film.title, "TitleCell");

    appendCell(row, film.progress, "ProgressCell");

    appendRatings(row, film, users);

    appendFilmButtons(row, film, users, false);

    // Add to table
    table.appendChild(row);

    log(row);
    log("-----------------------------------------");
}

/**
 * Returns HTML code for either a link to or embedded player for the video 
 * located at src URL, depending on global variable 'embedTrailers'.
 * 
 * @param {String} src
 * @returns {String}
 */
function embedTrailer(src) {
    if (embedTrailers) {
        // Database must process YouTube links for embedding
        return '<iframe src=' + src + ' controls=2></iframe>';
    } else {
        return "<a href=" + src + ">\
                <img src='./Res/playIcon.png' class='icon'</img></a>";
    }
}


////////////////////////////// Editing Films ///////////////////////////////////

/**
 * Enbales edit controls for the film provided using the row provided 
 * in the film table.
 * 
 * @param {array(String)} users
 * @param {'tr'} row
 * @param {object} film
 */
function editFilm(users, row, film) {
    row.innerHTML = "";


    if (alwaysEditingFilms) {
        displayTrailerOrAuto(row, film, users);
    } else {
        // Trailer edit controls
        var trailer = isSet(film.trailer) ? film.trailer : "";

        var trailerField = newElem('input', "TableInput", "Trailer", trailer);
        trailerField.onblur = updateFilm.bind(null, film.filmID, "trailer", trailerField);

        var autoTrailerBtn = newIconBtn(icon('search'), function () {
            trailerField.value = "AUTO";
            updateFilm(film.filmID, "trailer", trailerField);
        }, "Mini");

        var trailerCell = appendCell(row);
        trailerCell.appendChild(trailerField);
        trailerCell.appendChild(autoTrailerBtn);
    }


    // Title field
    var titleField = newElem('input', "TableInput", "Title", film.title);
    titleField.onblur = updateFilm.bind(null, film.filmID, "title", titleField,
            function () { // TODO resolve timing race

                if (film.title === "") {
                    createFilm(); // Always show new film controls
                }

                if (alwaysEditingFilms) {
                    getAutoTrailer(film.filmID);
                } else {
                    // Get new auto trailer if nessesary
                    if (trailerField.value === "AUTO") {
                        getAutoTrailer(film.filmID);
                    }
                }

            });
    appendCell(row, null, "TitleCell").appendChild(titleField);


    // Progress field
    var progressField = newElem('input', "TableInput", "Progress", film.progress);
    progressField.onblur = updateFilm.bind(null, film.filmID, "progress", progressField);
    appendCell(row, null, "ProgressCell").appendChild(progressField);


    appendRatings(row, film, users);

    appendFilmButtons(row, film, users, true);

    log(row);
    log("-----------------------------------------");
}

/**
 * Sets trailer for film with filmID to auto-find.
{'fraction_non_alphanumeric': 0.16481976818239716, 'fraction_numerical': 0.0008916061648197682, 'mean_word_length': 2.1481555733761026, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1397749', 'n_tokens_mistral': 4597, 'n_tokens_neox': 4346, 'n_words': 1239}