// Class: MouseMazeController
//
// Author: Alyce Brady
//    Modified 21 May 2017 to add @Override
//    Modified 4 Oct 2025 to support markers and check for a stuck mouse
//
// Created on Feb 29, 2004
//
// License Information:
//   This class is free software; you can redistribute it and/or modify
//   it under the terms of the GNU General Public License as published by
//   the Free Software Foundation.
//
//   This class is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU General Public License for more details.

import edu.kzoo.grid.gui.SteppedGridAppController;

/**
 *  A <code>MouseMazeController</code> object handles the starting, stepping, and
 *  stopping operations initiated by the user using the GUI fir the
 *  mouse-in-a-maze application.
 *
 *  @author Alyce Brady
 *  @version 4 Oct 2025
 **/
public class MouseMazeController extends SteppedGridAppController
{
    private MouseMazeGUI gui;
    private Mouse mouse;
    private boolean mouseIsStuck = false;

    /** Constructs a MouseMazeController object. */
    public MouseMazeController()
    {
    }

    /** Sets the graphical user interface that the controller will
     *  communicate with as the program progresses.
     **/
    public void setGUI(MouseMazeGUI gui)
    {
        this.gui = gui;
    }

    /* (non-Javadoc)
     * @see edu.kzoo.grid.gui.SteppedGridAppController#step()
     */
    @Override
    public void step()
    {
        if ( mouse != null )
            mouse.move();
    }

    /* (non-Javadoc)
     * @see edu.kzoo.grid.gui.SteppedGridAppController#hasReachedStoppingState()
     */
    @Override
    public boolean hasReachedStoppingState()
    { 
        // Return true if mouse has found the finish location.
        if ( mouse == null )
            return true;
        if ( mouse.location().equals(gui.getMaze().getFinishLoc()) ||
             mouse.isStuck() )
        {
            System.out.println("Mouse took " + mouse.getStepCount() +
                " steps to find the cheese.");
            return true;
        }
        return false;

    }

    /* (non-Javadoc)
     * @see edu.kzoo.grid.gui.SteppedGridAppController#init()
     */
    @Override
    public void init()
    {
        Maze maze = gui.getMaze();
        if ( maze == null )
            return;

        // Clean out any left-over mouse or "been there" markers if necessary.
        cleanMaze();
            
        // Put the cheese in place if necessary;
        if ( maze.isEmpty(maze.getFinishLoc()) )
            maze.add(new Cheese(), maze.getFinishLoc());
    }

    /** Adds a mouse into the maze.
     *  (Precondition: the maze must already exist.)
     */
    protected void addMouse()
    {
        Maze maze = gui.getMaze();

        // Clean out any left-over mouse or "been there" markers if necessary.
        cleanMaze();

        // Put the new mouse in place.
        Class cls = gui.getMouseClass();
        try { mouse = (Mouse) cls.newInstance(); }
        catch (Exception e)
            { throw new IllegalArgumentException(cls.toString() +
                " is not a Mouse type with a no-parameter constructor"); };
        maze.add(mouse, maze.getStartLoc());
            
        // Reset mouseIsStuck;
        this.mouseIsStuck = false;
    }

    /** Clean out the maze (remove any mice or "been there" markers that
     *  might still be there).
     *  (Precondition: the maze must already exist.)
     */
    protected void cleanMaze()
    {
        Maze maze = gui.getMaze();
        if ( mouse != null  && mouse.grid() == maze )
        {
            maze.remove(mouse);
            mouse = null;
        }
        maze.removeMarkers();
    }

}
