import java.io.IOException;
import java.util.Scanner;

/**
 * Frontend implements the FrontendInterface
 * It handles user interaction, parses commands, and calls the backend
 */
public class Frontend implements FrontendInterface{
    private Scanner in;
    private BackendInterface backend;

    /**
     * Constructor for Frontend
     * @param in - the Scanner to read commands from
     * @param backend - backend instance
     */
    public Frontend(Scanner in, BackendInterface backend) {
        this.in = in;
        this.backend = backend;
    }

    /**
     * Runs the main loop
     */
    @Override
    public void runCommandLoop() {
        showCommandInstructions(); // Start by showing the command intructions
        String command;
        while (true) { // main command loop
            System.out.print(": "); // prompt
            if (!in.hasNextLine()) break;
            command = in.nextLine().trim();
            if (command.equalsIgnoreCase("quit")) {
                System.out.println("Quitting program!");
                break;
            }
            try {
                processSingleCommand(command);
            } catch (Exception e) {
                System.out.println("Error: " + e.getMessage());
            }
        }

    }

    /**
     * Displays list of commands
     */
    @Override
    public void showCommandInstructions() {
        System.out.println("Lowercase words at the start are command prompts and must be correct, the uppercase words are placeholders, replace with correct information");
        System.out.println("Available commands:");
        System.out.println("  load FILEPATH");
        System.out.println("  year MAX");
        System.out.println("  year MIN to MAX");
        System.out.println("  loudness MAX");
        System.out.println("  show MAX_COUNT");
        System.out.println("  show most danceable");
        System.out.println("  help");
        System.out.println("  quit");
    }

    /**
     * Parses and runs a command
     * @param command - the command string entered by the user
     * Some notes on the expected behavior of the different commands:
     *      *     load: results in backend loading data from specified path
     *      *     year: updates backend's range of songs to return
     *      *                 should not result in any songs being displayed
     *      *     loudness: updates backend's filter threshold
     *      *                   should not result in any songs being displayed
     *      *     show: displays list of songs with currently set thresholds
     *      *           MAX_COUNT: argument limits the number of song titles displayed
     *      *           to the first MAX_COUNT in the list returned from backend
     *      *           most danceable: argument displays results returned from the
     *      *           backend's fiveMost method
     *      *     help: displays command instructions
     *      *     quit: ends this program (handled by runCommandLoop method above)
     *      *           (do NOT use System.exit(), as this will interfere with tests)
     */
    @Override
    public void processSingleCommand(String command) {
        String[] parts = command.split(" ");
        if (parts.length == 0) {
            System.out.println("Invalid command: empty input");
            return;
        }

        String keyword = parts[0].toLowerCase();

        switch (keyword) {
            case "load":
                if (parts.length < 2) {
                    System.out.println("Error: missing file path for load!");
                } else {
                    try {
                        backend.readData(parts[1]);
                        System.out.println("Data loaded from " + parts[1]);
                    } catch (IOException e) {
                        System.out.println("Error loading file: " + e.getMessage());
                    }
                }
                break;

            case "year":
                if (parts.length == 2) {
                    Integer max = Integer.parseInt(parts[1]);
                    backend.getAndSetRange(null, max);
                    System.out.println("Year range set: up to " + max);
                } else if (parts.length == 4 && parts[2].equalsIgnoreCase("to")) {
                    Integer min = Integer.parseInt(parts[1]);
                    Integer max = Integer.parseInt(parts[3]);
					if (min > max) {
                        System.out.println("Year 1 has to be smaller than Year 2");

                    } else {
                        backend.getAndSetRange(min, max);
                        System.out.println("Year range set: " + min + " to " + max);
                    }
                } else {
                    System.out.println("Error, invalid syntax for year");
                }
                break;

            case "loudness":
                if (parts.length == 2) {
                    Integer threshold = Integer.parseInt(parts[1]);
                    backend.applyAndSetFilter(threshold);
                    System.out.println("Loudness set: " + threshold);
                } else {
                    System.out.println("Error, Invalid syntax for loudness");
                }
                break;

			case "show":
                    String argument = command.substring(5).trim(); // Skip "show" and get command
                    try {
                        if (argument.equalsIgnoreCase("most danceable")) {
                            System.out.println("Most danceable songs:");
                            for (String s : backend.fiveMost()) {
                                System.out.println(" " + s);
                            }
                        } else {
                            int count = Integer.parseInt(argument);
                            System.out.println("Showing " + count + " songs:");
                            for (String s : backend.getMostDanceable(count)) {
                                System.out.println(" " + s);
                            }
                       }
                    } catch (IllegalStateException e) {
                        System.out.println("Error: No data loaded. Load data please!");
                    } catch (NumberFormatException e) {
                        System.out.println("Error, invalid syntax for show");
                    }
                    break;


            case "help":
                showCommandInstructions();
                break;

            default:
                System.out.println("Unknown command: " + keyword);
        }
    }
}


