Greasy Fork is available in English.

Racing: Car Templates

Highlights cars and upgrades based on templates

// ==UserScript==
// @name         Racing: Car Templates
// @namespace    heartflower.torn.com
// @version      1.3.3
// @description  Highlights cars and upgrades based on templates
// @author       Heartflower [2626587]
// @match        https://www.torn.com/page.php?sid=racing*
// @match        https://www.torn.com/loader.php?sid=racing*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=torn.com
// ==/UserScript==

(function() {
    'use strict';

    let settings = 'old';
    let showAdaptRevert = true; // Set to 'false' if you don't want the adapt/revert link to show

    let savedSettings = localStorage.getItem('hf-car-settings');
    if (savedSettings) {
        settings = savedSettings;
    } else {
        localStorage.setItem('hf-car-settings', settings);
    }

    // When set to true, it will show you what the script entails
    let showExplanation = 'true';
    let storedShowExplanation = localStorage.getItem('hf-car-templates-explanation');

    // If it's the first time loading the script, always show the explanation
    if (!storedShowExplanation) {
        showExplanation = 'true';
        localStorage.setItem('hf-car-templates-explanation', 'true');
    } else {
        showExplanation = storedShowExplanation;
    }

    // Show background colours, by default set to true
    let redColor = 'true';
    let storedRedColor = localStorage.getItem('hf-car-templates-red-color');
    if (storedRedColor) {
        redColor = storedRedColor;
    }

    let blueColor = 'true';
    let storedBlueColor = localStorage.getItem('hf-car-templates-blue-color');
    if (storedBlueColor) {
        blueColor = storedBlueColor;
    }

    let greenColor = 'true';
    let storedGreenColor = localStorage.getItem('hf-car-templates-green-color');
    if (storedGreenColor) {
        greenColor = storedGreenColor;
    }

    // Declare some variables to use later
    let chosenCar = '';
    let selectedCar = '';
    let selectedTrack = '';
    let carType = '';
    let carRatio = '';
    let carTurbo = '';
    let possibleTemplates = [];
    let chosenTrack = '';

    // Set added car notes to false unless they've been added
    let addedCarNotes = false;

    // If the person chose a template already during this session, remember it
    let selectedTemplate = '';
    let storedTemplate = sessionStorage.getItem('selectedTemplate');

    if (storedTemplate) {
        selectedTemplate = storedTemplate;
    }

    // Create a set to store already logged title elements
    let loggedTitleElements = new Set();

    // Default Class A Car Templates as chosen by most racing guides
    let oldCarTemplates = [
        { name: 'Mudpit: Sierra Cosworth DS3', noteRecogniser: 'DS3' },
        { name: 'Two Islands: Honda NSX DL2', noteRecogniser: 'DL2' },
        { name: 'Parkland: Honda NSX DS3', noteRecogniser: 'DS3' },
        { name: 'Hammerhead: Honda NSX DS2', noteRecogniser: 'DS2' },
        { name: 'Stone Park: Audi R8 DS3', noteRecogniser: 'DS3' },
        { name: 'Withdrawal: Lexus LFA TL3', noteRecogniser: 'TL3' },
        { name: 'Speedway: Lexus LFA TL3', noteRecogniser: 'TL3' },
        { name: 'Uptown: Lexus LFA TL3', noteRecogniser: 'TL3' },
        { name: 'Underdog: Honda NSX TS2', noteRecogniser: 'TS2' },
        { name: 'Commerce: Honda NSX TS2', noteRecogniser: 'TS2' },
        { name: 'Sewage: Honda NSX TS2', noteRecogniser: 'TS2' },
        { name: 'Industrial: Honda NSX TS3', noteRecogniser: 'TS3' },
        { name: 'Vector: Honda NSX TS3', noteRecogniser: 'TS3' },
        { name: 'Meltdown: Honda NSX TS3', noteRecogniser: 'TS3' },
        { name: 'Docks: Ford GT40 TS3', noteRecogniser: 'TS3' },
        { name: 'Convict: Mercedes SLR TL3', noteRecogniser: 'TL3' },
    ];

    let newCarTemplates = [
        { name: 'Mudpit: Colina Tanprice DS3', noteRecogniser: 'DS3' },
        { name: 'Two Islands: Edomondo NSX DL2', noteRecogniser: 'DL2' },
        { name: 'Parkland: Edomondo NSX DS3', noteRecogniser: 'DS3' },
        { name: 'Hammerhead: Edomondo NSX DS2', noteRecogniser: 'DS2' },
        { name: 'Stone Park: Echo R8 DS3', noteRecogniser: 'DS3' },
        { name: 'Withdrawal: Veloria LFA TL3', noteRecogniser: 'TL3' },
        { name: 'Speedway: Veloria LFA TL3', noteRecogniser: 'TL3' },
        { name: 'Uptown: Veloria LFA TL3', noteRecogniser: 'TL3' },
        { name: 'Underdog: Edomondo NSX TS2', noteRecogniser: 'TS2' },
        { name: 'Commerce: Edomondo NSX TS2', noteRecogniser: 'TS2' },
        { name: 'Sewage: Edomondo NSX TS2', noteRecogniser: 'TS2' },
        { name: 'Industrial: Edomondo NSX TS3', noteRecogniser: 'TS3' },
        { name: 'Vector: Edomondo NSX TS3', noteRecogniser: 'TS3' },
        { name: 'Meltdown: Edomondo NSX TS3', noteRecogniser: 'TS3' },
        { name: 'Docks: Volt GT TS3', noteRecogniser: 'TS3' },
        { name: 'Convict: Mercia SLR TL3', noteRecogniser: 'TL3' },
    ];

    let carTemplates = newCarTemplates;

    if (settings === 'old') {
        carTemplates = oldCarTemplates;
    }

    // If the user already has their own templates, set those instead
    let storedCarTemplates = JSON.parse(localStorage.getItem('carTemplates'));

    if (storedCarTemplates) {
        carTemplates = storedCarTemplates;
    } else {
        carTemplates.sort(); // Order alphabetically for easiness
        localStorage.setItem('carTemplates', JSON.stringify(carTemplates)); // Set the default templates in storage
    }

    // Recommended upgrades to always have on the car
    const overallUpgrades = ['Air Forced Engine Cooling','Air Cooling Ducts for Brakes','Adjustable Rear Spoiler','Front Diffuser','Rear Diffuser','Fast Road Brake Fluid','Braided Brake Hoses',
                             'Grooved and Drilled Brake Discs','Competition Racing Brake Pads','Brake Balance Bias Control','6 Pot Uprated Brakes','Ported and Polished Head','Competition Racing Fuel Pump',
                             'Competition Polished Throttle Body','Bored Out Engine + Forged Pistons','Front Mounted Intercooler','Stage Three Remap','Competition Racing Camshaft','Full Exhaust System',
                             'Stainless Steel 4-1 Manifold','Custom Forced Induction Kit','Super Octane Fuel Plus Nitrous','Polyurethane Bushings Front','Polyurethane Bushings Rear','Upper Front Strut Brace',
                             'Lower Front Strut Brace','Rear Strut Brace','Front Adjustable Tie Rods','Adjustable Rear Control arms','Quick Shift','4 Pin Differential','Competition Racing Clutch','Ultra-Light Flywheel',
                             'Strip Out','Racing Steering Wheel','Lightweight Flocked Dash','Polycarbonate Windows','Carbon Fiber Roof','Carbon Fiber Trunk','Carbon Fiber Hood','Ultra-Lightweight Alloys'];

    // Recommended dirt upgrades
    const dirtLongRatioUpgrades = ['Group N Rally Suspension','Rally Gearbox (Long Ratio)','Rally Tires'];
    const dirtShortRatioUpgrades = ['Group N Rally Suspension','Rally Gearbox (Short Ratio)','Rally Tires'];

    // Recommended tarmac upgrades
    const tarmacLongRatioUpgrades = ['Adjustable Coilover Suspension','Paddle Shift Gearbox (Long Ratio)','Track Tires'];
    const tarmacShortRatioUpgrades = ['Adjustable Coilover Suspension','Paddle Shift Gearbox (Short Ratio)','Track Tires'];

    // Recommended turbo upgrades
    const turbo2Upgrades = ['Stage Two Turbo kit'];
    const turbo3Upgrades = ['Stage Three Turbo Kit'];

    // Set needed car upgrades by default to overall upgrades
    let carUpgrades = [...overallUpgrades];

    // All available tracks on Torn
    let trackNames = [
        'Commerce',
        'Convict',
        'Docks',
        'Hammerhead',
        'Industrial',
        'Meltdown',
        'Mudpit',
        'Parkland',
        'Sewage',
        'Speedway',
        'Stone Park',
        'Two Islands',
        'Underdog',
        'Uptown',
        'Vector',
        'Withdrawal',
    ];

    // All available cars on Torn
    let oldCarNames = [
        'Alfa Romeo 156',
        'Aston Martin One-77',
        'Audi R8',
        'Audi S3',
        'Audi S4',
        'Audi TT Quattro',
        'BMW M5',
        'BMW X5',
        'BMW Z8',
        'Bugatti Veyron',
        'Chevrolet Cavalier',
        'Chevrolet Corvette Z06',
        'Citroen Saxo',
        'Classic Mini',
        'Dodge Charger',
        'Ferrari 458',
        'Fiat Punto',
        'Ford Focus RS',
        'Ford GT40',
        'Ford Mustang',
        'Holden SS',
        'Honda Accord',
        'Honda Civic',
        'Honda Integra R',
        'Honda NSX',
        'Honda S2000',
        'Hummer H3',
        'Lamborghini Gallardo',
        'Lexus LFA',
        'Lotus Exige',
        'Mercedes SLR',
        'Mini Cooper S',
        'Mitsubishi Evo X',
        'Nissan GT-R',
        'Nissan Micra',
        'Peugeot 106',
        'Pontiac Firebird',
        'Porsche 911 GT3',
        'Reliant Robin',
        'Renault Clio',
        'Seat Leon Cupra',
        'Sierra Cosworth',
        'Subaru Impreza STI',
        'Toyota MR2',
        'TVR Sagaris',
        'Vauxhall Astra GSI',
        'Vauxhall Corsa',
        'Volkswagen Beetle',
        'Volkswagen Golf GTI',
        'Volvo 850'
    ];

    // Car names after the change
    let newCarNames = [
        'Mercia SLR',
        'Veloria LFA',
        'Weston Marlin 177',
        'Lambrini Torobravo',
        'Volt GT',
        'Edomondo NSX',
        'Zaibatsu GT-R',
        'Lolo 458',
        'Echo R8',
        'Volt MNG',
        'Bavaria M5',
        'Dart Rampager',
        'Echo S4',
        'Wington GGU ',
        'Tsubasa Impressor',
        'Yotsuhada EVX',
        'Colina Tanprice',
        'Cosmos EX',
        'Chevalier CZ06',
        'Oceania SS',
        'Knight Firebrand',
        'Sturmfahrt 111',
        'Edomondo S2',
        'Volt RS',
        'Bavaria Z8',
        'Edomondo IR',
        'Bedford Nova',
        'Echo S3',
        'Nano Cavalier',
        'Echo Quadrato',
        'Tabata RM2',
        'Chevalier CVR',
        'Edomondo ACD',
        'Bavaria X5',
        'Alpha Milano 156',
        'Invader H3',
        'Coche Basurero',
        'Edomondo Localé',
        'Verpestung Insecta',
        'Papani Colé',
        'Stålhög 860',
        'Verpestung Sport',
        'Zaibatsu Macro',
        'Çagoutte 10-6',
        'Nano Pioneer',
        'Trident',
        'Vita Bravo',
        'Limoen Saxon',
        'Bedford Racer',
    ];

    let carNames = newCarNames;

    if (settings === 'old') {
        carNames = oldCarNames;
    }

    // If the message element is there, add the necessary things to it
    function observeMessageElement() {
        const messageWrap = document.querySelector('.info-msg-cont');
        const categoriesWrap = document.querySelector('.pm-categories-wrap');

        if (categoriesWrap) {
            messageWrap.style.background = 'rgba(20, 113, 151, 0.5)';
            const messageElement = messageWrap.querySelector('.right-round');

            // Find the element containing the racing points text
            let racingPointsElement = document.getElementById('racing-points');

            if (racingPointsElement) {
                // Get the current racing points value
                let racingPoints = racingPointsElement.innerText;

                // Find the element containing the car name
                let carNameElement = document.querySelector('.msg.right-round b');
                if (carNameElement && addedCarNotes == false) {
                    // Get the car name
                    let carName = carNameElement.innerText;
                    selectedCar = carName;

                    // Update the text
                    let newText = carName + " (" + chosenCar + ")";

                    // Replace only the specific part of the text
                    let textNode = racingPointsElement.parentElement.childNodes[1]; // Assuming the second child node
                    textNode.textContent = newText;
                    racingPointsElement.parentElement.innerHTML;

                    addedCarNotes = true;
                }
            }

            // Only show the explanation if wanted and not already there
            let existingTextDiv = document.getElementById('carScriptTextDiv');

            if (!existingTextDiv && showExplanation == 'true') {
                let textDiv = document.createElement('div');
                textDiv.id = 'carScriptTextDiv';
                textDiv.style.paddingTop = '16px';
                textDiv.innerHTML = `The <b style="color:red; font-style:italic">Racing: Car Templates</b> script shows you what upgrades you have and/or are missing based on car templates.
            There are already a few car templates added based on some popular guides, but you're able to remove or add them as you please.
            Clicking the ✓ sets a new template, whilst clicking the X removes an existing template.<br><br>
            Upon setting a new template, you will be asked to enter a <span style='font-style:italic'>note recogniser</span>. This recogniser will be used to highlight the suggested car for a specific race you are joining or creating. You're also able to edit this note recogniser at any time by simply clicking the note button.<br><br>
            You can choose to show or not show background colours by simply clicking their colour.<br>
            A <b style="color:rgb(116, 184, 22)">green</b> background means that the upgrade is suggested and fitted.
            A <b style="color:rgb(20, 113, 151)">blue</b> background means that the upgrade is suggested, but not fitted.
            An <b style="color:rgb(247, 103, 7)">orange</b> background means that the upgrade is not suggested, but fitted.
            <br><br>
            <a href="#" id="removeExplanationLink">Click here to remove the explanation forever.</a>`;

                messageElement.appendChild(textDiv);

                let removeLink = document.getElementById('removeExplanationLink');
                if (removeLink) {
                    removeLink.addEventListener('click', function(event) {
                        event.preventDefault(); // Prevent the default behavior of the link
                        removeExplanation(); // Call the removeExplanation function
                    });
                };
            }

            // Create the radio buttons
            createRadioButtons(messageElement);

            // Create the datalist container
            let datalistContainer = document.querySelector('#racingScriptDatalistContainer');

            if (!datalistContainer) {
                datalistContainer = document.createElement('div');
                datalistContainer.id = 'racingScriptDatalistContainer';
                datalistContainer.style.display = 'flex';
                datalistContainer.style.flexWrap = 'wrap';
                datalistContainer.style.paddingTop = '15px';
                datalistContainer.style.paddingBottom = '10px';

                messageElement.appendChild(datalistContainer);
            }

            // Create other containers
            createCarNamesContainer(datalistContainer);
            createTrackNamesContainer(datalistContainer);
            createCarTemplatesContainer(datalistContainer);

            // Create the button container (template buttons) if not already there
            let buttonContainer = '';

            let existingButtonContainer = document.getElementById('racingButtonContainer');

            if (!existingButtonContainer) {
                buttonContainer = document.createElement('div');
                buttonContainer.id = 'racingButtonContainer';
                buttonContainer.style.display = 'flex';
                buttonContainer.style.paddingTop = '8px';

                datalistContainer.appendChild(buttonContainer);

                // Add button for creating new template
                let createTemplateButtonDiv = document.createElement('div');
                createTemplateButtonDiv.style.paddingRight = '8px';

                buttonContainer.appendChild(createTemplateButtonDiv);

                let createTemplateButton = document.createElement('button');
                createTemplateButton.textContent = '✓';
                createTemplateButton.style.color = 'white';
                createTemplateButton.onclick = createNewTemplate;
                createTemplateButton.style.background = 'url(/images/v2/racing/header/stripy_bg.png) 0 0 repeat';
                createTemplateButton.style.cursor = 'pointer';
                createTemplateButton.style.borderRadius = '5px';
                createTemplateButton.style.transition = 'background-color 0.3s ease';

                // Add event listener to change background color on hover
                createTemplateButton.addEventListener('mouseenter', function(event) {
                    createTemplateButton.style.background = 'rgba(0, 191, 255, 0.5)';
                    createTemplateButton.style.color = 'var(--default-color)';
                });

                // Restore original background color when mouse leaves
                createTemplateButton.addEventListener('mouseleave', function() {
                    createTemplateButton.style.background = 'url(/images/v2/racing/header/stripy_bg.png) 0 0 repeat';
                    createTemplateButton.style.color = 'white';
                });

                createTemplateButtonDiv.appendChild(createTemplateButton);

                // Add button for removing selected template
                let removeTemplateButtonDiv = document.createElement('div');
                removeTemplateButtonDiv.style.paddingRight = '8px';

                buttonContainer.appendChild(removeTemplateButtonDiv);

                let removeTemplateButton = document.createElement('button');
                removeTemplateButton.textContent = 'X';
                removeTemplateButton.style.color = 'white';
                removeTemplateButton.onclick = removeSelectedTemplate;
                removeTemplateButton.style.background = 'url(/images/v2/racing/header/stripy_bg.png) 0 0 repeat';
                removeTemplateButton.style.cursor = 'pointer';
                removeTemplateButton.style.borderRadius = '5px';
                removeTemplateButton.style.transition = 'background-color 0.3s ease';

                // Add event listener to change background color on hover
                removeTemplateButtonDiv.addEventListener('mouseenter', function(event) {
                    removeTemplateButton.style.background = 'rgba(0, 191, 255, 0.5)';
                    removeTemplateButton.style.color = 'var(--default-color)';
                });

                // Restore original background color when mouse leaves
                removeTemplateButtonDiv.addEventListener('mouseleave', function() {
                    removeTemplateButton.style.background = 'url(/images/v2/racing/header/stripy_bg.png) 0 0 repeat';
                    removeTemplateButton.style.color = 'white';
                });

                removeTemplateButtonDiv.appendChild(removeTemplateButton);

                // Add button for editing noteRecogniser
                let changeNoteRecogniserButtonDiv = document.createElement('div');
                changeNoteRecogniserButtonDiv.style.width = '25px';
                changeNoteRecogniserButtonDiv.style.height = '21px';
                changeNoteRecogniserButtonDiv.style.background = 'url(/images/v2/racing/header/stripy_bg.png) 0 0 repeat';
                changeNoteRecogniserButtonDiv.style.borderRadius = '5px';

                buttonContainer.appendChild(changeNoteRecogniserButtonDiv);

                let changeNoteRecogniserButton = document.createElement('button');
                changeNoteRecogniserButton.textContent = ' ';
                changeNoteRecogniserButton.style.color = 'white';
                changeNoteRecogniserButton.onclick = function() {
                    // Get the input element
                    let input = document.querySelector('#carTemplatesContainer input');

                    // Get the selected template name
                    let selectedTemplateName = input.value;
                    changeTemplateNoteRecogniser(selectedTemplateName);
                };
                changeNoteRecogniserButton.style.background = 'url(/images/v2/racing/edit_car_name.svg) no-repeat';
                changeNoteRecogniserButton.style.backgroundPositionX = '2px';
                changeNoteRecogniserButton.style.backgroundPositionY = '1px';
                changeNoteRecogniserButton.style.width = '25px';
                changeNoteRecogniserButton.style.height = '18px';
                changeNoteRecogniserButton.style.cursor = 'pointer';
                changeNoteRecogniserButton.style.transition = 'background-color 0.3s ease';

                // Add event listener to change background color on hover
                changeNoteRecogniserButton.addEventListener('mouseenter', function(event) {
                    changeNoteRecogniserButton.style.backgroundPositionY = '-17px';
                    changeNoteRecogniserButtonDiv.style.background = 'rgba(0, 191, 255, 0.5)';
                });

                // Restore original background color when mouse leaves
                changeNoteRecogniserButton.addEventListener('mouseleave', function() {
                    changeNoteRecogniserButton.style.backgroundPositionY = '1px';
                    changeNoteRecogniserButton.style.color = 'white';
                    changeNoteRecogniserButtonDiv.style.background = 'url(/images/v2/racing/header/stripy_bg.png) 0 0 repeat';
                });

                changeNoteRecogniserButtonDiv.appendChild(changeNoteRecogniserButton);
            } else {
                buttonContainer = existingButtonContainer;
            }
        } else {
            // If the message container is not there yet, keep trying to find it
            setTimeout(() => {
                observeMessageElement();
            }, 100);
        }
    }

    // If the explanation is no longer wanted, remove it
    function removeExplanation() {
        showExplanation = false;
        localStorage.setItem('hf-car-templates-explanation', false);

        let existingTextDiv = document.getElementById('carScriptTextDiv');

        if (existingTextDiv) {
            existingTextDiv.remove();
        }
    }

    // Create the container and datalist for track names
    function createTrackNamesContainer(messageElement) {
        let existingDataListContainer = document.getElementById('trackNamesContainer');
        if (existingDataListContainer) {
            return;
        }

        let dataListContainer = document.createElement('div');
        dataListContainer.id = 'trackNamesContainer';
        dataListContainer.style.paddingRight = '16px';

        dataListContainer.style.display = 'flex';
        dataListContainer.style.alignItems = 'center';
        dataListContainer.style.paddingTop = '8px';
        let textContainer = document.createElement('p');
        textContainer.textContent = 'Track:';
        textContainer.style.fontWeight = 'bold';
        textContainer.style.paddingRight = '4px';

        dataListContainer.appendChild(textContainer);

        let input = document.createElement('input');
        input.style.border = '1px solid black';
        input.style.borderRadius = '5px';
        input.style.padding = '2px 4px';
        input.style.width = '100px';
        input.setAttribute('list', 'trackNames');

        // Add an input event listener
        input.addEventListener('input', function() {
            selectedTrack = input.value;
            observeTitleElements();
        });

        dataListContainer.appendChild(input);

        let dataList = document.createElement('datalist');
        dataList.id = 'trackNames';

        trackNames.forEach((track) => {
            let option = document.createElement('option');
            option.value = track;
            dataList.appendChild(option);
        });

        dataListContainer.appendChild(dataList);
        messageElement.appendChild(dataListContainer);
    }

    // Create the container and datalist for car names
    function createCarNamesContainer(messageElement) {
        let existingDataListContainer = document.getElementById('carNamesContainer');
        if (existingDataListContainer) {
            return;
        }

        let dataListContainer = document.createElement('div');
        dataListContainer.id = 'carNamesContainer';
        dataListContainer.style.paddingRight = '16px';
        dataListContainer.style.paddingTop = '8px';
        dataListContainer.style.display = 'flex';
        dataListContainer.style.alignItems = 'center';

        let textContainer = document.createElement('p');
        textContainer.textContent = 'Car:';
        textContainer.style.fontWeight = 'bold';
        textContainer.style.paddingRight = '4px';

        dataListContainer.appendChild(textContainer);

        let input = document.createElement('input');
        input.style.border = '1px solid black';
        input.style.borderRadius = '5px';
        input.style.padding = '2px 4px';
        input.setAttribute('list', 'carNames');

        // Add an input event listener
        input.addEventListener('input', function() {
            // Get the selected value from the input
            let selectedCar = input.value;
            observeTitleElements();
        });

        dataListContainer.appendChild(input);

        let dataList = document.createElement('datalist');
        dataList.id = 'carNames';

        carNames.forEach((car) => {
            let option = document.createElement('option');
            option.value = car;
            dataList.appendChild(option);
        });

        dataListContainer.appendChild(dataList);
        messageElement.appendChild(dataListContainer);
    }

    // Create the container and datalist for car templates
    function createCarTemplatesContainer(messageElement) {
        let existingDataListContainer = document.getElementById('carTemplatesContainer');
        if (existingDataListContainer) {
            return;
        }

        let dataListContainer = document.createElement('div');
        dataListContainer.id = 'carTemplatesContainer';
        dataListContainer.style.paddingRight = '8px';
        dataListContainer.style.paddingTop = '8px';
        dataListContainer.style.display = 'flex';
        dataListContainer.style.alignItems = 'center';

        let textContainer = document.createElement('p');
        textContainer.textContent = 'Template:';
        textContainer.style.fontWeight = 'bold';
        textContainer.style.paddingRight = '4px';

        dataListContainer.appendChild(textContainer);

        let input = document.createElement('input');
        input.style.border = '1px solid black';
        input.style.borderRadius = '5px';
        input.style.padding = '2px 4px';
        input.style.width = '189px';
        input.setAttribute('list', 'carTemplates');

        // Add an input event listener
        input.addEventListener('input', function() {
            selectedTemplate = input.value;
            changeUpgrades(selectedTemplate);
            observeTitleElements();
        });

        dataListContainer.appendChild(input);

        let dataList = document.createElement('datalist');
        dataList.id = 'carTemplates';

        carTemplates.forEach((template) => {
            let option = document.createElement('option');
            option.value = template.name;
            dataList.appendChild(option);
        });

        dataListContainer.appendChild(dataList);
        messageElement.appendChild(dataListContainer);

        changeCarNamesInput(selectedCar);
        writeCarInTemplates(selectedCar);
    }

    // Create a new template
    function createNewTemplate() {
        let type = '';
        let ratio = '';
        let turbo = '';

        if (carType == 'dirt') {
            type = 'D';
        } else if (carType == 'tarmac') {
            type = 'T';
        }

        if (carRatio == 'longRatio') {
            ratio = 'L';
        } else if (carRatio == 'shortRatio') {
            ratio = 'S';
        }

        if (carTurbo == 'turbo2') {
            turbo = '2';
        } else if (carTurbo == 'turbo3') {
            turbo = '3';
        }

        // Construct the new template name
        let newTemplateName = selectedTrack + ': ' + selectedCar + ' ' + type + ratio + turbo;

        // Check if the template already exists
        if (carTemplates.some(template => template.name === newTemplateName)) {
            alert('The template ' + newTemplateName + ' already exists, not adding again.');
            return; // Exit the function if the template already exists
        }

        if (selectedTrack == '') {
            alert('Please make sure to fill in a preferred track!');
            return;
        }

        if (selectedCar == '') {
            alert('Please make sure to fill in a preferred car!');
            return;
        }

        if (type == '') {
            alert('Please choose between dirt and tarmac!');
            return;
        }

        if (ratio == '') {
            alert('Please choose between long and short ratio!');
            return;
        }

        if (turbo == '') {
            alert('Please choose between turbo 2 and turbo 3!');
            return;
        }

        // Prompt the user to enter a note recogniser
        let noteRecogniser = prompt("Enter a note recogniser for the new template " + newTemplateName + ":");

        // Create an object representing the new template
        let newTemplate = {
            name: newTemplateName,
            noteRecogniser: noteRecogniser
        };

        carTemplates.push(newTemplate);
        carTemplates.sort();

        // Save updated carTemplates to localStorage
        localStorage.setItem('carTemplates', JSON.stringify(carTemplates));

        // Update the datalist options
        let dataList = document.getElementById('carTemplates');
        let option = document.createElement('option');
        option.value = newTemplateName;
        dataList.appendChild(option);

        writeCarInTemplates(newTemplateName);

        alert("Successfully added new template: " + newTemplateName + " with note recogniser " + noteRecogniser);
    }

    // Write the wanted car in templates to make it easier
    function writeCarInTemplates(selectedCar) {
        let input = document.querySelector('#carTemplatesContainer input');
        input.value = selectedCar;
    }

    // Remove an existing template
    function removeSelectedTemplate() {
        let selectedTemplateName = document.querySelector('#carTemplatesContainer input').value;

        // Find the index of the selected template in carTemplates
        let index = -1;
        for (let i = 0; i < carTemplates.length; i++) {
            if (carTemplates[i].name === selectedTemplateName) {
                index = i;
                break;
            }
        }

        // If the selected template is found, remove it
        if (index !== -1) {
            carTemplates.splice(index, 1);
            carTemplates.sort();

            // Save updated carTemplates to localStorage
            localStorage.setItem('carTemplates', JSON.stringify(carTemplates));

            // Update the datalist options
            let dataList = document.getElementById('carTemplates');
            let optionToRemove = dataList.querySelector(`option[value='${selectedTemplateName}']`);
            if (optionToRemove) {
                dataList.removeChild(optionToRemove);
                alert("Successfully removed template: " + selectedTemplateName);

                writeCarInTemplates(selectedCar);
            }
        }
    }

    // Change the upgrades based on a template
    function changeUpgrades(template) {
        let lastWord = selectedTemplate.split(' ').pop();

        let type = '';
        let ratio = '';
        let turbo = '';

        carUpgrades = [...overallUpgrades];

        if (lastWord.includes('D')) {
            type = 'dirt';
        } else if (lastWord.includes('T')) {
            type = 'tarmac';
        }

        if (lastWord.includes('S')) {
            ratio = 'shortRatio';
        } else if (lastWord.includes('L')) {
            ratio = 'longRatio';
        }

        if (lastWord.includes('2')) {
            turbo = 'turbo2';
        } else if (lastWord.includes('3')) {
            turbo = 'turbo3';
        }

        if (type == 'dirt' && ratio == 'shortRatio') {
            carUpgrades.push(...dirtShortRatioUpgrades);
        } else if (type == 'dirt' && ratio == 'longRatio') {
            carUpgrades.push(...dirtLongRatioUpgrades);
        } else if (type == 'tarmac' && ratio == 'shortRatio') {
            carUpgrades.push(...tarmacShortRatioUpgrades);
        } else if (type == 'tarmac' && ratio == 'longRatio') {
            carUpgrades.push(...tarmacLongRatioUpgrades);
        }

        if (turbo == 'turbo2') {
            carUpgrades.push(...turbo2Upgrades);
        } else if (turbo == 'turbo3') {
            carUpgrades.push(...turbo3Upgrades);
        }

        clickRadioButtons(type, ratio, turbo);
        changeCarNamesInput(selectedTemplate);
        changeTrackNamesInput(selectedTemplate);

        observeTitleElements();

        sessionStorage.setItem('selectedTemplate', selectedTemplate);
    }

    // Click radio buttons based on the wanted values
    function clickRadioButtons(typeValue, ratioValue, turboValue) {
        let typeRadioButton = document.querySelector(`input[value="${typeValue}"]`);
        let ratioRadioButton = document.querySelector(`input[value="${ratioValue}"]`);
        let turboRadioButton = document.querySelector(`input[value="${turboValue}"]`);

        if (typeRadioButton && ratioRadioButton && turboRadioButton) {
            typeRadioButton.checked = true;
            ratioRadioButton.checked = true;
            turboRadioButton.checked = true;

            // Trigger 'change' event on the radio buttons
            typeRadioButton.dispatchEvent(new Event('change'));
            ratioRadioButton.dispatchEvent(new Event('change'));
            turboRadioButton.dispatchEvent(new Event('change'));
        }
    }

    // Change car template input based on the wanted value
    function changeCarTemplatesInput(template) {
        let carTemplatesInput = document.querySelector('#carTemplatesContainer input');
        let carTemplatesDatalist = document.querySelector('#carTemplates');

        let matchedOption = null;

        // Loop through options in the datalist to find a match in the template
        for (let option of carTemplatesDatalist.options) {
            if (template.includes(option.value)) {
                matchedOption = option.value;
                break;
            }
        }

        if (matchedOption) {
            carTemplatesInput.value = matchedOption;
        } else {
            console.error('No matching option found in the template');
        }
    }

    // Change car name input based on the wanted value
    function changeCarNamesInput(template) {
        let carNamesInput = document.querySelector('#carNamesContainer input');
        let carNamesDatalist = document.querySelector('#carNames');

        let matchedOption = null;

        // Loop through options in the datalist to find a match in the template
        for (let option of carNamesDatalist.options) {
            if (template.includes(option.value)) {
                matchedOption = option.value;
                break;
            }
        }

        if (matchedOption) {
            carNamesInput.value = matchedOption;
            selectedCar = matchedOption;
        } else {
            console.error('No matching option found in the template');
        }
    }

    // Change track name input based on the wanted value
    function changeTrackNamesInput(template) {
        let trackNamesInput = document.querySelector('#trackNamesContainer input');
        let trackNamesDatalist = document.querySelector('#trackNames');

        let matchedOption = null;

        // Loop through options in the datalist to find a match in the template
        for (let option of trackNamesDatalist.options) {
            if (template.includes(option.value)) {
                matchedOption = option.value;
                break;
            }
        }

        if (matchedOption) {
            trackNamesInput.value = matchedOption;
            selectedTrack = matchedOption;
        } else {
            console.error('No matching option found in the template');
        }
    }

    // Create the radio buttons (type, turbo, ratio)
    function createRadioButtons(messageElement) {
        let existingRadioContainer = document.getElementById('carUpgradesRadioContainer');

        if (existingRadioContainer) {
            return;
        }

        let radioContainer = document.createElement('div');
        radioContainer.id = 'carUpgradesRadioContainer';
        radioContainer.style.display = 'flex';
        radioContainer.style.flexWrap = 'wrap';
        radioContainer.style.paddingTop = '10px';

        // Create Long/Short Ratio radio buttons
        let ratioContainer = document.createElement('div');
        ratioContainer.style.paddingRight = '16px';
        ratioContainer.style.paddingTop = '16px';
        ratioContainer.style.display = 'flex';
        createRadioButton(ratioContainer, 'longRatio', 'Long Ratio', 'ratio', 'left');
        createRadioButton(ratioContainer, 'shortRatio', 'Short Ratio', 'ratio', 'right');
        radioContainer.appendChild(ratioContainer);

        // Create Turbo 2/Turbo 3 radio buttons
        let turboContainer = document.createElement('div');
        turboContainer.style.paddingRight = '16px';
        turboContainer.style.paddingTop = '16px';
        turboContainer.style.display = 'flex';
        createRadioButton(turboContainer, 'turbo2', 'Turbo 2', 'turbo', 'left');
        createRadioButton(turboContainer, 'turbo3', 'Turbo 3', 'turbo', 'right');
        radioContainer.appendChild(turboContainer)

        // Create Dirt/Tarmac radio buttons
        let typeContainer = document.createElement('div');
        typeContainer.style.paddingRight = '16px';
        typeContainer.style.paddingTop = '16px';
        typeContainer.style.display = 'flex';
        createRadioButton(typeContainer, 'dirt', 'Dirt', 'type', 'left');
        createRadioButton(typeContainer, 'tarmac', 'Tarmac', 'type', 'right');
        radioContainer.appendChild(typeContainer);

        createCheckboxes(radioContainer);

        messageElement.appendChild(radioContainer);

        // Add event listener to update additional text based on radio buttons
        let radioOptions = document.querySelectorAll('.carScriptRadioButton');
        radioOptions.forEach(radio => {
            radio.addEventListener('change', function () {
                updateUpgradeBackgrounds();
                readRadioButtons();
                observeTitleElements();
            });
        });
    }

    // Create a single radio button couple
    function createRadioButton(parentElement, value, labelText, name, side) {
        let radioDiv = document.createElement('div');
        radioDiv.style.display = 'block';

        let radioButton = document.createElement('input');
        radioButton.type = 'radio';
        radioButton.name = name;
        radioButton.value = value;
        radioButton.className = 'carScriptRadioButton';
        radioButton.id = name;
        radioButton.style.display = 'none';

        let labelDiv = document.createElement('div');
        let label = document.createElement('label');
        label.id = name + '-label';
        label.textContent = labelText;
        label.style.color = 'white';
        label.style.padding = '6px 10px';
        label.style.background = 'url(/images/v2/racing/header/stripy_bg.png) 0 0 repeat';
        label.style.cursor = 'pointer';

        if (side == 'left') {
            label.style.borderBottomLeftRadius = '5px';
            label.style.borderTopLeftRadius = '5px';
        } else if (side == 'right') {
            label.style.borderBottomRightRadius = '5px';
            label.style.borderTopRightRadius = '5px';
        }

        // Add click event listener to the label
        label.addEventListener('click', function () {
            radioButton.click(); // Trigger the associated radio button's click event
            observeTitleElements();
        });

        radioDiv.appendChild(radioButton);
        radioDiv.appendChild(label);

        parentElement.appendChild(radioDiv);
    }

    // Change upgrades based on which radio buttons are checked
    function readRadioButtons() {
        let radioOptions = document.querySelectorAll('.carScriptRadioButton');

        // Set car upgrades to default upgrades
        carUpgrades = [...overallUpgrades];

        radioOptions.forEach(radio => {
            if (radio.checked) {
                switch (radio.name) {
                    case 'type':
                        carType = radio.value;
                        break;
                    case 'ratio':
                        carRatio = radio.value;
                        break;
                    case 'turbo':
                        carTurbo = radio.value;
                        break;
                }
            }
        });

        if (carType == 'dirt' && carRatio == 'shortRatio') {
            carUpgrades.push(...dirtShortRatioUpgrades);
        } else if (carType == 'dirt' && carRatio == 'longRatio') {
            carUpgrades.push(...dirtLongRatioUpgrades);
        } else if (carType == 'tarmac' && carRatio == 'shortRatio') {
            carUpgrades.push(...tarmacShortRatioUpgrades);
        } else if (carType == 'tarmac' && carRatio == 'longRatio') {
            carUpgrades.push(...tarmacLongRatioUpgrades);
        }

        if (carTurbo == 'turbo2') {
            carUpgrades.push(...turbo2Upgrades);
        } else if (carTurbo == 'turbo3') {
            carUpgrades.push(...turbo3Upgrades);
        }
    }

    // Create checkboxes to show or don't show certain background colours
    function createCheckboxes(messageElement) {
        // If already there, don't add again
        let existingCheckboxDiv = document.getElementById('checkboxDiv');
        if (existingCheckboxDiv) {
            return;
        }

        let checkboxDiv = document.createElement('div');
        checkboxDiv.id = 'checkboxDiv';
        checkboxDiv.style.display = 'flex';
        checkboxDiv.style.paddingTop = '14px';
        checkboxDiv.style.paddingLeft = '16px';

        let textDiv = document.createElement('div');
        textDiv.textContent = 'Show background colors:';
        textDiv.style.fontWeight = 'bold';
        textDiv.style.alignSelf = 'center';
        textDiv.style.paddingRight = '4px';

        checkboxDiv.appendChild(textDiv);
        createCheckbox('green', checkboxDiv);
        createCheckbox('blue', checkboxDiv);
        createCheckbox('red', checkboxDiv);

        messageElement.appendChild(checkboxDiv);

        let checkboxOptions = document.querySelectorAll('.carScriptCheckbox');
        checkboxOptions.forEach(checkbox => {
            checkbox.addEventListener('change', function () {
                checkLabels();
                observeTitleElements();
            });
        });
    }

    // Create a single checkbox
    function createCheckbox(colour, checkboxDiv) {
        const checkbox = document.createElement('input');
        checkbox.type = 'checkbox';
        checkbox.id = colour + '-checkbox';
        checkbox.className = 'carScriptCheckbox';
        checkbox.style.display = 'none';

        let labelDiv = document.createElement('div');
        labelDiv.style.paddingRight = '4px';

        const label = document.createElement('label');
        label.htmlFor = checkbox.id;
        label.style.width = '20px';
        label.style.height = '20px';
        label.style.display = 'inline-block';
        label.style.cursor = 'pointer';
        label.style.textAlign = 'center';
        label.style.lineHeight = '20px';
        label.style.fontSize = '14px';
        label.style.verticalAlign = 'middle';
        label.style.borderRadius = '5px';

        if (colour == 'red') {
            label.style.background = 'rgba(247,103,7,0.5)';
            if (redColor === true || redColor === 'true') {
                checkbox.checked = true;
                label.textContent = 'X';
            } else {
                checkbox.checked = false;
                label.textContent = '';
            }
        } else if (colour == 'blue') {
            label.style.background = 'rgba(20, 113, 151, 0.5)';
            if (blueColor === true || blueColor === 'true') {
                checkbox.checked = true;
                label.textContent = 'X';
            } else {
                checkbox.checked = false;
                label.textContent = '';
            }
        } else if (colour == 'green') {
            label.style.background = 'rgba(116,184,22,0.5)';
            if (greenColor === true || greenColor === 'true') {
                checkbox.checked = true;
                label.textContent = 'X';
            } else {
                checkbox.checked = false;
                label.textContent = '';
            }
        }

        // Add click event listener to the label
        label.addEventListener('click', function (event) {
            event.preventDefault(); // Prevent default label click behavior
            checkbox.checked = !checkbox.checked; // Toggle the 'checked' state of the associated checkbox
            checkbox.dispatchEvent(new Event('change')); // Dispatch a change event on the checkbox
            checkLabels(); // Update labels after toggling the checkbox
            observeTitleElements();
        });

        labelDiv.appendChild(checkbox);
        labelDiv.appendChild(label);
        checkboxDiv.appendChild(labelDiv);
    }

    // Keep checking the labels to see if any backgrounds need to be turned off
    function checkLabels() {
        let checkboxOptions = document.querySelectorAll('.carScriptCheckbox');

        checkboxOptions.forEach(checkbox => {
            let label = checkbox.nextElementSibling;

            if (checkbox.checked) {
                label.textContent = 'X';
                // Update color variables based on checkbox state
                if (checkbox.id === 'red-checkbox') {
                    redColor = true;
                    localStorage.setItem('hf-car-templates-red-color', 'true');
                } else if (checkbox.id === 'blue-checkbox') {
                    blueColor = true;
                    localStorage.setItem('hf-car-templates-blue-color', 'true');
                } else if (checkbox.id === 'green-checkbox') {
                    greenColor = true;
                    localStorage.setItem('hf-car-templates-green-color', 'true');
                }
            } else {
                label.textContent = '';
                // Update color variables based on checkbox state
                if (checkbox.id === 'red-checkbox') {
                    redColor = false;
                    localStorage.setItem('hf-car-templates-red-color', 'false');
                } else if (checkbox.id === 'blue-checkbox') {
                    blueColor = false;
                    localStorage.setItem('hf-car-templates-blue-color', 'false');
                } else if (checkbox.id === 'green-checkbox') {
                    greenColor = false;
                    localStorage.setItem('hf-car-templates-green-color', 'false');
                }
            }
        });
    }

    // Start observing the title elements until you found the racing wrap
    function observeTitleElements() {
        const pmItemsWraps = document.querySelectorAll('.pm-items-wrap');

        if (pmItemsWraps) {
            pmItemsWraps.forEach(function(pmItemsWrap) {

                // Find all title elements (car upgrades)
                const titleElements = pmItemsWrap.querySelectorAll('.title.t-overflow');

                titleElements.forEach(function(titleElement) {
                    highlightTitleContents(titleElement, pmItemsWrap);
                });
            });
        }
    }

    // Highlight upgrade titles based on the car upgrades
    function highlightTitleContents(titleElement, pmItemsWrap) {
        const titleText = titleElement.textContent.trim();

        // Check if not already included and if valid option
        if (carUpgrades.includes(titleText)) {
            loggedTitleElements.add(titleText); // Add to the set to avoid duplicate logging
            changeBackgroundColors(titleElement);
        } else {
            removeBackgroundColors(titleElement);
        }
    }

    // Remove previous background colours if upgrades are no longer wanted
    function removeBackgroundColors(titleElement) {
        const bgWrap = titleElement.closest('.bg-wrap');
        if (bgWrap) {
            // Check if the "info" div contains the specific text
            const infoDiv = bgWrap.querySelector('.info');
            if (infoDiv && infoDiv.textContent.trim() === 'Upgrade is already fitted to this car') {
                if (redColor === 'true' || redColor === true) {
                    bgWrap.style.background = 'rgba(247,103,7,0.15)'; // Red colour
                } else {
                    bgWrap.style.background = '';
                }
            } else {
                bgWrap.style.background = '';
            }
        }

        const boxWrap = titleElement.closest('.box-wrap');
        if (boxWrap) {
            const parentElement = boxWrap.parentElement; // Get the parent of box-wrap

            // Check if the "info" div contains the specific text
            const infoDiv = boxWrap.querySelector('.info');
            if (infoDiv && infoDiv.textContent.trim() === 'Upgrade is already fitted to this car') {
                if (redColor === 'true' || redColor === true) {
                    parentElement.style.background = 'rgba(247,103,7,0.15)'; // Red colour
                } else {
                    parentElement.style.background = '';
                }
            } else {
                parentElement.style.background = '';
            }
        }
    }

    // Change background colours for wanted  upgrades
    function changeBackgroundColors(titleElement) {
        const bgWrap = titleElement.closest('.bg-wrap');
        if (bgWrap) {

            // Check if the "info" div contains the specific text
            const infoDiv = bgWrap.querySelector('.info');
            if (infoDiv && infoDiv.textContent.trim() === 'Upgrade is already fitted to this car') {
                if (greenColor === 'true' || greenColor === true) {
                    bgWrap.style.background = 'rgba(116,184,22,0.15)'; // Green background
                } else {
                    bgWrap.style.background = '';
                }
            } else {
                if (blueColor === 'true' || blueColor === true) {
                    bgWrap.style.background = 'rgba(20, 113, 151, 0.15'; // Blue background
                } else {
                    bgWrap.style.background = '';
                }
            }
        }

        const boxWrap = titleElement.closest('.box-wrap');
        if (boxWrap) {
            const parentElement = boxWrap.parentElement; // Get the parent of box-wrap

            // Check if the "info" div contains the specific text
            const infoDiv = boxWrap.querySelector('.info');
            if (infoDiv && infoDiv.textContent.trim() === 'Upgrade is already fitted to this car') {
                if (greenColor === 'true' || greenColor === true) {
                    parentElement.style.background = 'rgba(116,184,22,0.15)'; // Green background
                } else {
                    parentElement.style.background = '';
                }
            } else {
                if (blueColor === 'true' || blueColor === true) {
                    parentElement.style.background = 'rgba(20, 113, 151, 0.15)'; // Blue background
                } else {
                    parentElement.style.background = '';
                }
            }
        }
    }

    // Change background colours based on radio buttons
    function updateUpgradeBackgrounds() {
        let radioOptions = document.querySelectorAll('.carScriptRadioButton');
        let selectedOptions = [];

        radioOptions.forEach(radio => {
            let container = radio.parentElement;

            if (radio.checked) {
                selectedOptions.push(radio.value);

                // Set the background color of all siblings to green
                Array.from(container.children).forEach(sibling => {
                    if (sibling !== radio) {
                        sibling.style.background = 'rgba(0, 191, 255, 0.5)';
                        sibling.style.color = 'var(--default-color)';
                    }
                });
            } else {
                // Reset the background color of all siblings to black
                Array.from(container.children).forEach(sibling => {
                    sibling.style.background = 'url(/images/v2/racing/header/stripy_bg.png) 0 0 repeat';
                    sibling.style.color = 'white';
                });
            }
        });
    }


    // Check if the user clicks 'Official Race' or 'Custom Race'
    function checkButtons() {
        let headerWrap = document.querySelector('.header-wrap');

        if (headerWrap) {
            document.querySelector('a[tab-value="race"]').addEventListener('click', function(event) {
                officialRace();
            });

            document.querySelector('a[tab-value="customrace"]').addEventListener('click', function(event) {
                customRace();
            });

        }
    }

    // When the user clicks 'Custom Race', check if they create or join a race
    function customRace() {
        const createRaceButtons = document.querySelectorAll('.btn-wrap.silver.c-pointer a.btn-action-tab');
        const joinRaceButtons = document.querySelectorAll('.join-wrap a.link.btn-action-tab');

        if (createRaceButtons && joinRaceButtons) {
            document.addEventListener('click', function(event) {
                const target = event.target;

                // Check if the clicked element is a "create race" button
                if (target.matches('.btn-wrap.silver.c-pointer a.btn-action-tab')) {
                    createCustomRace();
                }

                // Check if the clicked element is a "join race" button
                if (target.matches('.join-wrap a.link.btn-action-tab') || target.closest('.join-wrap a.link.btn-action-tab') || target.classList.contains('btn-action-form')) {

                    // Find the closest .active-row ancestor of the clicked button
                    const successRow = target.closest('.active-row');
                    if (successRow) {
                        // Find the track name within the success row element
                        const trackElement = successRow.querySelector('.track');
                        if (trackElement) {
                            let trackText = trackElement.textContent.trim();
                            chosenTrack = trackText.split('(')[0].trim();

                            let raceName = trackElement.querySelector('.hf-race-name');
                            if (raceName) {
                                let textContent = raceName.textContent;
                                chosenTrack = chosenTrack.replace(textContent, '').trim();
                            }

                            possibleTemplates = [];

                            for (let template of carTemplates) {
                                if (chosenTrack === template.name.split(':')[0].trim()) {
                                    possibleTemplates.push(template);
                                }
                            }

                            setTimeout(function() {
                                highlightSuggestedCar(possibleTemplates, chosenTrack);
                            }, 100);
                        } else {
                            setTimeout(customRace, 100)
                        }
                    } else {
                        console.error('[Racing: Car Templates] Something went wrong whilst trying to fetch the track name');
                    }
                }
            });
        } else {
            setTimeout(customRace, 100);
        }
    }

    // If the user creates a custom race, remember the track they choose
    function createCustomRace() {
        // Find the button by its class name
        let createButton = document.querySelector('[name="createCustomRace"]');

        if (createButton) {
            createButton.addEventListener('click', function() {
                let selectMenuStatus = document.querySelector('.ui-selectmenu');
                let mobileSelectMenu = document.querySelector('#select-racing-track');

                if (selectMenuStatus) {
                    chosenTrack = selectMenuStatus.textContent.trim();
                    possibleTemplates = [];

                    for (let template of carTemplates) {
                        if (template.name.includes(chosenTrack)) {
                            possibleTemplates.push(template);
                        }
                    }

                    setTimeout(function() {
                        highlightSuggestedCar(possibleTemplates, chosenTrack);
                    }, 100);
                } else if (mobileSelectMenu) {
                    let selectedOption = mobileSelectMenu.options[mobileSelectMenu.selectedIndex];
                    chosenTrack = selectedOption.textContent;

                    possibleTemplates = [];

                    for (let template of carTemplates) {
                        if (template.name.includes(chosenTrack)) {
                            possibleTemplates.push(template);
                        }
                    }

                    setTimeout(function() {
                        highlightSuggestedCar(possibleTemplates, chosenTrack);
                    }, 300);

                } else {
                    console.error('[Racing: Car Templates] Something went wrong whilst trying to fetch the track name');
                }
            });
        } else {
            setTimeout(createCustomRace, 100);
        }
    }

    // When the user clicks 'Official Race'
    function officialRace() {
        let joinButton = document.querySelector('a[href*="tab=race"][href*="section=changeRacingCar"][href*="step=getInRace"]');

        if (joinButton) {
            joinButton.addEventListener('click', function() {
                findOfficialTrack();
            });
        } else {
            setTimeout(officialRace, 100);
        }
    }

    // When the user joins an official race, remember the track they choose
    function findOfficialTrack() {
        let enlistWrap = document.querySelector('.enlist-wrap');

        if (enlistWrap) {
            let trackElement = document.querySelector('.enlisted-btn-wrap').textContent;

            if (trackElement) {
                chosenTrack = trackElement.split(' - Official race')[0].trim();

                possibleTemplates = [];

                for (let template of carTemplates) {
                    if (chosenTrack === template.name.split(':')[0].trim()) {
                        possibleTemplates.push(template);
                    }
                }

                setTimeout(function() {
                    highlightSuggestedCar(possibleTemplates, chosenTrack);
                }, 100);
            } else {
                console.error('[Racing: Car Templates] Something went wrong whilst trying to fetch the track name');
            }

        } else {
            setTimeout(findOfficialTrack, 100);
        }
    }

    // Display and highlight the suggested car based on the track and templates
    function highlightSuggestedCar(templates, chosenTrack) {
        if (chosenTrack == 'ENLIST ANOTHER CAR' || chosenTrack == '') {
            chosenTrack = 'unknown track';
            return;
        }

        let racingInfoWrap = document.querySelector('.racing-info-wrap');

        if (racingInfoWrap) {
            racingInfoWrap.style.paddingTop = '10px';

            let existingContainer = document.getElementById('hf-suggested-car-templates');
            if (existingContainer) {
                existingContainer.remove();
            }

            let container = document.createElement('div');

            container.id = 'hf-suggested-car-templates';
            container.style.background = 'linear-gradient(180deg, rgba(20, 113, 151, 0.5), rgba(20, 113, 151, 0.15))';
            container.style.display = 'flex';
            container.style.flexWrap = 'wrap';

            racingInfoWrap.appendChild(container);

            let textDivContainer = document.createElement('div');
            textDivContainer.style.padding = '8px';
            textDivContainer.style.borderRadius = '5px';

            let textDiv = document.createElement('p');
            textDiv.textContent = 'Suggested car template(s) for ' + chosenTrack + ':';
            textDiv.style.fontWeight = 'bold';
            textDiv.style.paddingBottom = '4px';

            textDivContainer.appendChild(textDiv);
            container.appendChild(textDivContainer);

            if (templates !== '') {

                templates.forEach(template => {
                    let templateName = template.name;
                    let noteRecogniser = template.noteRecogniser;

                    let index = templateName.indexOf(':');
                    if (index !== -1) {
                        let suggestedCar = templateName.substring(index + 1).trim();
                        let modelWithoutClass = suggestedCar.split(' ').slice(0, -1).join(' '); // Remove last word

                        let existingParagraph = document.getElementById('hf-racing-' + suggestedCar);

                        if (existingParagraph) {
                            existingParagraph.remove();
                        }

                        let paragraphContainer = document.createElement('div');
                        paragraphContainer.id = 'hf-racing-' + suggestedCar;
                        paragraphContainer.style.display = 'flex';
                        paragraphContainer.style.fontWeight = 'normal';

                        let paragraph = document.createElement('p');
                        paragraph.textContent = '\u2022 ' + suggestedCar + ' (' + noteRecogniser + ')';
                        paragraph.style.alignSelf = 'center';

                        paragraphContainer.appendChild(paragraph);

                        // Add button for editing noteRecogniser
                        let changeNoteRecogniserButton = document.createElement('button');
                        changeNoteRecogniserButton.textContent = ' ';
                        changeNoteRecogniserButton.style.color = 'white';
                        changeNoteRecogniserButton.onclick = function() {
                            changeTemplateNoteRecogniser(templateName, templates, chosenTrack);
                        };
                        changeNoteRecogniserButton.style.background = 'url(/images/v2/racing/edit_car_name.svg) no-repeat';
                        changeNoteRecogniserButton.style.width = '18px';
                        changeNoteRecogniserButton.style.height = '18px';
                        changeNoteRecogniserButton.style.cursor = 'pointer';
                        changeNoteRecogniserButton.style.transition = 'background-color 0.3s ease';
                        changeNoteRecogniserButton.style.marginTop = '6px';

                        // Add event listener to change background color on hover
                        changeNoteRecogniserButton.addEventListener('mouseenter', function(event) {
                            changeNoteRecogniserButton.style.backgroundPositionY = '-18px';
                        });

                        // Restore original background color when mouse leaves
                        changeNoteRecogniserButton.addEventListener('mouseleave', function() {
                            changeNoteRecogniserButton.style.backgroundPositionY = '0px';
                            changeNoteRecogniserButton.style.color = 'white';
                        });

                        paragraphContainer.appendChild(changeNoteRecogniserButton);

                        textDivContainer.appendChild(paragraphContainer);

                        // Loop through all the li elements
                        document.querySelectorAll('li').forEach(li => {
                            // Check if the list item contains modelWithoutClass
                            if (li.textContent.includes(modelWithoutClass)) {
                                if (li.textContent.includes(noteRecogniser)) {
                                    li.style.background = 'rgba(20, 113, 151, 0.15)';

                                    let enlistInfoWrap = li.querySelector('.enlist-info-wrap');
                                    enlistInfoWrap.style.background = 'rgba(20, 113, 151, 0.15';

                                    let enlistCar = li.querySelector('.enlist-car');
                                    enlistCar.style.background = 'rgba(20, 113, 151, 0.15';

                                    // Get the parent ul element
                                    let parentUl = li.parentNode;

                                    // Append li as first child
                                    parentUl.insertBefore(li, parentUl.firstChild);
                                }
                            } else {
                                li.style.background = '';

                                let enlistInfoWrap = li.querySelector('.enlist-info-wrap');

                                if (enlistInfoWrap) {
                                    enlistInfoWrap.style.background = '';
                                }

                                let enlistCar = li.querySelector('.enlist-car');

                                if (enlistCar) {
                                    enlistCar.style.background = '';
                                }

                            }
                        });
                    }
                });
            } else {
                let paragraph = document.createElement('p');
                paragraph.textContent = 'No template found for this track';
                paragraph.style.fontWeight = 'normal';
                paragraph.style.paddingTop = '4px';
            }
        } else {
            setTimeout(function() {
                highlightSuggestedCar(templates, chosenTrack);
            }, 100);
        }
    }

    // Deprecated, but leaving this here in case I do need it later
    function manuallyAddTrackName() {
        let existingContainer = document.getElementById('hf-racing-track-error');

        if (existingContainer) {
            return;
        }

        let enlistList = document.querySelector('.enlist-list');

        if (!enlistList) {
            setTimeout(manuallyAddTrackName, 100);
        }

        let delimiterElement = document.querySelector('.delimiter-999.m-top10');

        let container = document.createElement('div');
        container.id = 'hf-racing-track-error';
        container.style.paddingTop = '4px';

        let infoMsgDiv = document.createElement('div');
        infoMsgDiv.className = 'info-msg-cont border-round m-top10 factionMessageDiv';
        infoMsgDiv.style.background = 'red';

        // Create the inner div for the message content
        let innerDiv = document.createElement('div');
        innerDiv.className = 'info-msg border-round';

        // Create the icon element
        let iconElement = document.createElement('i');
        iconElement.className = 'info-icon';

        // Create the message container div
        let msgContainer = document.createElement('div');
        msgContainer.className = 'delimiter';

        // Create the message element
        let messageElement = document.createElement('div');
        messageElement.className = 'msg right-round';
        messageElement.setAttribute('role', 'alert');
        messageElement.setAttribute('aria-live', 'assertive');

        let textElement = document.createElement('div');
        textElement.className = 'factionTextElement';
        textElement.textContent = 'There was an error fetching the track name. Click here to manually insert track Name';
        textElement.style.color = 'var(--default-red-color)';
        textElement.style.textDecoration = 'underline';

        textElement.addEventListener('click', function() {
            let manualTrack = prompt('Please manually enter the track name: ');

            if (manualTrack) {
                chosenTrack = manualTrack;
                container.remove();
                possibleTemplates = [];

                for (let template of carTemplates) {
                    if (chosenTrack.toLowerCase() === template.name.split(':')[0].trim().toLowerCase()) {
                        possibleTemplates.push(template);
                    }
                }

                setTimeout(function() {
                    highlightSuggestedCar(possibleTemplates, chosenTrack);
                }, 100);
            }
        });

        messageElement.appendChild(textElement);

        // Append elements to construct the message structure
        msgContainer.appendChild(messageElement);
        innerDiv.appendChild(iconElement);
        innerDiv.appendChild(msgContainer);
        infoMsgDiv.appendChild(innerDiv);
        container.appendChild(infoMsgDiv);
        delimiterElement.parentNode.insertBefore(container, delimiterElement);

    }

    // Function to handle the button click event
    function changeTemplateNoteRecogniser(selectedTemplateName, templates, chosenTrack) {
        // Find the corresponding template object
        let selectedTemplate = carTemplates.find(template => template.name === selectedTemplateName);

        // If template found, proceed
        if (selectedTemplate) {
            // Prompt with the current note recogniser pre-filled
            let newNoteRecogniser = prompt('Change the note recogniser for the template ' + selectedTemplate.name, selectedTemplate.noteRecogniser);

            // If user enters something and clicks OK
            if (newNoteRecogniser !== null) {
                // Update the note recogniser of the selected template
                selectedTemplate.noteRecogniser = newNoteRecogniser;

                // Save updated carTemplates to localStorage
                localStorage.setItem('carTemplates', JSON.stringify(carTemplates));

                // Alert the user
                alert("Note recogniser updated for " + selectedTemplateName);
            }

            if (templates && chosenTrack) {
                setTimeout(function() {
                    highlightSuggestedCar(templates, chosenTrack);
                }, 100);
            }
        } else {
            alert("No template selected.");
        }
    }

    // Initial script setup
    observeTitleElements();
    observeMessageElement();
    checkButtons();

    // Attach click event listener
    document.body.addEventListener('click', handleButtonClick);

    // Reconnect observer when a button is clicked
    function handleButtonClick(event) {
        const clickedElement = event.target;
        const isAnchor = clickedElement.tagName === 'a' || clickedElement.closest('a') !== null;

        if (isAnchor) {
            observeTitleElements();
            observeMessageElement();
            checkButtons();
            setTimeout(function() {
                if (clickedElement.classList.contains('page-number')) {
                    highlightSuggestedCar(possibleTemplates, chosenTrack);
                }
            }, 200);

            // Find the closest parent <li> element of the clicked <a> element
            const listItem = event.target.closest('li');

            // Check if listItem exists
            if (listItem) {
                const carNameSpan = listItem.querySelector('[class^="model-car-name-"]');

                if (carNameSpan) {
                    chosenCar = carNameSpan.textContent.trim();
                    addedCarNotes = false;
                }
            }
        }
    }

    let carChanges = {
        'Mitsubishi Evo X': 'Yotsuhada EVX',
        'Volvo 850': 'Stålhög 860',
        'Alfa Romeo 156': 'Alpha Milano 156',
        'BMW X5': 'Bavaria X5',
        'Seat Leon Cupra': 'Coche Basurero',
        'Vauxhall Astra GSI': 'Bedford Nova',
        'Volkswagen Golf GTI': 'Verpestung Sport',
        'Audi S3': 'Echo S3',
        'Ford Focus RS': 'Volt RS',
        'Honda s2': 'Edomondo S2',
        'Mini Cooper S': 'Nano Cavalier',
        'Sierra Cosworth': 'Colina Tanprice',
        'Lotus Exige': 'Cosmos EX',
        'Vauxhall Corsa': 'Bedford Racer',
        'Porsche 911 GT3': 'Sturmfahrt 111',
        'Subaru Impreza STI': 'Tsubasa Impressor',
        'TVR Sagaris': 'Wington GGU',
        'Aston Martin One-77': 'Weston Marlin 177',
        'Audi R8': 'Echo R8',
        'Bugatti Veyron': 'Stormatti Casteon',
        'Ferrari 458': 'Lolo 458',
        'Lamborghini Gallardo': 'Lambrini Torobravo',
        'Lexus LFA': 'Veloria LFA',
        'Mercedes SLR': 'Mercia SLR',
        'Nissan GT-R': 'Zaibatsu GT-R',
        'Honda Civic': 'Edomondo Localé',
        'Honda NSX': 'Edomondo NSX',
        'Audi TT Quattro': 'Echo Quadrato',
        'BMW M5': 'Bavaria M5',
        'BMW Z8': 'Bavaria Z8',
        'Chevrolet Corvette Z06': 'Chevalier CZ06',
        'Dodge Charger': 'Dart Rampager',
        'Pontiac Firebird': 'Knight Firebrand',
        'Ford GT40': 'Volt GT',
        'Hummer H3': 'Invader H3',
        'Audi S4': 'Echo S4',
        'Honda Integra R': 'Edomondo IR',
        'Honda Accord': 'Edomondo ACD',
        'Toyota MR2': 'Tabata RM2',
        'Volkswagen Beetle': 'Verpestung Insecta',
        'Chevrolet Cavalier': 'Chevalier CVR',
        'Ford Mustang': 'Volt MNG',
        'Reliant Robin': 'Trident',
        'Holden SS': 'Oceania SS',
        'Citroen Saxo': 'Limoen Saxon',
        'Classic Mini': 'Nano Pioneer',
        'Fiat Punto': 'Vita Bravo',
        'Nissan Micra': 'Zaibatsu Macro',
        'Peugeot 106': 'Çagoutte 10-6',
        'Renault Clio': 'Papani Colé',
    };

    // Function to replace one set of car names with another set in the templates
    function updateCarNames(oldName, newName) {
        let matchingTemplates = carTemplates.filter(template => {
            let templateName = template.name.toLowerCase();
            let searchTerm = oldName.toLowerCase();
            return templateName.includes(searchTerm);
        });

        matchingTemplates.forEach(template => {
            template.name = template.name.replace(oldName, newName);
        });
    }

    function adaptToNewCars() {
        settings = 'new';
        localStorage.setItem('hf-car-settings', settings);

        Object.entries(carChanges).forEach(([oldName, newName]) => {
            updateCarNames(oldName, newName);
        });

        carTemplates.sort(); // Order alphabetically for easiness

        localStorage.setItem('carTemplates', JSON.stringify(carTemplates)); // Set the default templates in storage

        location.reload();
    }

    function revertToOldCars() {
        settings = 'old';
        localStorage.setItem('hf-car-settings', settings);

        Object.entries(carChanges).forEach(([oldName, newName]) => {
            if (oldName === 'Volt GT40') {
                oldName = 'Volt GT';
            }

            updateCarNames(newName, oldName);
        });

        carTemplates.sort(); // Order alphabetically for easiness

        localStorage.setItem('carTemplates', JSON.stringify(carTemplates)); // Set the default templates in storage

        location.reload();
    }

    function addAdaptRevert() {
        let linksElement = document.getElementById('top-page-links-list');
        if (!linksElement) {
            setTimeout(addAdaptRevert, 100);
            return;
        }

        linksElement.style.display = 'flex';
        linksElement.style.justifyContent = 'flex-end';
        linksElement.style.alignItems = 'center';

        let span = document.createElement('span');
        span.style.paddingRight = '8px';
        span.style.cursor = 'pointer';
        span.style.color = 'var(--default-blue-color)';

        linksElement.insertBefore(span, linksElement.children[0]);

        if (settings === 'old') {
            span.textContent = 'Adapt to new cars';
            span.onclick = adaptToNewCars;
        } else if (settings === 'new') {
            span.textContent = 'Revert to old cars';
            span.onclick = revertToOldCars;
        }
    }

    if (showAdaptRevert === true) {
        addAdaptRevert();
    }


})();