package W07H07_RockPaperScissorsV2;

import java.util.Random;
import java.util.Scanner;

public class Hand  implements Comparable<Hand> {
    public static final int ROCK =      0;
    public static final int PAPER =     1;
    public static final int SCISSORS =  2;
    public static final int HANDS =     3;
    private final int form; // Possible values: ROCK, PAPER or SCISSORS
    public static final int WINS =      1;
    public static final int TIES =      0;
    public static final int LOOSES =   -1;
    private static final Random randomGenerator;
    private static final Scanner in;

    static { // Static Initialization Block
        // Executed statically only once (when the class is loaded)
        randomGenerator = new Random();
        in = new Scanner(System.in);
    }
    
    { // Instance  Initialization Block
        // Executed non-statically every time an object instance is constructed
        // It is executed before the code in the constructor method
        // Therefore, the form attribute hasn't been set yet.
        System.out.println("Hand ready!");
    }
    
    public Hand(int form) {
        this.form = form;
    }
    
    public Hand() {
        this.form = randomGenerator.nextInt(HANDS);
    }
    
    public static Hand randomHand() {
        return new Hand(randomGenerator.nextInt(HANDS));
        // Don't forget the "new" keyword. Otherwise:
        // "Cannot find symbol. Symbol: method Hand(int)"
    }
    
    public static Hand askHand() {
        String form;
        char c;
        
        do {
            System.out.println("Form? [r]ock, [p]aper or [s]cissors");
            form = in.nextLine();
            c = form.charAt(0);
        } while (c != 'r' && c != 'p' && c != 's');
        switch (c) {
            case 'r':
                return new Hand(ROCK);
            case 'p':
                return new Hand(PAPER);
            case 's':
            default:
                return new Hand(SCISSORS);
        }
    }
    
    @Override
    public int compareTo(Hand other) {
        /*
            | R| P| S| <- this          | R| P| S| <- this 
          --+--+--+--+                --+--+--+--+         
        o  R| 0| 1| 2| HANDS +      o  R| T| W| L| this:   
        t --+--+--+--+ this.form -  t --+--+--+--+ - Wins  
        h  R| 2| 0| 1| other.form   h  R| L| T| W| - Looses
        e --+--+--+--+ % HANDS      e --+--+--+--+ - Ties  
        r  R| 1| 2| 0|              r  R| W| L| T|         
          --+--+--+--+                --+--+--+--+        
        - Now Win is 1 and Loose is 2.
        */
        switch ((HANDS + this.form - other.form) % HANDS) {
            case 1:
                return WINS;
            case 2:
                return LOOSES;
            default:
                return TIES;
        }
    }
    
    @Override
    public String toString() {
        switch (form) {
            case ROCK:
                return "rock";
            case PAPER:
                return "paper";
            case SCISSORS:
            default:
                return "scissors";
        }
    }
}
