module gumballmachine;

import std.stdio : writeln;
import std.conv : to;

class GumballMachine
{
    static const int SOLD_OUT = 0;      // нет шариков
    static const int NO_QUARTER = 1;    // нет монетки
    static const int HAS_QUARTER = 2;   // есть монетка
    static const int SOLD = 3;          // шарик продан

    int state = SOLD_OUT;
    int count = 0;

    this(int count)
    {
        this.count = count;
        if (count > 0)
        {
            state = NO_QUARTER;
        }
    }

    void insertQuarter()
    {
        if (state == HAS_QUARTER)
        {
            writeln("You can't insert another quarter");
        }
        else if (state == NO_QUARTER)
        {
            state = HAS_QUARTER;
            writeln("You inserted a quarter");
        }
        else if (state == SOLD_OUT)
        {
            writeln("You can't insert a quarter, the machine is sold out");
        }
        else if (state == SOLD)
        {
            writeln("Please wait, we're already giving you a gumball");
        }
    }

    void ejectQuarter()
    {
        if (state == HAS_QUARTER)
        {
            writeln("Quarter returned");
            state = NO_QUARTER;
        }
        else if (state == NO_QUARTER)
        {
            writeln("You haven't inserted a quarter");
        }
        else if (state == SOLD)
        {
            writeln("Sorry, you already turned the crank");
        }
        else if (state == SOLD_OUT)
        {
            writeln("You can't eject, you haven't inserted a quarter yet");
        }
    }
 
    void turnCrank()
    {
        if (state == SOLD)
        {
            writeln("Turning twice doesn't get you another gumball!");
        }
        else if (state == NO_QUARTER)
        {
            writeln("You turned but there's no quarter");
        }
        else if (state == SOLD_OUT)
        {
            writeln("You turned, but there are no gumballs");
        }
        else if (state == HAS_QUARTER)
        {
            writeln("You turned...");
            state = SOLD;
            dispense();
        }
    }
 
    private void dispense()
    {
        if (state == SOLD)
        {
            writeln("A gumball comes rolling out the slot");
            --count;
            if (count == 0)
            {
                writeln("Oops, out of gumballs!");
                state = SOLD_OUT;
            }
            else
            {
                state = NO_QUARTER;
            }
        }
        else if (state == NO_QUARTER)
        {
            writeln("You need to pay first");
        }
        else if (state == SOLD_OUT)
        {
            writeln("No gumball dispensed");
        }
        else if (state == HAS_QUARTER)
        {
            writeln("No gumball dispensed");
        }
    }
 
    void refill(int numGumBalls)
    {
        this.count = numGumBalls;
        state = NO_QUARTER;
    }

    override string toString() const
    {
        string s;
        s ~= "\nMighty Gumball, Inc.";
        s ~= "\nJava-enabled Standing Gumball Model #2004\n";
        s ~= "Inventory: " ~ count.to!string ~ " gumball";
        if (count != 1)
        {
            s ~= "s";
        }
        s ~= "\nMachine is ";
        if (state == SOLD_OUT)
        {
            s ~= "sold out";
        }
        else if (state == NO_QUARTER)
        {
            s ~= "waiting for quarter";
        }
        else if (state == HAS_QUARTER)
        {
            s ~= "waiting for turn of crank";
        }
        else if (state == SOLD)
        {
            s ~= "delivering a gumball";
        }
        s ~= "\n";
        return s;
    }
}
