/*
 * This source file was generated by the Gradle 'init' task
 */
package org.example;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Optional;
import java.util.Random;
import java.util.Scanner;

enum PrizeLevel {
    NORMAL,
    RARE,
    EPIC,
    LEGENDARY,
    EMPTY,
}

class Ball extends Object {
    String name;
    String colour;
    String description;
    String prize = null;

    String formatPrize() {
        return prize == null ? "... nothing" : " " + prize;
    }

    @Override
    public String toString() {

        return String.format("%s (%s), it contains %s.", name, colour, formatPrize());
    }

    public String toDescriptionString() {
        return String.format("%s (%s), it contains %s\n%s", name, colour, formatPrize(), description);
    }

    public Ball(PrizeLevel level, String colour, String desc, String prize) {
        switch (level) {
            case NORMAL:
                this.name = "Normal Prize Ball";
                break;
            case RARE:
                this.name = "Rare Prize Ball";
                break;
            case EPIC:
                this.name = "Epic Prize Ball";
                break;
            case LEGENDARY:
                this.name = "Legendary Prize Ball";
                break;
            default:
                this.name = "Empty Ball";
                break;
        }
        this.colour = colour;
        this.description = desc;
        this.prize = prize;
    }
}

class BallFactory {
    PrizeLevel level;
    String colour;
    String description;
    HashMap<String, Integer> prizes;
    int numBalls;

    public BallFactory(PrizeLevel level, String colour, String description, String[] prizes, int number) {
        this.level = level;
        this.colour = colour;
        this.description = description;
        int each = number / prizes.length;
        int error = number % prizes.length;
        System.out.println("each: " + each + " error: " + error);
        HashMap<String, Integer> myPrizes = new HashMap<>();
        for (String prize : prizes) {
            myPrizes.put(prize, each);
        }
        for (int i = 0; i < error; i++) {
            String randKey = prizes[new Random().nextInt(prizes.length)];
            myPrizes.put(randKey, myPrizes.get(randKey) + 1);
        }
        this.prizes = myPrizes;
        System.out.println(this.prizes);
        this.numBalls = number;

    }

    public Ball[] makePrizeBalls() {
        Ball[] balls = new Ball[numBalls];
        Random r = new Random();
        for (int i = 0; i < balls.length; i++) {
            ArrayList<String> available = new ArrayList<String>(prizes.keySet());
            System.out.println(this.prizes);
            int sel = r.nextInt(available.size());
            System.out.println(available.get(sel));
            balls[i] = new Ball(level, colour, description, available.get(sel));
            System.out.println("a ball has been made: " + balls[i]);
            prizes.put(available.get(sel), prizes.get(available.get(sel)) - 1);
            prizes.entrySet().removeIf(entry -> entry.getValue() <= 0); // NOTE: Here I had to use AI because
                                                                        // `ConcurrentModificationException` keeps being
                                                                        // thrown.
        }
        return balls;

    }

    class BallMachine extends Object {
        Ball[] balls;

        public void showBalls() {
            for (Ball ball : balls) {
                System.out.println(ball);
            }
        }
    }
}

public class App {
    public static void main(String[] args) {
        String filename;
        if (args.length < 1) {
            System.out.println("A file name was not specified when starting the application. Provide it here: ");
            Scanner sc = new Scanner(System.in);
            filename = sc.nextLine();
            sc.close();
        } else {
            filename = args[0];
        }
        File file = new File(filename);
        try {
            Scanner fileReader = new Scanner(file);
            ArrayList<String> lines = new ArrayList<>();
            ArrayList<Ball> balls = new ArrayList<>();
            while (fileReader.hasNext()) {
                lines.add(fileReader.nextLine());
            }
            for (int i = 0; i < lines.size(); i++) {
                System.out.println("parsing " + lines.get(i));
                if (lines.get(i).matches("[A-Z]* [A-Z]* BALL \\[[\\d]*\\]")) {
                    // A ball collection starts
                    String[] ballNameParts = lines.get(i).split(" ");
                    PrizeLevel level = PrizeLevel.valueOf(ballNameParts[0]);
                    int numBalls = Integer.parseInt(ballNameParts[3].replace("[", "").replace("]", ""));
                    String colour = lines.get(i + 1);
                    System.out.println("colour: " + colour);
                    String desc = lines.get(i + 2);
                    String prize = null;
                    if (!(level.equals(PrizeLevel.EMPTY))) {
                        // ball has prize
                        prize = lines.get(i + 3);
                    }

                    BallFactory factory = new BallFactory(level, colour, desc,
                            prize.replace("{", "").replace("}", "").split(", "), numBalls);
                    balls.addAll(Arrays.asList(factory.makePrizeBalls()));
                }
            }
            for (Ball b : balls) {
                System.out.println("ball: " + b.toDescriptionString());
            }
            fileReader.close();
        } catch (FileNotFoundException e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }
}
