Source: world_get/world_get.js

/* Obtain specific information about the world, either at a given
   position, or for the world in general.
*/

require("./../rur.js");
require("./../translator.js");
require("./../programming_api/exceptions.js");
require("./../default_tiles/tiles.js");
require("./../dialogs/create.js");
require("./../listeners/canvas.js");
require("./../utils/supplant.js");
require("./../world_api/things.js");
require("./../world_api/background_tile.js");

RUR.world_get = {};

RUR.world_get.object_at_robot_position = function (robot, obj) { // TODO: still needed or move elsewhere?
    return object_of_type_here(robot, obj, RUR.get_current_world().objects);
};


function goal_to_achieve() {
    return "<h3>" + RUR.translate("Goal to achieve:") + "</h3>";
}


function difficulty(level) {
    var image_src, begin, i, robots;
    image_src = '<img src = "' + RUR.BASE_URL + '/src/images/transparent_robot.png"';
    begin = '<h3>' + RUR.translate("Difficulty level") + '</h3><div class="difficulty">';

    level = level[level.length-1];  // extract last character.
    level = parseInt(level, 10);
    if (level === 0) {
        level = 10;
    }
    robots = '';
    for (i=1; i <= level; i++) {
        robots += image_src + 'class = "difficulty' + i +'">';
    }
    for (i=level+1; i <= 10; i++) {
        robots += image_src + '>';
    }

    return begin + robots + '</div>';
}


function object_of_type_here (robot, obj, object_type) {
    // object_type == RUR.get_current_world().objects or RUR.get_current_world().decorative_objects
    var obj_here, obj_type, all_objects;
    var coords = robot.x + "," + robot.y;

    if (object_type === undefined ||
        object_type[coords] === undefined) {
        return [];
    }

    obj_here =  object_type[coords];
    all_objects = [];

    for (obj_type in obj_here) {
        if (obj_here.hasOwnProperty(obj_type)) {
            if (obj !== undefined && obj_type == RUR.translate_to_english(obj)) {
                return [RUR.translate(obj_type)];
            }
            all_objects.push(RUR.translate(obj_type));
        }
    }

    if (obj !== undefined) {
        return [];
    } else if (all_objects.length === 0){
        return [];
    } else {
        return all_objects;
    }
}

/** @function show_editors_content
 * @memberof RUR
 * @instance
 *
 * @desc Used to show (or not) the content of the various world
 * editors in the world's description (**World Info** button for English UI).
 *
 * @param {bool} show
 * 
 */

RUR.show_editors_content = function (show) {
    RUR.SHOW_EDITORS_CONTENTS = show;
    RUR.world_get.world_info();
};


RUR.world_get.world_info = function (show_info_at_location) {
    "use strict";
    // Shows the world information, as included in the description editor.
    // In addition shows the information about a given grid position
    // when the user clicks on the canvas at that grid position.
    // If a global flag is set, it also show the various editors content.
    var content, description, goals, information, insertion, to_replace, topic;
    var no_object, obj, r, robot, robots, x, y;

    // Default value if not description is provided:
    information = "<div class='automatic-description'><h2>" + RUR.translate("Description") + "</h2>";

    description = RUR.get_current_world().description;
    if (description === undefined) {
        description = '';
    } else if (typeof description != "string") {
        description = description.join("\n");
    }

    if (RUR.SHOW_EDITORS_CONTENTS) {
        if (RUR.get_current_world().onload) {
            description = "<h3>Onload editor content</h3>INSERT_ONLOAD" + description;
        }   
         if (RUR.get_current_world().pre) {
            description = "<h3>Pre editor content</h3>INSERT_PRE" + description;
        }   
        if (RUR.get_current_world().post) {
            description = "<h3>Post editor content</h3>INSERT_POST" + description;
        }   
        if (RUR.get_current_world().editor) {
            description = "<h3>World's Editor content</h3>INSERT_EDITOR" + description;
        }   
        if (RUR.get_current_world().library) {
            description = "<h3>World's Library content</h3>INSERT_LIBRARY" + description;
        }    
    }

    if (description) {
        if (RUR.get_current_world().pre) {
            content = RUR.get_current_world().pre;
            if (typeof content != "string") {
                content = content.join("\n");
            }
            insertion = "<pre class='world_info_source'>" + content + "</pre>";
            to_replace = "INSERT_PRE";
            description = description.replace(to_replace, insertion);
        }
        if (RUR.get_current_world().editor) {
            content = RUR.get_current_world().editor;
            if (typeof content != "string") {
                content = content.join("\n");
            }            
            insertion = "<pre class='world_info_source'>" + content + "</pre>";
            to_replace = "INSERT_EDITOR";
            description = description.replace(to_replace, insertion);
        }        
        if (RUR.get_current_world().library) {
            content = RUR.get_current_world().library;
            if (typeof content != "string") {
                content = content.join("\n");
            }            
            insertion = "<pre class='world_info_source'>" + content + "</pre>";
            to_replace = "INSERT_LIBRARY";
            description = description.replace(to_replace, insertion);
        }
        if (RUR.get_current_world().post) {
            content = RUR.get_current_world().post;
            if (typeof content != "string") {
                content = content.join("\n");
            }            
            insertion = "<pre class='world_info_source'>" + content + "</pre>";
            to_replace = "INSERT_POST";
            description = description.replace(to_replace, insertion);
        }
        if (RUR.get_current_world().onload) {
            content = RUR.get_current_world().onload;
            if (typeof content != "string") {
                content = content.join("\n");
            }            
            insertion = "<pre class='world_info_onload'>" + content + "</pre>";
            to_replace = "INSERT_ONLOAD";
            description = description.replace(to_replace, insertion);
        }
        description = description.replace("DIFFICULTY1", difficulty("difficulty1"));
        description = description.replace("DIFFICULTY2", difficulty("difficulty2"));
        description = description.replace("DIFFICULTY3", difficulty("difficulty3"));
        description = description.replace("DIFFICULTY4", difficulty("difficulty4"));
        description = description.replace("DIFFICULTY5", difficulty("difficulty5"));
        description = description.replace("DIFFICULTY6", difficulty("difficulty6"));
        description = description.replace("DIFFICULTY7", difficulty("difficulty7"));
        description = description.replace("DIFFICULTY8", difficulty("difficulty8"));
        description = description.replace("DIFFICULTY9", difficulty("difficulty9"));
        description = description.replace("DIFFICULTY10", difficulty("difficulty10"));

        // replace the default since a description was provided.
        information = "<div class='automatic-description'>" + description + "</div>";
    }

    if (show_info_at_location) {
        information = get_info_about_location() + information;
    }

    // Info about existing robots
    robots = RUR.get_current_world().robots;

    if (robots !== undefined && robots.length !== undefined){
        for (r=0; r<robots.length; r++){
            robot = robots[r];
            x = robot.x;
            y = robot.y;
            if (robot.possible_initial_positions !== undefined && robot.possible_initial_positions.length > 1){
                x = RUR.translate("random location");
                y = '';
            }
            no_object = true;
            for (obj in robot.objects){
                if (robot.objects.hasOwnProperty(obj)) {
                    if (no_object) {
                        no_object = false;
                        information += "<br><b>" + RUR.translate("A robot located here carries:").supplant({x:x, y:y}) + "</b>";
                    }
                    information += "<br>" + RUR.translate(obj) + ":" + RUR.translate(robot.objects[obj].toString());
                }
            }
            if (no_object){
                information += "<br><b>" + RUR.translate("A robot located here carries no objects.").supplant({x:x, y:y}) + "</b>";
            }
        }
    }

    // Goal: final position of the robot - only one can be specified

    goals = RUR.get_current_world().goal;
    if (goals !== undefined &&
         (goals.possible_final_positions !== undefined || goals.position !== undefined)){

        information += goal_to_achieve();
        if (goals.possible_final_positions !== undefined && goals.possible_final_positions.length > 2) {
            information += RUR.translate("The final required position of the robot will be chosen at random.");
        } else {
            information += RUR.translate("The final position of the robot must be (x, y) = ") +
                           "(" + goals.position.x + ", " + goals.position.y + ")";
        }
    }

    if (!description) {
        information = information + "</div>";
    }


    $("#World-info").html(information + '</div>');
    // automatically determined from running program
    $('.world_info_source').each(function() {
        var $this = $(this), $code = $this.text();
        $this.empty();
        var myCodeMirror = CodeMirror(this, {
            value: $code,
            mode:  RUR.state.programming_language,
            lineNumbers: !$this.is('.inline'),
            readOnly: true,
            theme: 'reeborg-readonly'
        });
    });
    $('.world_info_onload').each(function() {
        var $this = $(this), $code = $this.text();
        $this.empty();
        var myCodeMirror = CodeMirror(this, {
            value: $code,
            mode:  RUR.state.onload_programming_language,
            lineNumbers: !$this.is('.inline'),
            readOnly: true,
            theme: 'reeborg-readonly'
        });
    });

    // defined explicitly by World Creator
    $('.python').each(function() {
        var $this = $(this), $code = $this.text();
        $this.empty();
        var myCodeMirror = CodeMirror(this, {
            value: $code,
              mode: {
                name: "python",
                version: 3
              },
            lineNumbers: !$this.is('.inline'),
            readOnly: true,
            theme: 'reeborg-readonly'
        });
    });
    $('.javascript').each(function() {
        var $this = $(this), $code = $this.text();
        $this.empty();
        var myCodeMirror = CodeMirror(this, {
            value: $code,
            mode:  'javascript',
            lineNumbers: !$this.is('.inline'),
            readOnly: true,
            theme: 'reeborg-readonly'
        });
    });
    $('.html').each(function() {
        var $this = $(this), $code = $this.text();
        $this.empty();
        var myCodeMirror = CodeMirror(this, {
            value: $code,
            mode:  "htmlmixed",
            lineNumbers: !$this.is('.inline'),
            readOnly: true,
            theme: 'reeborg-readonly'
        });
    });

};


function get_info_about_location() {
    /* finds all the relevant information about a location where the
       user has clicked. */
    "use strict";
    var position, x, y, coords, grid_info, need_heading, goals;
    var tile, tilename, tiles;
    var obj, obj_here, obj_type;
    var special_info_about_location = "<h3>" + RUR.translate("Special information about this location:") + "</h3>";

    position = RUR.calculate_grid_position();
    x = position[0];
    y = position[1];
    if (isNaN(x) || isNaN(y)){
        return '';
    }

    coords = x + "," + y;
    grid_info = "<div class='grid-info'><code>x,y = " + coords + "</code><br>";

    try {
        tile = RUR.get_background_tile(x, y);
        if (tile) {
            tile = RUR.THINGS[tile];
        }
    } catch (e) {
        tile = false;
    }

    need_heading = true;
    if (tile){
        if (RUR.translate(tile.info)) {
            if (need_heading) {
                need_heading = false;
                grid_info += special_info_about_location;
            }
            grid_info += RUR.translate(tile.info) + "<br>";
        }
    }

    // obstacles at that location; same topic heading as for background tiles
    try {
        tiles = RUR.get_obstacles(x, y);
    } catch (e) {
        tiles = false;
    }
    if (tiles) {
        for (tilename of tiles) {
            tile = RUR.THINGS[tilename];
            if (RUR.translate(tile.info)){
                if (need_heading) {
                    need_heading = false;
                    grid_info += special_info_about_location;
                }
                if (tile.name == "fence") {
                    // multiple fences can be drawn at a single location to
                    // create a compount fence; the only information relevant
                    // to the user is that there is at least one fence there.
                    if (!fence_noted) {
                        fence_noted = true;
                        grid_info += RUR.translate(tile.info) + "<br>";
                    }
                } else {
                    grid_info += RUR.translate(tile.info) + "<br>";
                }
            }
        }
    }

    // objects at that location
    obj = RUR.get_current_world().objects;
    need_heading = true; // done with previous heading

    if (obj !== undefined && obj[coords] !== undefined){
        obj_here = obj[coords];
        for (obj_type in obj_here) {
            if (obj_here.hasOwnProperty(obj_type)) {
                if (need_heading) {
                    need_heading = false;
                    grid_info += "<h3>" + RUR.translate("Objects found here:") + "</h3>";
                }
                grid_info += RUR.translate(obj_type) + ":" + obj_here[obj_type];
                grid_info += " " + RUR.translate(RUR._get_property(obj_type, "info"))+"<br>";
            }
        }
    }

    // goal to achieve that that location
    goals = RUR.get_current_world().goal;
    need_heading = true; // done with previous heading

    if (goals !== undefined){
        obj = goals.objects;
        if (obj !== undefined && obj[coords] !== undefined){
            obj_here = obj[coords];
            for (obj_type in obj_here) {
                if (obj_here.hasOwnProperty(obj_type)) {
                    if (need_heading){
                        need_heading = false;
                        grid_info += goal_to_achieve();
                    }
                   grid_info += RUR.translate(obj_type) + ":" + obj_here[obj_type] + "<br>";
                }
            }
        }
        if (goals.walls !== undefined && coords) {
            if (goals.walls[coords] !== undefined){
                if (goals.walls[coords].indexOf("east") != -1) {
                    if (need_heading){
                        need_heading = false;
                        grid_info += goal_to_achieve();
                    }
                    grid_info += RUR.translate("A wall must be built east of this location.") + "<br>";
                }
                if (goals.walls[coords].indexOf("north") != -1) {
                    if (need_heading){
                        need_heading = false;
                        grid_info += goal_to_achieve();
                    }
                    grid_info += RUR.translate("A wall must be built north of this location.") + "<br>";
                }
            }
            x -= 1;
            coords = x + "," + y;
            if (goals.walls[coords] !== undefined){
                if (goals.walls[coords].indexOf("east") != -1) {
                    if (need_heading){
                        need_heading = false;
                        grid_info += goal_to_achieve();
                    }
                    grid_info += RUR.translate("A wall must be built west of this location.") + "<br>";
                }
            }
            x += 1;
            y -= 1;
            coords = x + "," + y;
            if (goals.walls[coords] !== undefined){
                if (goals.walls[coords].indexOf("north") != -1) {
                    if (need_heading){
                        need_heading = false;
                        grid_info += goal_to_achieve();
                    }
                    grid_info += RUR.translate("A wall must be built south of this location.") + "<br>";
                }
            }
            y += 1;
            coords = x + "," + y;
        }
    }

    return grid_info + '</div>';
}


$(document).ready(function () {
 RUR.create_and_activate_dialogs( $("#world-info-button"), $("#World-info"),
                                 {height:600, width:800}, RUR.world_get.world_info);
});



/** @function show_description
 * @memberof RUR
 * @instance
 *
 * @desc Ensures that the world description window 
 * (usually open from **World Info** button for English UI)
 * is shown.
 * 
 */
RUR.show_description = function () {
    if ($("#world-info-button").hasClass("blue-gradient")) {
        $("#world-info-button").click();
    }
};