# AUTOGENERATED! DO NOT EDIT! File to edit: 03_main.ipynb (unless otherwise specified).

__all__ = ['COMMANDS', 'get_direction_idx', 'parse_args', 'Runner', 'run']

# Cell
from .direction import Direction
from .robot import *
from argparse import ArgumentParser
import re

# Cell
COMMANDS = ['MOVE', 'REPORT', 'LEFT', 'RIGHT']

# Cell
def get_direction_idx(direction, directions=['NORTH', 'EAST', 'SOUTH', 'WEST']):
    "returns the index of direction passed as input from `directions`."
    return directions.index(direction.upper())

# Cell
def parse_args():
    "argument parser to accept `path` as CLI arg."
    parser = ArgumentParser()
    parser.add_argument(
        '-path',
        '--cmd_file_path',
        required=True,
        help="absolute path to the `.txt` file containing commands for the ToyRobot."
    )
    parser.add_argument(
        '-v',
        '--verbose',
        help="Whether to print out every time a direction or pos change occurs.",
        action='store_true',
        default=False
    )
    args = parser.parse_args()
    return args

# Cell
class Runner:
    """
    This class takes care of the constraints for `ToyRobot` and also calls the required commands
    for the `ToyRobot` to do the actual moving, change direction and report.

    It can be considered to be a regular function with a state `self.robot`.

    It can be called just as a function passing in a list of args or nothing at all.
    If no args are passed, then the [ArgumentParser](https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser)
    is run to get arguments from the command line. Otherwise, for testing some args can
    also be passed.

    This function reads the text file line by line, removes comma and whitespace and splits the
    string command to get actual arguments. Then based on these arguments the actual commands on
    `ToyRobot` are called.

    If 'PLACE' command is seen, then a new robot is created and assigned to self.robot if
    it is a valid 'PLACE' command.

    A valid command is one that places the `ToyRobot` inside the `Table`.

    Otherwise, if the command is not valid then no `ToyRobot` is instantiated and all other commands
    are ignored until a valid 'PLACE' command is seen.

    If there are two 'PLACE' commands inside the .txt file, then
    - both will run if they are both valid.
    - only valid command will run if one is valid.
    - no robot will be created if both are invalid.
    """

    def __init__(self):
        self.robot = None

    def __call__(self, args=None):
        "main function to run the package from command line."
        if not args:
            args = parse_args()
        # open text file from path passed as arg
        f = open(args.cmd_file_path, 'r')
        # read line by line and execute commands based on constraints in `problem.md`
        for line in f.readlines():
            # remove any extra whitespace and commas to get command
            cmds = re.findall(r'[^,\s]+', line)
            if cmds[0]=='PLACE':
                robot = ToyRobot.from_placement(
                    int(cmds[1]), int(cmds[2]), get_direction_idx(cmds[3]), args.verbose)
                if robot:
                    self.robot = robot
                    if args.verbose: self.robot.report()

            elif self.robot is not None and cmds[0] != 'PLACE' and cmds[0] in COMMANDS:
                cmd = f"self.robot.{cmds[0].lower()}()"
                exec(cmd)

# Cell
run = Runner()