package uebung10.logo;

public class HanselGretelVisitor implements Visitor<Void> {

    private double gap;
    private double s;
    private Turtle turtle;
    private DarkForest forest;
    private State state;

    public HanselGretelVisitor(double s, Turtle turtle, DarkForest forest) {
        this.s = s;
        this.turtle = turtle;
        this.forest = forest;
    }

    @Override
    public Void visit(PenUp penUp) {
        up();
        return null;
    }

    @Override
    public Void visit(PenDown penDown) {
        down();
        return null;
    }

    @Override
    public Void visit(Turn turn) {
        turtle.turn(turn.angle);
        return null;
    }

    @Override
    public Void visit(Sequence sequence) {
        for(Stmt elem :sequence.seq) {
            elem.accept(this);
        }
        return null;
    }

    @Override
    public Void visit(Go go) {
        go(go.dist);
        return null;
    }

    private void breadCrumb() {
        // TODO Auto-generated method stub
        throw new UnsupportedOperationException("Unimplemented method 'breadCrumb'");
    }

    private void layTrail(double d) {
        forest.breadCrumb(turtle.getX(), turtle.getY());
    }

    private abstract class State {
        abstract void go(double dist);
        void up() {}
        void down() {}
        }

    private final State shortUp = new ShortUpState();// muss nicht geschrieben werden
    private final State down = new DownState();// muss nicht geschrieben werden
    private final State longUp = new State(){

        @Override
        void go(double d) {turtle.go(d);}

        @Override
        void down(){
            breadCrumb();
            state = down;
        }

    };

    private class DownState extends State{
        void go(double d){
            layTrail(d);
        }

        void up(){state = shortUp;}
    }

    //TODO
    private class ShortUpState extends State {
        void go(double d){}
        void up(){}
        void down(){}
    }


    private void go(double d) {
        state.go(d);
    }

    private void down() {
        state.down();
    }

    private void up() {
        state.up();
    }
}
