"use strict";
this.name = "ShipConfiguration_Book";
this.author = "phkb";
this.description = "Adds the Ship Configuration Handbook to the Ship's Library";

this._cols = [5, 25];

//-------------------------------------------------------------------------------------------------------------
this.startUpComplete = function () {
    this._registerSCBook();
}

//-------------------------------------------------------------------------------------------------------------
this._registerSCBook = function () {
    var core = worldScripts.ShipConfiguration_Core;
    this.$engineGrid();
    this.$hyperdriveGrid();
    this.$thrusterGrid();
    this.$boosterGrid();
    this.$shieldGrid();
    this.$injectorGrid();
    this.$scoopGrid();
    this.$heatShieldGrid();
    this.$armourGrid();
    this.$elecBusGrid();
    this.$engineCouplingGrid();
    this.$hyperdriveCouplingGrid();
    this.$thrusterCouplingGrid();
    this.$boosterCouplingGrid();
    this.$energyCouplingGrid();
    this.$shieldCouplingGrid();
    this.$equipmentGrid();

    if (oolite.compareVersion("1.91") <= 0)
        this._key1 = expandMissionText("sc_prime_key_191");
    else
        this._key1 = expandMissionText("sc_prime_key_190");

    var contents = [
        { level: 0, key: "sc_intro" },
        { level: 1, key: "sc_chap1", params: [function () { return core.$equipmentSpaceTotal(player.ship); }, function () { return core.$cargoSpaceAvailable(player.ship); }, function () { return core.$equipmentSpaceTotal(player.ship) + core.$cargoSpaceAvailable(player.ship); }] },
        { level: 1, key: "sc_chap2", backgrounds: [{ name: "sc_book_ch2.png", height: 512 }, ""] },
        { level: 2, key: "sc_chap2a", backgrounds: [{ name: "sc_book_ch2a.png", height: 512 }, ""] },
        { level: 2, key: "sc_chap2b", backgrounds: [{ name: "sc_book_ch2b.png", height: 512 }, ""] },
        { level: 1, key: "sc_chap3" },
        { level: 2, key: "sc_chap3a", params: [function () { return core._engines.length; }, function () { return worldScripts.ShipConfiguration_Book._engineGrid; }] },
        { level: 2, key: "sc_chap3b", params: [function () { return core._hyperdrive.length; }, function () { return worldScripts.ShipConfiguration_Book._hyperdriveGrid; }] },
        { level: 2, key: "sc_chap3c", params: [function () { return core._thrusters.length; }, function () { return worldScripts.ShipConfiguration_Book._thrusterGrid; }] },
        { level: 2, key: "sc_chap3d", params: [function () { return core._boosters.length; }, function () { return worldScripts.ShipConfiguration_Book._boosterGrid; }] },
        { level: 2, key: "sc_chap3e" },
        { level: 2, key: "sc_chap3f", params: [function () { return core._frontshields.length - 1; }, function () { return worldScripts.ShipConfiguration_Book._shieldGrid; }] },
        { level: 2, key: "sc_chap3g", params: [function () { return core._fuelinjectors.length; }, function () { return worldScripts.ShipConfiguration_Book._injectorGrid; }] },
        { level: 2, key: "sc_chap3h", params: [function () { return core._fuelscoops.length; }, function () { return worldScripts.ShipConfiguration_Book._scoopGrid; }] },
        { level: 2, key: "sc_chap3i", params: [function () { return core._heatshields.length; }, function () { return worldScripts.ShipConfiguration_Book._heatShieldGrid; }] },
        { level: 2, key: "sc_chap3j", params: [function () { return core._frontarmour.length; }, function () { return worldScripts.ShipConfiguration_Book._armourGrid; }] },
        { level: 2, key: "sc_chap3k" },
        { level: 3, key: "sc_chap3k1", params: [function () { return core._electricalbus.length; }, function () { return worldScripts.ShipConfiguration_Book._elecBusGrid; }] },
        { level: 3, key: "sc_chap3k2", params: [function () { return core._enCoupling.length; }, function () { return worldScripts.ShipConfiguration_Book._engineCouplingGrid; }] },
        { level: 3, key: "sc_chap3k3", params: [function () { return core._hdCoupling.length; }, function () { return worldScripts.ShipConfiguration_Book._hyperdriveCouplingGrid; }] },
        { level: 3, key: "sc_chap3k4", params: [function () { return core._thCoupling.length; }, function () { return worldScripts.ShipConfiguration_Book._thrusterCouplingGrid; }] },
        { level: 3, key: "sc_chap3k5", params: [function () { return core._bsCoupling.length; }, function () { return worldScripts.ShipConfiguration_Book._boosterCouplingGrid; }] },
        { level: 3, key: "sc_chap3k6", params: [function () { return core._ebCoupling.length; }, function () { return worldScripts.ShipConfiguration_Book._energyCouplingGrid; }] },
        { level: 3, key: "sc_chap3k7", params: [function () { return core._fsCoupling.length; }, function () { return worldScripts.ShipConfiguration_Book._shieldCouplingGrid; }] },
        { level: 1, key: "sc_chap4" },
        { level: 2, key: "sc_chap4a" },
        { level: 2, key: "sc_chap4b" },
        { level: 2, key: "sc_chap4c" },
        { level: 2, key: "sc_chap4d" },
        { level: 2, key: "sc_chap4e", params: [function () { return worldScripts.ShipConfiguration_Book._equipmentGrid; }] },
        { level: 1, key: "sc_chap5" },
        { level: 2, key: "sc_chap5a", params: [function () { return worldScripts.ShipConfiguration_Book._key1; }] },
    ];
    worldScripts["Ships Library"]._registerBook("ship_configuration", expandMissionText("sc_title"), contents, 22);
}

//-------------------------------------------------------------------------------------------------------------
this.$engineGrid = function () {
    var core = worldScripts.ShipConfiguration_Core;
    var data = core._engines;
    var result = "";
    var next_break = 4;
    var rec_count = 0;
    for (var i = 0; i < data.length; i++) {
        var equip = EquipmentInfo.infoForKey(data[i]);
        var th = Math.round((1 - equip.scriptInfo.thrust_adjust) * 100);
        var th_change = (th > 0 ? "reduced" : (th == 0 ? "manufacturers standard" : "increased"));
        th = Math.abs(th);
        var sp = Math.round((1 - equip.scriptInfo.speed_adjust) * 100);
        var sp_change = (sp > 0 ? "reduced" : (sp == 0 ? "manufacturers standard" : "increased"));
        sp = Math.abs(sp);
        var spc = core._equipmentMatrix[data[i]][0];
        var w = core._equipmentMatrix[data[i]][1];
        var extra = "";
        if (equip.scriptInfo.description.indexOf("+heat") >= 0) extra = "Also adds to cabin heat. ";
        var text = equip.scriptInfo.short_title + "|" + expandMissionText("sc_engine_text", {
            thrust_change: (th != 0 ? th.toString() + "% " : "") + th_change,
            speed_change: (sp != 0 ? sp.toString() + "% " : "") + sp_change,
            space: spc.toString(),
            weight: w.toString(),
            tl: (equip.techLevel + 1),
            extra: extra
        });
        result += this.$padLine(text, this._cols);
        rec_count += 1;
        if (rec_count == next_break) {
            result += String.fromCharCode(30) + "\n";
            next_break += (rec_count > 30 ? 6 : 6);
        }
    }
    this._engineGrid = result;
}

//-------------------------------------------------------------------------------------------------------------
this.$hyperdriveGrid = function () {
    var core = worldScripts.ShipConfiguration_Core;
    var data = core._hyperdrive;
    var result = "";
    for (var i = 0; i < data.length; i++) {
        var equip = EquipmentInfo.infoForKey(data[i]);
        var tm = equip.scriptInfo.spin_time
        var spc = core._equipmentMatrix[data[i]][0];
        var w = core._equipmentMatrix[data[i]][1];
        var text = equip.scriptInfo.short_title + "|" + expandMissionText("sc_hyperdrive_text", {
            spintime: tm,
            space: spc.toString(),
            weight: w.toString(),
            tl: (equip.techLevel + 1)
        });
        result += this.$padLine(text, this._cols);
    }
    this._hyperdriveGrid = result;
}

//-------------------------------------------------------------------------------------------------------------
this.$thrusterGrid = function () {
    var core = worldScripts.ShipConfiguration_Core;
    var data = core._thrusters;
    var result = "";
    var next_break = 6;
    var rec_count = 0;
    for (var i = 0; i < data.length; i++) {
        var equip = EquipmentInfo.infoForKey(data[i]);
        var pt = Math.round((1 - equip.scriptInfo.pitch_adjust) * 100);
        var pt_change = (pt > 0 ? "reduced" : (pt == 0 ? "manufacturers standard" : "increased"));
        pt = Math.abs(pt);
        var rl = Math.round((1 - equip.scriptInfo.roll_adjust) * 100);
        var rl_change = (rl > 0 ? "reduced" : (rl == 0 ? "manufacturers standard" : "increased"));
        rl = Math.abs(rl);
        var spc = core._equipmentMatrix[data[i]][0];
        var w = core._equipmentMatrix[data[i]][1];
        var extra = "";
        if (equip.scriptInfo.description.indexOf("+heat") >= 0) extra = "Also adds to cabin heat. ";
        var text = equip.scriptInfo.short_title + "|" + expandMissionText("sc_thruster_text", {
            pitch_change: (pt != 0 ? pt.toString() + "% " : "") + pt_change,
            roll_change: (rl != 0 ? rl.toString() + "% " : "") + rl_change,
            space: spc.toString(),
            weight: w.toString(),
            tl: (equip.techLevel + 1),
            extra: extra
        });
        result += this.$padLine(text, this._cols);
        rec_count += 1;
        if (rec_count == next_break) {
            result += String.fromCharCode(30) + "\n";
            next_break += 7;
        }
    }
    this._thrusterGrid = result;
}

//-------------------------------------------------------------------------------------------------------------
this.$boosterGrid = function () {
    var core = worldScripts.ShipConfiguration_Core;
    var data = core._boosters;
    var result = "";
    var next_break = 3;
    var rec_count = 0;
    for (var i = 0; i < data.length; i++) {
        var equip = EquipmentInfo.infoForKey(data[i]);
        var sp = Math.round((1 - equip.scriptInfo.speed_adjust) * 100);
        sp = Math.abs(sp);
        var th = Math.round((1 - equip.scriptInfo.thrust_adjust) * 100);
        th = Math.abs(th);
        var ht = Math.round(equip.scriptInfo.heat_buildup * 100);
        var spc = core._equipmentMatrix[data[i]][0];
        var w = core._equipmentMatrix[data[i]][1];
        var text = equip.scriptInfo.short_title + "|" + expandMissionText("sc_booster_text", {
            boost: sp.toString() + "%",
            throttle: ht.toString() + "%",
            space: spc.toString(),
            weight: w.toString(),
            tl: (equip.techLevel + 1)
        });
        result += this.$padLine(text, this._cols);
        rec_count += 1;
        if (rec_count == next_break) {
            result += String.fromCharCode(30) + "\n";
            next_break += 6;
        }
    }
    this._boosterGrid = result;
}

//-------------------------------------------------------------------------------------------------------------
this.$shieldGrid = function () {
    var core = worldScripts.ShipConfiguration_Core;
    var data = core._frontshields;
    var result = "";
    for (var i = 1; i < data.length; i++) {
        var equip = EquipmentInfo.infoForKey(data[i]);
        var chg = equip.scriptInfo.description;
        var spc = core._equipmentMatrix[data[i]][0];
        var w = core._equipmentMatrix[data[i]][1];
        var text = equip.scriptInfo.short_title + "|" + expandMissionText("sc_shield_text", {
            change: (chg == "standard" ? "No change" : chg),
            space: spc.toString(),
            weight: w.toString(),
            tl: (equip.techLevel + 1)
        });
        result += this.$padLine(text, this._cols);
    }
    this._shieldGrid = result;
}

//-------------------------------------------------------------------------------------------------------------
this.$injectorGrid = function () {
    var core = worldScripts.ShipConfiguration_Core;
    var data = core._fuelinjectors;
    var result = "";
    for (var i = 0; i < data.length; i++) {
        var equip = EquipmentInfo.infoForKey(data[i]);
        var br = Math.round((1 - equip.scriptInfo.burn_rate) * 100);
        br = Math.abs(br) + "% " + (br < 0 ? "more" : "less");
        var sf = Math.round((equip.scriptInfo.speed_factor - 1) * 100);
        var chg = "boost";
        if (sf < 0) chg = "reduction";
        var spc = core._equipmentMatrix[data[i]][0];
        var w = core._equipmentMatrix[data[i]][1];
        if (sf == 0) {
            var text = equip.scriptInfo.short_title + "|" + expandMissionText("sc_injector_text_alt", {
                space: spc.toString(),
                weight: w.toString(),
                tl: (equip.techLevel + 1)
            });
        } else {
            var text = equip.scriptInfo.short_title + "|" + expandMissionText("sc_injector_text", {
                burn: br,
                speed: sf + "%",
                change: chg,
                space: spc.toString(),
                weight: w.toString(),
                tl: (equip.techLevel + 1)
            });
        }
        result += this.$padLine(text, this._cols);
    }
    this._injectorGrid = result;
}

//-------------------------------------------------------------------------------------------------------------
this.$scoopGrid = function () {
    var core = worldScripts.ShipConfiguration_Core;
    var data = core._fuelscoops;
    var result = "";
    for (var i = 0; i < data.length; i++) {
        var equip = EquipmentInfo.infoForKey(data[i]);
        var acc = (parseFloat(equip.scriptInfo.accumulator_size) + 0.1);
        var extra = "";
        if (acc == 0.1) extra = "This is the standard type of fuel scoop. ";
        var w = core._equipmentMatrix[data[i]][1];
        var text = equip.scriptInfo.short_title + "|" + expandMissionText("sc_scoop_text", {
            ly: acc.toFixed(2),
            weight: w.toString(),
            extra: extra,
            tl: (equip.techLevel + 1)
        });
        result += this.$padLine(text, this._cols);
    }
    this._scoopGrid = result;
}

//-------------------------------------------------------------------------------------------------------------
this.$heatShieldGrid = function () {
    var core = worldScripts.ShipConfiguration_Core;
    var data = core._heatshields;
    var result = "";
    for (var i = 0; i < data.length; i++) {
        var equip = EquipmentInfo.infoForKey(data[i]);
        var str = equip.scriptInfo.oolite_heat_insulation_strength;
        var w = core._equipmentMatrix[data[i]][1];
        var extra = "";
        if (str == "1.0") extra = "This is the general standard level of heat shielding. ";
        var text = equip.scriptInfo.short_title + "|" + expandMissionText("sc_heatshield_text", {
            strength: str,
            weight: w.toString(),
            extra: extra,
            tl: (equip.techLevel + 1)
        });
        result += this.$padLine(text, this._cols);
    }
    this._heatShieldGrid = result;
}

//-------------------------------------------------------------------------------------------------------------
this.$armourGrid = function () {
    var core = worldScripts.ShipConfiguration_Core;
    var data = core._frontarmour;
    var result = "";
    for (var i = 0; i < data.length; i++) {
        var equip = EquipmentInfo.infoForKey(data[i]);
        var dmg = equip.scriptInfo.damage_point;
        var str = equip.scriptInfo.armour_strength;
        var w = core._equipmentMatrix[data[i]][1];
        var key = "sc_armour_type_" + (i + 1).toString();
        var text = equip.scriptInfo.short_title + "|" + expandMissionText(key) + expandMissionText("sc_armour_text", {
            strength: str,
            damage: dmg,
            weight: w.toString(),
            tl: (equip.techLevel + 1)
        });
        result += this.$padLine(text, this._cols);
    }
    this._armourGrid = result;
}

//-------------------------------------------------------------------------------------------------------------
this.$elecBusGrid = function () {
    var core = worldScripts.ShipConfiguration_Core;
    var data = core._electricalbus;
    var result = "";
    for (var i = 0; i < data.length; i++) {
        var equip = EquipmentInfo.infoForKey(data[i]);
        var spc = core._equipmentMatrix[data[i]][0];
        var w = core._equipmentMatrix[data[i]][1];
        var text = equip.scriptInfo.short_title + "|" + expandMissionText("sc_elecbus_text", {
            upto: (i == 0 ? "" : "up to "),
            class: "class " + (i + 1).toString() + (i == 6 ? "/8" : ""),
            space: spc.toString(),
            weight: w.toString(),
            tl: (equip.techLevel + 1)
        });
        result += this.$padLine(text, this._cols);
    }
    this._elecBusGrid = result;
}

//-------------------------------------------------------------------------------------------------------------
this.$engineCouplingGrid = function () {
    var core = worldScripts.ShipConfiguration_Core;
    var data = core._enCoupling;
    var result = "";
    for (var i = 0; i < data.length; i++) {
        var equip = EquipmentInfo.infoForKey(data[i]);
        var spc = core._equipmentMatrix[data[i]][0];
        var w = core._equipmentMatrix[data[i]][1];
        var text = equip.scriptInfo.short_title + "|" + expandMissionText("sc_engine_coupling_text", {
            upto: (i == 0 ? "" : "up to "),
            class: "class " + (i + 1).toString(),
            space: spc.toString(),
            weight: w.toString(),
            tl: (equip.techLevel + 1)
        });
        result += this.$padLine(text, this._cols);
    }
    this._engineCouplingGrid = result;
}

//-------------------------------------------------------------------------------------------------------------
this.$hyperdriveCouplingGrid = function () {
    var core = worldScripts.ShipConfiguration_Core;
    var data = core._hdCoupling;
    var result = "";
    for (var i = 0; i < data.length; i++) {
        var equip = EquipmentInfo.infoForKey(data[i]);
        var spc = core._equipmentMatrix[data[i]][0];
        var w = core._equipmentMatrix[data[i]][1];
        var text = equip.scriptInfo.short_title + "|" + expandMissionText("sc_hyperdrive_coupling_text", {
            upto: (i == 0 ? "" : "up to "),
            class: "class " + (i + 1).toString(),
            space: spc.toString(),
            weight: w.toString(),
            tl: (equip.techLevel + 1)
        });
        result += this.$padLine(text, this._cols);
    }
    this._hyperdriveCouplingGrid = result;
}

//-------------------------------------------------------------------------------------------------------------
this.$thrusterCouplingGrid = function () {
    var core = worldScripts.ShipConfiguration_Core;
    var data = core._thCoupling;
    var result = "";
    for (var i = 0; i < data.length; i++) {
        var equip = EquipmentInfo.infoForKey(data[i]);
        var spc = core._equipmentMatrix[data[i]][0];
        var w = core._equipmentMatrix[data[i]][1];
        var text = equip.scriptInfo.short_title + "|" + expandMissionText("sc_thruster_coupling_text", {
            upto: (i == 0 ? "" : "up to "),
            class: "class " + (i + 1).toString(),
            space: spc.toString(),
            weight: w.toString(),
            tl: (equip.techLevel + 1)
        });
        result += this.$padLine(text, this._cols);
    }
    this._thrusterCouplingGrid = result;
}

//-------------------------------------------------------------------------------------------------------------
this.$boosterCouplingGrid = function () {
    var core = worldScripts.ShipConfiguration_Core;
    var data = core._bsCoupling;
    var result = "";
    for (var i = 0; i < data.length; i++) {
        var equip = EquipmentInfo.infoForKey(data[i]);
        var spc = core._equipmentMatrix[data[i]][0];
        var w = core._equipmentMatrix[data[i]][1];
        var text = equip.scriptInfo.short_title + "|" + expandMissionText("sc_booster_coupling_text", {
            upto: (i == 0 ? "" : "up to "),
            class: "class " + (i + 1).toString(),
            space: spc.toString(),
            weight: w.toString(),
            tl: (equip.techLevel + 1)
        });
        result += this.$padLine(text, this._cols);
    }
    this._boosterCouplingGrid = result;
}

//-------------------------------------------------------------------------------------------------------------
this.$energyCouplingGrid = function () {
    var core = worldScripts.ShipConfiguration_Core;
    var data = core._fsCoupling;
    var result = "";
    for (var i = 0; i < data.length; i++) {
        var equip = EquipmentInfo.infoForKey(data[i]);
        var spc = core._equipmentMatrix[data[i]][0];
        var w = core._equipmentMatrix[data[i]][1];
        var text = equip.scriptInfo.short_title + "|" + expandMissionText("sc_energy_coupling_text", {
            class: "class " + (((i + 1) * 3) + 1).toString(),
            space: spc.toString(),
            weight: w.toString(),
            tl: (equip.techLevel + 1)
        });
        result += this.$padLine(text, this._cols);
    }
    this._energyCouplingGrid = result;
}

//-------------------------------------------------------------------------------------------------------------
this.$shieldCouplingGrid = function () {
    var core = worldScripts.ShipConfiguration_Core;
    var data = core._fsCoupling;
    var result = "";
    for (var i = 0; i < data.length; i++) {
        var equip = EquipmentInfo.infoForKey(data[i]);
        var spc = core._equipmentMatrix[data[i]][0];
        var w = core._equipmentMatrix[data[i]][1];
        var text = equip.scriptInfo.short_title + "|" + expandMissionText("sc_shield_coupling_text", {
            upto: (i == 0 ? "" : "up to "),
            class: "class " + (i + 1).toString(),
            space: spc.toString(),
            weight: w.toString(),
            tl: (equip.techLevel + 1)
        });
        result += this.$padLine(text, this._cols);
    }
    this._shieldCouplingGrid = result;
}

//-------------------------------------------------------------------------------------------------------------
this.$equipmentGrid = function () {
    var lines = expandMissionText("sc_equipment_list").split("\n");
    var result = "";
    for (var i = 0; i < lines.length; i++) {
        result += this.$padLine(lines[i], [15, 5, 5])
    }
    this._equipmentGrid = result;
}

//-------------------------------------------------------------------------------------------------------------
this.$padLine = function (text, cols) {
    var core = worldScripts.ShipConfiguration_Core;
    var coltext = text.split("|");
    if (coltext.length != cols.length) {
        log(this.name, "mismatch in column definitions");
        return text;
    }
    var results = [];
    var max = 0;
    for (var i = 0; i < coltext.length; i++) {
        var result = this.$columnText(coltext[i], cols[i]);
        if (result.length > max) max = result.length;
        results.push(result);
    }
    var idx = 0;
    var final = "";
    do {
        for (var i = 0; i < results.length; i++) {
            if (idx < results[i].length) {
                final += core.$padTextRight(results[i][idx], cols[i]);
            } else {
                final += core.$padTextRight(" ", cols[i]);
            }
        }
        final += "\n";
        idx += 1;
        if (idx == max) idx = -1;
    } while (idx != -1)
    return final;
}

//-------------------------------------------------------------------------------------------------------------
// arranges text into a array of strings with a particular column width
this.$columnText = function $columnText(originalText, columnWidth) {
    var returnText = [];
    if (defaultFont.measureString(originalText) > columnWidth) {
        var hold = originalText;
        do {
            var newline = "";
            var remain = "";
            var point = hold.length;
            do {
                point = hold.lastIndexOf(" ", point - 1);
                newline = hold.substring(0, point).trim();
                remain = hold.substring(point + 1).trim();
            } while (defaultFont.measureString(newline) > columnWidth);
            returnText.push(newline);
            if (remain != "") {
                if (defaultFont.measureString(remain) <= columnWidth) {
                    returnText.push(remain);
                    hold = "";
                } else {
                    hold = remain;
                }
            } else {
                hold = "";
            }
        } while (hold != "");
    } else {
        returnText.push(originalText);
    }
    return returnText;
}
