"use strict";

// worldScripts.world_builder

this.name = "world_builder";

this._currentMenuKey    = null;
this._currentBackground = null;
this._propertyToChange  = null;

/* ========================================================
	ALL THE PROPERTY-SPECIIC HELP MESSAGES
=========================================================== */

this._messageTexts = function () {
    // Centralized message storage
    const messages = {
        name: "Enter a new value for 'name'.\n" +
              "- A text string naming the planet.\n" +
              "- Example: 'Alpha Centauri', 'Tionisla'.",

        economy: "Enter a new value for 'economy'.\n" +
                 "- Valid range: 0 to 7 (integer).\n" +
                 "- Represents the economic type of the system.\n" +
                 "- Default descriptions, if economy_description is not set,\n" +
                 "- are in descriptions.plist, not in planetinfo.plist:\n" +
                 "- 0: Rich Industrial\n" +
                 "- 1: Average Industrial\n" +
                 "- 2: Poor Industrial\n" +
                 "- 3: Mainly Industrial\n" +
                 "- 4: Mainly Agricultural\n" +
                 "- 5: Rich Agricultural\n" +
                 "- 6: Average Agricultural\n" +
                 "- 7: Poor Agricultural",

        economy_description: "Enter a new value for 'economy_description'.\n" +
                             "- A free-form text string describing the economy.\n" +
                             "- Example: 'Rich Industrial', 'Average Agricultural'.",

        government: "Enter a new value for 'government'.\n" +
                    "- Valid range: 0 to 7 (integer).\n" +
                    "- Represents the government type of the system.\n" +
                    "- Example: 0 = Anarchy, 7 = Corporate State.\n" +
                    "- Default descriptions, if government_description is not set,\n" +
                    "- are in descriptions.plist, not in planetinfo.plist:\n" +
                    "- 0: Anarchy\n" +
                    "- 1: Feudal\n" +
                    "- 2: Multi-Government\n" +
                    "- 3: Dictatorship\n" +
                    "- 4: Communist\n" +
                    "- 5: Confederacy\n" +
                    "- 6: Democracy\n" +
                    "- 7: Corporate State",

        government_description: "Enter a new value for 'government_description'.\n" +
                                "- A free-form text string describing the government.\n" +
                                "- Example: 'Corporate State', 'Feudal'.",

        techlevel: "Enter a new value for 'techlevel'.\n" +
                   "- Valid range: 0 to 15 (integer).\n" +
                   "- Represents the technological sophistication of the planet.\n" +
                   "- On F7, this is displayed as techlevel + 1 (e.g., setting 0 displays as 1).",

        population: "Enter a new value for 'population'.\n" +
                    "- Valid range: 0 to 100 (integer).\n" +
                    "- Represents the population in hundreds of millions.\n" +
                    "- On F7, this is displayed as 'Population: X.X Billion' (e.g., population = 14 becomes 'Population: 1.4 Billion').",

        population_description: "Enter a new value for 'population_description'.\n" +
                                "- Overrides the default text used to describe the population.\n" +
                                "- Example: '7 Castaways', '13 Billion'.",

        inhabitant: "Enter a new value for 'inhabitant' (singular word).\n" +
                    "- A free-form text string describing the inhabitants.\n" +
                    "- Example: 'Human Colonist', 'Rodent-Ruined Reptile'.\n" +
                    "- Remember to stay aligned with inhabitants (plural words).",

        inhabitants: "Enter a new value for 'inhabitants' (plural words).\n" +
                     "- A free-form text string describing the inhabitants.\n" +
                     "- Example: 'Human Colonists', 'Rodent-Ruined Reptiles'.\n" +
                     "- Remember to also update inhabitant (singular word).",

        productivity: "Enter a new value for 'productivity'.\n" +
                      "- A whole number representing gross productivity in MegaCredits (MCr).\n" +
                      "- On F7, this is displayed as 'Gross Productivity: X MCr'.\n" +
                      "- Its role in game mechanics is unclear; it may be purely cosmetic.",

        radius: "Enter a new value for 'radius'.\n" +
                "- Valid range: 3000 to 7000 (integer). (Limits unconfirmed.)\n" +
                "- The radius of the planet. On F7, this is displayed as kilometres.\n" +
                "- The radius in game is 1/100th of this.\n" +
                "- Pro-tip: setting radius to 0 suppresses the image on F7 screen.",

        description: "Enter a new value for 'description'.\n" +
                     "- A free-form text string describing the planet.\n" +
                     "- Use this field creatively to add flavour to your worlds.\n" +
                     "- Example: 'This is a dull planet.', 'The Lord Chamberlain visited this planet on stardate x.'",

        visits: "The value for 'visits' is maintained by Explorers' Club, version 1.5 or later.\n" +
                "- Counts the number of times the player has visited this system.",

        corona_flare: "Enter a new value for 'corona_flare'.\n" +
                      "- Sets the overall size of the corona in proportion to its sun.\n" +
                      "- Valid range: 0.0 (invisibly small) to 1.0 (huge).\n" +
                      "- Example: '0.075' creates a moderately sized corona.",

        corona_hues: "Enter a new value for 'corona_hues'.\n" +
                     "- Specifies whether the corona should have visible bands of colors within the corona.\n" +
                     "- Valid range: 0.0 (monochromatic) to 1.0 (vivid alternating colors).\n" +
                     "- Example: '0.6' creates vivid but not overly contrasting color bands.",

        corona_shimmer: "Enter a new value for 'corona_shimmer'.\n" +
                        "- Specifies how quickly the corona colors change.\n" +
                        "- Valid range: 0.0 (very slow) to 1.0 (very fast).\n" +
                        "- Example: '0.4' creates a moderate shimmer effect.",

        sun_color: "Enter a new value for 'sun_color'.\n" +
                   "- Sets the color of a system's sun.\n" +
                   "- Can be any color specifier or named color (e.g., 'blueColor', 'redColor').\n" +
                   "- The specified color is blended with 50% white, so it will never be fully saturated.\n" +
                   "- Dark colors will appear brighter due to this blending.\n" +
                   "- Example: 'blueColor' creates a bright blue sun.",

        sun_distance: "Enter a new value for 'sun_distance'.\n" +
                      "- Sets the distance between the sun and the main planet in meters.\n" +
                      "- Ignored if 'sun_distance_modifier' is set.\n" +
                      "- Example: '924122' sets the sun at approximately 924 kilometers from the planet.",

        sun_distance_multiplier: "Enter a new value for 'sun_distance_multiplier'.\n" +
                                 "- Multiplies the distance between the sun and the main planet by this factor.\n" +
                                 "- Ignored if 'sun_distance_modifier' is set.\n" +
                                 "- Example: '2' doubles the default distance between the sun and the planet.",

        sun_distance_modifier: "Enter a new value for 'sun_distance_modifier'.\n" +
                               "- Sets the approximate distance between a system's sun and its main planet.\n" +
                               "- The standard distance is 20 planetary radii. Lower values (e.g., 10 or less) may cause delays when generating systems due to potential collisions.\n" +
                               "- In Oolite 1.81 or later, 'sun_distance_multiplier' is more useful.\n" +
                               "- Example: '15.0' sets the sun at 15 times the planet's radius.",

        sun_gone_nova: "Enter a new value for 'sun_gone_nova'.\n" +
                       "- Sets whether the system's sun has gone nova.\n" +
                       "- Valid values: 'YES' or 'NO'.\n" +
                       "- Example: 'YES' creates a nova sun in the system.",

        sun_name: "Enter a new value for 'sun_name'.\n" +
                  "- Stores the name of a system's sun.\n" +
                  "- This feature is only implemented in Oolite version 1.79 onwards.\n" +
                  "- Example: 'Alpha Centauri' names the sun accordingly.",

        sun_radius: "Enter a new value for 'sun_radius'.\n" +
                    "- Sets the radius of a system's sun in kilometers.\n" +
                    "- Valid range: 1000 to 1000000.\n" +
                    "- Example: '100000' creates a sun with a radius of 100,000 kilometers.",

        sun_vector: "Enter a new value for 'sun_vector'.\n" +
                    "- Specifies the direction of the sun relative to the main planet.\n" +
                    "- Format: A vector with three components (x, y, z).\n" +
                    "- Example: '-0.717 -0.668 0.201' defines the sun's position.",

        default: "You are setting the '" + this._propertyToChange + "' property.\n" +
                 "Sorry, no out-of-range validation will be done - you should know what you are doing."
    };

    // Return the appropriate message based on this._propertyToChange
    return messages[this._propertyToChange] || messages.default;
};

/* ========================================================
	DEFINITIONS OF ALL THE SHORT-CUT MENUS
=========================================================== */

// Define a reusable menu structure
const menuItems = {
    world_builder: [
        "Enter the property to change (case-sensitive), or enter 'HELP'. Below are some of the available properties:",
        "name",
        "economy",
        "economy_description",
        "government",
        "government_description",
        "techlevel",
        "population",
        "population_description",
        "inhabitants",
        "productivity",
        "radius",
        "description"
    ],
    HELP: [
        "Enter a keyword (ALL-CAPS) for a menu of relevant properties to change:",
        "PEOPLE",
        "PLANET",
        "ATMOSPHERE",
        "SKY",
        "STATION",
        "SUN",
        "READONLY"
    ],
    PEOPLE: [
        "Enter any property to change (case-sensitive). Below are some of the available properties:",
        "description",
        "economy",
        "economy_description",
        "government",
        "government_description",
        "inhabitant",
        "inhabitants",
        "name",
        "population",
        "population_description",
        "productivity",
        "techlevel"
    ],
    PLANET: [
        "Enter any property to change (case-sensitive). Below are SOME of the planet-related properties:",
        "illumination_color",
        "land_color",
        "land_fraction",
        "planet_distance",
        "planet_distance_multiplier",
     // "planet_name",
        "polar_land_color",
        "polar_sea_color",
        "radius",
        "rotational_velocity",
        "rotation_speed",
        "rotation_speed_factor",
        "sea_color",
        "terminator_threshold_vector",
        "texture",
        "texture_hsb_color",
        "texture_normspec"
    ],
    ATMOSPHERE: [
        "Enter any property to change (case-sensitive). Below are SOME of the atmosphere-related properties:",
        "air_color",
        "air_color_mix_ratio",
        "air_density",
        "atmosphere_rotational_velocity",
        "cloud_alpha",
        "cloud_color",
        "cloud_fraction",
        "has_atmosphere",
        "polar_cloud_color"
    ],
    SKY: [
        "Enter any property to change (case-sensitive). Below are all the sky-related properties:",
        "ambient_level",
        "nebula_color_1",
        "nebula_color_2",
        "nebula_count_multiplier",
        "sky_blur_alpha",
        "sky_blur_cluster_chance",
        "sky_blur_scale",
        "sky_color_1",
        "sky_color_2",
        "sky_n_blurs",
        "sky_n_stars",
        "sky_rgb_colors",
        "star_count_multiplier"
    ],
    STATION: [
        "Enter any property to change (case-sensitive). Below are all the station-related properties:",
        "market_script",
        "station",
        "station_roll",
        "station_vector",
        "stations_require_docking_clearance"
    ],
    SUN: [
        "Enter any property to change (case-sensitive). Below are all the sun-related properties:",
        "corona_flare",
        "corona_hues",
        "corona_shimmer",
        "sun_color",
        "sun_distance",
        "sun_distance_modifier",
        "sun_distance_multiplier",
        "sun_gone_nova",
        "sun_name",
        "sun_radius",
        "sun_vector"
    ],
    READONLY: [
        "View read-only properties by selecting an option below:",
        "coordinates",
        "galaxyID",
        "systemID",
        "visits",
        "sun_gone_nova"
    ]
};

/* ========================================================
		SETTING THE INTERFACE ON F4 SCREEN
=========================================================== */

this.infoSystemChanged = this.shipWillExitWitchspace = function () {
    this._applyInterface();
};

this.startUp = function () {
    this._applyInterface();
    delete this.startUp;
};

this._applyInterface = function () {
    if (system.mainStation) {
        system.mainStation.setInterface("world_builder", {
            title: "World Builder",
            category: expandDescription("[interfaces-category-uncategorised]"),
            summary: "Improve a world, any world. Currently improving " + System.systemNameForID(player.ship.infoSystem) + ".",
            callback: this._changeWorld.bind(this)
        });
    }
};

/* ========================================================
		FIRST USER-INPUT SCREEN

    Here the user will enter: a property name directly (e.g.
    "government"); a number from the displayed menu, which
    will be converted to a property name in step 2; or a
    KEYWORD which will be passed back to this function to
    create an alternative menu.
    Dynamically generate the message from the menuItems array.
=========================================================== */

this._changeWorld = function (menuKey) {
    if (!menuItems[menuKey]) {
        log(this.name, "Error: Menu " + menuKey + " not found.");
        return;
    }
    this._currentMenuKey = menuKey;
    this._currentBackground = { name: "wb_bg_" + menuKey + ".png", height: 512 };

    let message = menuItems[menuKey][0] + "\n\n";
    for (let i = 1; i < menuItems[menuKey].length; i++) {
        message += (i + ". " + menuItems[menuKey][i] + "\n");
    }

    let sysID = player.ship.infoSystem;

    var parameters = {
        title: "Rebuilding World " + sysID + ", " + System.systemNameForID(sysID),
        message: message,
        screenID: "world_builder",
        background: this._currentBackground,
        exitScreen: "GUI_SCREEN_SYSTEM_DATA",
        allowInterrupt: false, // Conflicts with text-entry.
        textEntry: true
    }
    if (menuKey === "world_builder") {
        parameters.music = "dt_manipulating_property_values.ogg";
    }
    mission.runScreen(parameters, this._changeWorld2.bind(this));
};

/* ========================================================
		SECOND USER-INPUT SCREEN
=========================================================== */

this._changeWorld2 = function (userInput) {
    if (userInput && userInput !== "") {
        // Check if the input is a positive integer
        var numericInput = parseInt(userInput, 10);
        if (!isNaN(numericInput) && numericInput > 0) {
            // Map the numeric input to the corresponding property name
            const menuItemIndex = numericInput;
            const selectedMenu = menuItems[this._currentMenuKey]; // Use the active menu key

            if (menuItemIndex >= 1 && menuItemIndex < selectedMenu.length) {
                this._propertyToChange = selectedMenu[menuItemIndex];
            } else {

                // Invalid numeric input
                mission.runScreen({
                    title: "World Builder",
                    message: "Invalid numeric input. Please enter a valid property name or number.",
                    background: "wb_bg_ERROR.png",
                    exitScreen: "GUI_SCREEN_SYSTEM_DATA",
                    allowInterrupt: true,
                    screenID: "world_builder"
                });
                return; // Exit early to avoid proceeding with invalid input
            }
        } else {
            // Use the input as-is (assuming it's a property name)
            this._propertyToChange = userInput;
        }
    }

    // Check for KEYWORD to change the _currentMenuKey
    if (menuItems.hasOwnProperty(this._propertyToChange)) {
        this._currentMenuKey = this._propertyToChange; // Update the current menu key
        this._changeWorld(this._currentMenuKey);      // Restart the process with the new menu
        return;                                      // Exit early to avoid proceeding with other logic
    }

    // Check if the property is read-only
    if (menuItems.READONLY.indexOf(this._propertyToChange) !== -1) {
        const sys = System.infoForSystem(galaxyNumber, player.ship.infoSystem);
        const readOnlyMessage = "Current value of " + this._propertyToChange + ": " + sys[this._propertyToChange] + ".\n" + "This property is read-only. You cannot modify it.";
        const readOnlyTitle = "Rebuilding World " + player.ship.infoSystem + ", " + sys.name;
        mission.runScreen({
            title: readOnlyTitle,
            message: readOnlyMessage,
            choices: {"1_AGAIN": "Choose another property", "9_EXIT": "EXIT World Builder"},
            screenID: "world_builder",
            background: { name: "wb_bg_READONLY.png", height: 512 },
            exitScreen: "GUI_SCREEN_LONG_RANGE_CHART",
            allowInterrupt: true
        }, this._handleExitChoice.bind(this));
        return; // Exit early to avoid proceeding with other logic
    }

    // Proceed to Step 2: Enter new value for the property
    var parameters = {
        title: "Rebuilding World " + player.ship.infoSystem + ", " + System.systemNameForID(player.ship.infoSystem),
        message: "Current value of " + this._propertyToChange + ": " + System.infoForSystem(galaxyNumber, player.ship.infoSystem)[this._propertyToChange] + ".\n" + this._messageTexts(),
        screenID: "world_builder",
        background: this._currentBackground,
        exitScreen: "GUI_SCREEN_SYSTEM_DATA",
        allowInterrupt: false, // Conflicts with text-entry.
        textEntry: true
    }
    mission.runScreen(parameters, this._changeWorld3.bind(this));
};

/* ========================================================
		STEP 3 - MAKING THE CHANGE
=========================================================== */

this._changeWorld3 = function (newValue) {

    var title = "World Builder";
    var message = "No change recorded.";

    if (newValue && newValue !== "") {
        const sysID = player.ship.infoSystem;
        const sys = System.infoForSystem(galaxyNumber, sysID);
        const oldValue = sys[this._propertyToChange.toString()];
     // const oldValue = sys[this._propertyToChange].toString();

        // To enable an "undo" log to be maintained, before changing system information, call:
        worldScripts.sysInfoChangeLog._pendingChange(galaxyNumber, sysID, this._propertyToChange, oldValue, newValue, 2);

        sys[this._propertyToChange] = newValue;

        title = "Rebuilding World " + sysID + ", " + sys.name;
        message = "Changed " + this._propertyToChange + " from " + oldValue + " to " + newValue + ". Exit to view result.";
    }
    mission.runScreen({
        title: title,
        message: message,
        choices: {"1_AGAIN": "Edit another property", "9_EXIT": "EXIT World Builder"},
        screenID: "world_builder",
        background: this._currentBackground,
        exitScreen: "GUI_SCREEN_SYSTEM_DATA",
        allowInterrupt: true
    }, this._handleExitChoice.bind(this));
};

/* ========================================================
	HANDLER FROM LAST SCREEN
=========================================================== */

this._handleExitChoice = function (choice) {
    if (choice === "1_AGAIN") {
        // Return to the first input screen
        this._changeWorld(this._currentMenuKey);
    }
};

/* ========================================================
        UNDO FUNCTIONALITY
=========================================================== */

this._undoLastChange = function () {
    // Retrieve the change log
    if (!missionVariables.World_Builder_systemChangeLog) {
        mission.runScreen({
            title: "World Builder",
            message: "No changes to undo.",
            exitScreen: "GUI_SCREEN_SYSTEM_DATA",
            allowInterrupt: true,
            screenID: "world_builder"
        });
        return;
    }

    var changeLog = JSON.parse(missionVariables.World_Builder_systemChangeLog);
    if (changeLog.length === 0) {
        mission.runScreen({
            title: "World Builder",
            message: "No changes to undo.",
            exitScreen: "GUI_SCREEN_SYSTEM_DATA",
            allowInterrupt: true,
            screenID: "world_builder"
        });
        return;
    }

    // Get the most recent change
    const lastChange = changeLog.pop(); // Remove the last change from the log
    const { galaxyID, systemID, property, oldValue } = lastChange;

    // Revert the change
    const sys = System.infoForSystem(galaxyID, systemID);
    if (sys[property] !== undefined) {
        sys[property] = oldValue; // Revert the property to its old value

        // Save the updated log back to mission variables
        missionVariables.World_Builder_systemChangeLog = JSON.stringify(changeLog);

        // Notify the user
        mission.runScreen({
            title: "World Builder",
            message: "Undid the last change:\n" +
                     "- Property: " + property + "\n" +
                     "- Old Value: " + oldValue,
            exitScreen: "GUI_SCREEN_SYSTEM_DATA",
            allowInterrupt: true,
            screenID: "world_builder"
        });
    } else {
        mission.runScreen({
            title: "World Builder",
            message: "Failed to undo the last change. The property may no longer exist.",
            exitScreen: "GUI_SCREEN_SYSTEM_DATA",
            allowInterrupt: true,
            screenID: "world_builder"
        });
    }
};

/* ========================================================
        ADD UNDO OPTION TO THE INTERFACES
=========================================================== */
/*
this._applyInterface = function () {
    if (system.mainStation) {
        system.mainStation.setInterface("world_builder", {
            title: "World Builder",
            category: expandDescription("[interfaces-category-uncategorised]"),
            summary: "Improve a world, any world. Currently improving " + System.systemNameForID(player.ship.infoSystem) + ".",
            callback: this._changeWorld.bind(this)
        });
        system.mainStation.setInterface("world_builder_undo", {
            title: "World Builder (undo last change)",
            category: expandDescription("[interfaces-category-uncategorised]"),
            summary: "Undo the last change made to system information by World Builder.",
            callback: this._undoLastChange.bind(this)
        });
    }
};
*/
/* ========================================================
		THE END
=========================================================== */