import java.io.*;
import java.nio.channels.FileChannel;
import java.util.*;

class cmdList implements Command{
    @Override
    public void execute(String[] cmd) {
        String cmp = "name";
        if(cmd.length>1){
            String basedOn = cmd[1];
            if(BeerParser.comps.containsKey(basedOn)){
                cmp = basedOn;
            }
            /*if(basedOn.equals("name")){
                BeerParser.list.sort((b1, b2) -> b1.getName().compareTo(b2.getName()));
            } else if(basedOn.equals("strength")){
                BeerParser.list.sort((b1,b2) -> Double.compare(b1.getStrength(),b2.getStrength()));
            } else if(basedOn.equals("style")){
                BeerParser.list.sort((b1, b2) -> b1.getStyle().compareTo(b2.getStyle()));
            }*/
        }
        BeerParser.list.sort(BeerParser.comps.get(cmp));

        for(int i = 0; i< BeerParser.list.size(); i++){
            System.out.println(BeerParser.list.get(i)+"\n----------------\n");
        }
    }
}

class cmdAdd implements Command{
    @Override
    public void execute(String[] cmd) {
        BeerParser.list.add(new Beer(cmd[1],cmd[2],Double.parseDouble(cmd[3])));
    }
}

class cmdSearch implements Command{
    @Override
    public void execute(String[] cmd) {
        String basedOn = "name";
        String param="";
        if(cmd.length==2){
            param = cmd[1];
        } else {
            basedOn = cmd[1];
            param = cmd[2];
        }

        if(basedOn.equals("name")){
            for (Beer beer : BeerParser.list) {
                if(beer.getName().equals(param)){
                    System.out.println(beer+"\n----------------\n");
                }

            }
        } else if(basedOn.equals("style")){
            for (Beer beer : BeerParser.list) {
                if(beer.getStyle().equals(param)){
                    System.out.println(beer+"\n----------------\n");
                }

            }
        } else if(basedOn.equals("strength")){
            for (Beer beer : BeerParser.list) {
                if(beer.getStrength() == Double.parseDouble(param)){
                    System.out.println(beer+"\n----------------\n");
                }

            }
        }
    }
}

class cmdFind implements Command{
    @Override
    public void execute(String[] cmd) {
        String basedOn = "name";
        String param="";
        if(cmd.length==2){
            param = cmd[1];
        } else {
            basedOn = cmd[1];
            param = cmd[2];
        }

        if(basedOn.equals("name")){
            for (Beer beer : BeerParser.list) {
                if(beer.getName().contains(param)){
                    System.out.println(beer+"\n----------------\n");
                }

            }
        } else if(basedOn.equals("style")){
            for (Beer beer : BeerParser.list) {
                if(beer.getStyle().contains(param)){
                    System.out.println(beer+"\n----------------\n");
                }

            }
        } else if(basedOn.equals("strength")){
            for (Beer beer : BeerParser.list) {
                if(beer.getStrength() >= Double.parseDouble(param)){
                    System.out.println(beer+"\n----------------\n");
                }

            }
        } else if(basedOn.equals("weaker")){
            for (Beer beer : BeerParser.list) {
                if(beer.getStrength() <= Double.parseDouble(param)){
                    System.out.println(beer+"\n----------------\n");
                }

            }
        }
    }
}

class cmdDelete implements Command{
    @Override
    public void execute(String[] cmd) {
        String param = cmd[1];
        Iterator<Beer> it = BeerParser.list.iterator();

        while(it.hasNext()){
            if(it.next().getName().equals(param)){
                it.remove();
            }
        }
    }
}

class cmdLoad implements Command{
    @Override
    public void execute(String[] cmd) {
        BeerParser.list.clear();
        String filename = cmd[1];
        try {
            FileInputStream file = new FileInputStream(filename);
            ObjectInputStream in = new ObjectInputStream(file);
            BeerParser.list = (ArrayList<Beer>) in.readObject();

            in.close();
            file.close();

        } catch (IOException ex) {
            System.out.println("IOException hiba!");
        } catch (ClassNotFoundException ex) {
            System.out.println("ClassNotFoundException hiba! (Nincs beer class)");
        }
    }
}

class cmdSave implements Command{
    @Override
    public void execute(String[] cmd) {
        String filename = cmd[1];

        try {
            FileOutputStream file = new FileOutputStream(filename);
            ObjectOutputStream out = new ObjectOutputStream(file);
            out.writeObject(BeerParser.list);
            out.close();
            file.close();
            System.out.println("Serializálás sikeres.");

        } catch (IOException ex) {
            System.out.println("IOException hiba!");
        }
    }
}


public class BeerParser{

    private final Scanner scanner = new Scanner(System.in);

    public static ArrayList<Beer> list = new ArrayList<>();

    private static HashMap<String, Command> commands = new HashMap<>();

    public static HashMap<String, Comparator<Beer>> comps = new HashMap<>();

    BeerParser(){
        upload();
    }
    void startParsing(){

        while (true) {
            String input = scanner.nextLine();
            String[] cmd = input.split(" ");

            if(commands.containsKey(cmd[0])){
                commands.get(cmd[0]).execute(cmd);
            }

        }
    }
    private static void upload() {
        commands.put("list", new cmdList());
        commands.put("add", new cmdAdd());
        commands.put("load", new cmdLoad());
        commands.put("save", new cmdSave());
        commands.put("search", new cmdSearch());
        commands.put("find", new cmdFind());
        commands.put("delete", new cmdDelete());
        commands.put("exit", cmd -> System.exit(0));

        comps.put("name",new NameComparator());
        comps.put("strength",new StrengthComparator());
        comps.put("style",new StyleComparator());
    }

}
