#  Copyright (C) 2001 Steve Howell
#  You must read the file called INFO.txt before distributing this code.
# ---
# Worlds for Karel are defined with simple text files that we parse out
# in this module.  See the worlds folder for examples.

from world import NORTH,SOUTH,EAST,WEST
from utils import L2U
DIRECTIONS = (NORTH,SOUTH,EAST,WEST)
import re

class WorldMapException(Exception):
    def __init__(self, line, str): 
        self.line = line
        self.str = str
    def __str__(self): return self.str

def checkDirection(line, dir):
    if dir not in DIRECTIONS:
        raise WorldMapException(line, 
            L2U(_("In line %d:\n%s is not a valid direction -- use N, S, E, or W"))
            % (line, dir))

def removeComment(line):
    foundComment = False
    for i in range(len(line)):
        if line[i] == "#": 
            foundComment = True
            break
    if foundComment:
        return line[:i]
    else:
        return line

def readWorld(lines, world):
    definedRobot = 0
    useGuido = False
    linenumber = 0
    worldSize = None
    for line in lines:
        linenumber += 1
        try:
            if re.search("\S", line) and not re.match("\s*#", line):
                line = removeComment(line)
                tokens = line.split()
                keyword = tokens[0].upper()
                if keyword == L2U(_('WALL')):
                    tokens = [x.upper() for x in tokens]
                    dir = tokens[3]
                    checkDirection(linenumber, dir)
                    world.setWall(*tokens[1:])
                elif keyword == L2U(_('ROBOT')):
                    if definedRobot:
                        raise WorldMapException(linenumber, L2U(_('You may only have one robot definition.')))
                    definedRobot = 1
                    if len(tokens) == 5:
                        x, y, dir, numBeepers = tokens[1:]
                    else:
                        x, y, dir = tokens[1:]
                        numBeepers = 0
                    dir = dir.upper()
                    checkDirection(linenumber, dir)
                    robotX, robotY = int(x), int(y)
                    world.positionRobot(robotX, robotY, dir)
                    if numBeepers == "unlimited":
                        world.unlimitedBeepers = True
                        numBeepers = 0
                    world.setRobotBeepers(int(numBeepers))
                elif keyword == L2U(_('BEEPERS')):
                    x, y, numBeepers = tokens[1:]
                    world.setBeepers(int(x), int(y), int(numBeepers))
                elif keyword == 'BDFL':
                    useGuido = True
                elif keyword == L2U(_('SIZE')):
                    if worldSize:
                        raise WorldMapException(linenumber,
                            L2U(_('You may only have one size statement')))
                    try:
                        avenues, streets = [int(coord) for coord in tokens[1:]]
                    except ValueError:
                        raise WorldMapException(linenumber,
                            L2U(_('Size statement should have 2 integers'))) 
                    if avenues < 7 or streets < 7:
                        raise WorldMapException(linenumber,
                            L2U(_('Size coordinates must be at least 7')))
                    worldSize = (avenues, streets)
                else:
                    raise WorldMapException(linenumber, L2U(_("Cannot understand: %s")) % line)
        except Exception,info:
            info = "Error in line %s:\n%s\n%s" % (linenumber,line,info)
            raise WorldMapException(linenumber, info)
    if not definedRobot:
        raise WorldMapException(linenumber, L2U(_("The world map seems to be missing information.")))
    world.useGuido = useGuido
    return worldSize
