import java.util.Set;
import java.util.HashSet;

// Abstract class for any Main

public abstract class Main {
    protected double area;
    protected double perimeter;

    public Main() {} // Empty constructor

    public double area() {
        return area;
    }

    public double perimeter() {
        return perimeter;
    }

    // Derived classes will call this to fill
    //  in the area and perimeter values;
    protected abstract void calculateValues();
}
public class Main {
    private Scanner s = new Scanner(System.in);
    private Set<String> validShapes = new HashSet<String>();

    public static void main(String[] args) {
        Main m = new Main(); // Sorry, I know this part is
        m.run();             //  sloppy programming.
    }

    public void run() {
        // Adds shape names into the validShape set
        addValidShapes();

        // Get shape name from user
        String shapeInput = getShapeInput();

        // Declare shape object
        Main shape = null;

        try {
            shape = getShapeData(shapeInput);
        } catch (Exception e) {
            System.out.println(e.getMessage());
            System.exit(-1);
        }

        String unit = getUnit();

        showShapeInfo(shape, unit);
    }

    protected void addValidShapes() {
        validShapes.add("rectangle");
        validShapes.add("square");
        validShapes.add("triangle");
        validShapes.add("circle");
    }

    public String getShapeInput() {
        System.out.print("Which shape? ");
        String shape = s.next().toLowerCase();

        if (validShapes.contains(shape)) {
            return shape;
        }

        return getShapeInput();
    }

    // Gets shape-specific data
    public Main getShapeData(String shapeInput) throws Exception {
        if (shapeInput.equals("rectangle")) {
            return getRectangleData();
        } else if (shapeInput.equals("square")) {
            return getSquareData();
        } else if (shapeInput.equals("triangle")) {
            return getTriangleData();
        } else if (shapeInput.equals("circle")) {
            return getCircleData();
        }

        throw new Exception("NoSuchShapeExcpetion");
    }

    public Rectangle getRectangleData() {
        System.out.print("Length? ");
            double length = s.nextDouble();
        System.out.print("Width? ");
            double width  = s.nextDouble();

        return new Rectangle(length, width);
    }

    public Square getSquareData() {
        System.out.print("Length? ");
            double length = s.nextDouble();

        return new Square(length);
    }

    public Triangle getTriangleData() {
        System.out.print("Base? ");
            double base   = s.nextDouble();
        System.out.print("Height? ");
            double height = s.nextDouble();
        System.out.print("Altitude Offset? ");
            double offset = s.nextDouble();

        return new Triangle(base, height, offset);
    }

    public Circle getCircleData() {
        System.out.print("Radius? ");
            double radius = s.nextDouble();

        return new Circle(radius);
    }

    public String getUnit() {
        System.out.print("Unit? ");
        return s.next();
    }

    // Outputs shape's area and perimeter info
    public void showShapeInfo(Main s, String u) {
        System.out.println("Area: " + s.area() + " " + u + " squared");
        System.out.println("Perimeter: " + s.perimeter() + " " + u);
    }
}