"""Classes representing robots in a simulation"""
# MCS 275 Spring 2022 Emily Dumas
# Lecture 5

import plane
import random

class Bot:
    """Base class for all robots.  Sits in one place forever."""
    def __init__(self,position):
        """Setup with initial position `position` (a plane.Point2 instance)"""
        self.alive = True
        if not isinstance(position,plane.Point2):
            raise TypeError("`postition` must be a Point2")
        self.position = position # intended to be a plane.Point2 instance

    def move(self,v):
        "Move the position of this Bot by Vector2 `v`"
        self.position = self.position + v

    def __str__(self):
        """Human-readable string representation"""
        return "{}(position=({},{}),alive={})".format(
            self.__class__.__name__,
            self.position.x,
            self.position.y,
            self.alive
        )

    def __repr__(self):
        """Unambiguous string representation"""
        return str(self)

    def update(self):
        """Advance one time step (by doing nothing)"""


class WanderBot(Bot):
    """A robot that wanders randomly"""
    steps = [ plane.Vector2(1,0), plane.Vector2(-1,0), plane.Vector2(0,1), plane.Vector2(0,-1) ]
    def update(self):
        """Take one random step"""
        self.move(random.choice(self.steps))


class HorizontalWanderBot(WanderBot):
    """A robot that wanders randomly along a horizontal line"""
    # Because we inherit from WanderBot, all we need to do is
    # change the value of class attribute `steps`.
    steps = [ plane.Vector2(1,0), plane.Vector2(-1,0) ]


class DestructBot(Bot):
    """A robot that sits for a while and then self-destructs"""
    def __init__(self,position,lifetime):
        """
        Initialize bot with position `position` (Point2) and
        which will sit there for `lifetime` steps
        """
        # super() # returns an object that behaves like self, but
                 # is a Bot, not a DestructBot
        super().__init__(position)  # call constructor of Bot
        self.lifetime = lifetime
        self.remaining = self.lifetime
        if self.lifetime <= 0:
            self.alive = False

    def __str__(self):
        """Human-readable string representation"""
        return "{}(position=({},{}),lifetime={},remaining={})".format(
            self.__class__.__name__,
            self.position.x,
            self.position.y,
            self.lifetime,
            self.remaining
        )

    def update(self):
        "Sit still and possibly self-destruct"
        if not self.alive:
            return
        self.remaining -= 1
        if self.remaining <= 0:
            # self-destruct
            self.alive = False

class PatrolBot(Bot):
    """A robot walks back and forth forever"""
    def __init__(self,position,step,numsteps):
        """
        Initialize a PatrolBot starting at `position`,
        taking steps given by Vector2 `step`, and turning
        around after `numsteps` steps.
        """
        super().__init__(position)
        self.step = step
        self.numsteps = numsteps
        self.curstep = 0

    def __str__(self):
        """Human-readable string representation"""
        return "{}(position=({},{}),step={},numsteps={},curstep={})".format(
            self.__class__.__name__,
            self.position.x,
            self.position.y,
            self.step,
            self.numsteps,
            self.curstep
        )

    def update(self):
        "Take one step and possibly turn around"
        if self.curstep == self.numsteps:
            self.step = -1*self.step # reverse direction
            self.curstep = 0 # reset the step counter
        self.move(self.step)
        self.curstep += 1


