package ru.kirillius.cooler.controller.CLI;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;

public abstract class Menu<T> {
    private final String name;
    private final List<MenuItem<T>> items = new ArrayList<>();
    private boolean closed = false;

    public Menu(String name) {
        this.name = name;
    }

    protected final void add(MenuItem<T> item) {
        items.add(item);
    }

    protected final void removeAll() {
        items.clear();
    }

    public final T selectByName(String name) {
        for (MenuItem<T> item : items) {
            if (item.render().equals(name)) {
                return item.select();
            }
        }

        return show();
    }

    public final T show() {
        T value = null;
        closed = false;
        do {
            System.out.println("-=[" + name + "]=-");
            StringJoiner joiner = new StringJoiner("\r\n");
            int i = 1;
            for (var item : items) {
                joiner.add("[" + (i++) + "] " + item.render());
            }
            System.out.println(joiner);
            System.out.print("Your input: ");
            try {
                String line = ConsoleApp.input.readLine();
                try {
                    int index = Integer.parseInt(line) - 1;
                    if (index < 0 || index >= items.size()) throw new NumberFormatException("Number is out of range");

                    var item = items.get(index);
                    value = OnSelect(index, item, item.select());
                } catch (NumberFormatException nfe) {
                    System.err.println("Invalid number: " + line);
                }
            } catch (IOException e) {
                return null;
            }
        } while (!closed);
        return value;
    }

    protected T OnSelect(int index, MenuItem<T> item, T value) {
        close();
        return value;
    }

    public final void close() {
        closed = true;
    }


    public String getName() {
        return name;
    }
}
