package view;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.WindowConstants;
import javax.swing.table.DefaultTableModel;

import model.Kunde;
import model.Pizza;
import model.PizzaSize;
import model.Topping;
import services.KundenService;
import services.PizzaService;
import view.util.ButtonColumn;

public class MyPizzaShop extends JFrame {
    private static final long serialVersionUID = -5421020006317002203L;

    final static String DEFAULT = "Default";
    final static String TODO = "Todo";
    final static String CONFIGURATOR = "Configurator";
    final static String PIZZALIST = "PizzaList";
    final static String CUSTOMERLIST = "CustomerList";
    final static String CUSTOMERDETAILS = "CustomerDetails";

    private Container container;
    private JPanel cards;
    PizzaListPanel pizzaListPanel;
    CustomerDetailsPanel customerDetailsPanel;
    CustomerListPanel customerListPanel;

    private String path;

    public MyPizzaShop() {
        super("My Pizza Shop");
        this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
        this.setSize(800, 600);
        KundenService kundenService = new KundenService();
        PizzaService pizzaService = new PizzaService();
        container = this.getContentPane();
        container.setLayout(new BorderLayout());
        StatusPanel statusPanel = new StatusPanel();
        container.add(statusPanel, BorderLayout.SOUTH);
        JPanel defaultPanel = new DefaultPanel();
        JPanel toDoPanel = new ToDoPanel();
        JPanel configuratorPanel = new ConfiguratorPanel(pizzaService);
        pizzaListPanel = new PizzaListPanel(pizzaService);
        customerListPanel = new CustomerListPanel(kundenService);
        customerDetailsPanel = new CustomerDetailsPanel(kundenService);

        cards = new JPanel(new CardLayout());
        cards.add(defaultPanel, DEFAULT);
        cards.add(toDoPanel, TODO);
        cards.add(configuratorPanel, CONFIGURATOR);
        cards.add(pizzaListPanel, PIZZALIST);
        cards.add(customerListPanel, CUSTOMERLIST);
        cards.add(customerDetailsPanel, CUSTOMERDETAILS);

        container.add(cards);

        ((CardLayout) (cards.getLayout())).show(cards, DEFAULT);

        this.setJMenuBar(new MenuBar(kundenService, pizzaService));
        this.addWindowListener(new java.awt.event.WindowAdapter() {
            @Override
            public void windowClosing(java.awt.event.WindowEvent windowEvent) {
                if (JOptionPane.showConfirmDialog(null,
                        "Wollen Sie das Fenster wirklich schließen?\nAlle ungespeicherten Änderungen gehen verloren!",
                        "Fenster schließen?", JOptionPane.YES_NO_OPTION,
                        JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
                    System.exit(0);
                }
            }
        });
    }

    private class StatusPanel extends JPanel {
        private static final long serialVersionUID = -5777179157927719004L;

        private StatusPanel() {
            this.setBorder(BorderFactory.createLineBorder(Color.black));
            JLabel label = new JLabel("Wilkommen");
            this.add(label);
        }
    }

    private class MenuBar extends JMenuBar {
        private static final long serialVersionUID = 7457449847994117214L;
        KundenService kundenService;
        PizzaService pizzaService;

        private MenuBar(KundenService kundenService, PizzaService pizzaService) {
            this.kundenService = kundenService;
            this.pizzaService = pizzaService;
            JMenu menu = new JMenu("Datei");
            JMenuItem open = new JMenuItem("Öffnen");
            JMenuItem quit = new JMenuItem("Beenden");
            open.addActionListener(e -> {
                new OpenDialog();
            });
            quit.addActionListener(e -> System.exit(0));
            JPanel panel = new JPanel();
            panel.add(new JLabel("Hallo, das ist ein Begrüßungstext"));
            menu.add(panel);
            menu.add(open);
            menu.add(quit);
            this.add(menu);

            JMenu configurator = new JMenu("Konfigurator");
            JMenuItem listPizzas = new JMenuItem("Zeige definierte Pizzen");
            CardLayout cl = (CardLayout) (cards.getLayout());
            listPizzas.addActionListener(e -> cl.show(cards, TODO));
            JMenuItem createPizza = new JMenuItem("Konfiguriere Pizza");
            createPizza.addActionListener(e -> cl.show(cards, CONFIGURATOR));
            JMenuItem savePizzaList = new JMenuItem("Liste Speichern");
            savePizzaList.addActionListener(e -> this.pizzaService.saveAllFromInternData());
            configurator.add(listPizzas);
            configurator.add(createPizza);
            configurator.add(savePizzaList);
            this.add(configurator);

            JMenu management = new JMenu("Verwaltung");
            JMenuItem listStaff = new JMenuItem("Liste der Mitarbeiter");
            listStaff.addActionListener(e -> cl.show(cards, TODO));
            management.add(listStaff);
            this.add(management);

            JMenu customer = new JMenu("Kunden");
            JMenuItem listCustomer = new JMenuItem("Liste der Kunden");
            listCustomer.addActionListener(e -> {
                customerListPanel.refresh();
                cl.show(cards, CUSTOMERLIST);
            });
            JMenuItem manageCustomer = new JMenuItem("Kunde hinzufügen");
            manageCustomer.addActionListener(e -> {
                customerDetailsPanel.clear();
                customerDetailsPanel.generateNewId();
                cl.show(cards, CUSTOMERDETAILS);
            });
            JMenuItem saveCustomerList = new JMenuItem("Liste Speichern");
            saveCustomerList.addActionListener(e -> {
                this.kundenService.saveAllFromInternData();
            });
            customer.add(listCustomer);
            customer.add(manageCustomer);
            customer.add(saveCustomerList);
            this.add(customer);

            JMenu order = new JMenu("Bestellung");
            JMenuItem listOders = new JMenuItem("Liste der Bestellungen");
            listOders.addActionListener(e -> cl.show(cards, TODO));
            order.add(listOders);
            this.add(order);
        }
    }

    private class OpenDialog extends JFileChooser {
        private static final long serialVersionUID = 6958059890118659301L;

        private OpenDialog() {
            this.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
            int returnVal = this.showOpenDialog(null);

            if (returnVal == JFileChooser.APPROVE_OPTION) {
                File file = this.getSelectedFile();
                path = file.getAbsolutePath();
                System.out.println("Path selected: " + file.getAbsolutePath());
            } else {
                System.out.println("Open command cancelled by user.");
            }
        }
    }

    private class DefaultPanel extends JPanel {

        private static final long serialVersionUID = 7042604402647213661L;

        private DefaultPanel() {
            this.add(new JLabel("Herzlich Wilkommen bei 'MyPizzaShop'."));
            this.add(new JLabel("Bitte wählen Sie eine Kategorie um fortzufahren."));
        }
    }

    private class ToDoPanel extends JPanel {
        private static final long serialVersionUID = 6822836519469016140L;

        private ToDoPanel() {
            this.add(new JLabel("To Do"));
        }
    }

    private class CustomerListPanel extends JPanel {

        private static final long serialVersionUID = 9065029635304808892L;
        KundenService kundenService;
        String[] columnNames = { "ID", "Name", "Vorname", "Ort", "", "", "" };
        JTable table;

        private CustomerListPanel(KundenService kundenService) {
            this.kundenService = kundenService;
            Object[][] data = this.kundenService.getTableData();

            // Add Button Text to table data
            for (int i = 0; i < data.length; i++) {
                data[i] = new Object[] { data[i][0], data[i][1], data[i][2], data[i][3], "Anzeigen", "Ändern",
                        "Löschen" };
            }
            DefaultTableModel model = new DefaultTableModel(data, columnNames);
            table = new JTable(model);

            JScrollPane scrollPane = new JScrollPane(table);
            table.setFillsViewportHeight(true);

            this.setLayout(new BorderLayout());
            JPanel bottomBar = new JPanel();
            JButton addCustomerBtn = new JButton("Füge Kunde hinzu");
            addCustomerBtn.addActionListener(e -> {
                customerDetailsPanel.clear();
                customerDetailsPanel.generateNewId();
                ((CardLayout) (cards.getLayout())).show(cards, CUSTOMERDETAILS);
            });
            bottomBar.add(wrap(addCustomerBtn));
            JButton printBtn = new JButton("Drucken");
            printBtn.addActionListener(e -> {
                System.out.println(Arrays.deepToString(kundenService.getTableData()));
            });
            bottomBar.add(wrap(printBtn));
            this.add(table.getTableHeader(), BorderLayout.PAGE_START);
            this.add(bottomBar, BorderLayout.AFTER_LAST_LINE);
            this.add(scrollPane, BorderLayout.CENTER);
            addTableButtons();
        }

        private void addTableButtons() {
            AbstractAction show = new AbstractAction() {
                private static final long serialVersionUID = 302149670181733310L;

                @Override
                public void actionPerformed(ActionEvent e) {
                    JTable table = (JTable) e.getSource();
                    int modelRow = Integer.valueOf(e.getActionCommand());
                    DefaultTableModel tableModel = (DefaultTableModel) table.getModel();
                    customerDetailsPanel.preloadData(tableModel.getValueAt(modelRow, 0).toString(),
                            tableModel.getValueAt(modelRow, 1).toString(),
                            tableModel.getValueAt(modelRow, 2).toString());
                    customerDetailsPanel.setReadOnly(true);
                    ((CardLayout) (cards.getLayout())).show(cards, CUSTOMERDETAILS);
                }
            };
            new ButtonColumn(table, show, 4);

            AbstractAction edit = new AbstractAction() {
                private static final long serialVersionUID = 302149670181733310L;

                @Override
                public void actionPerformed(ActionEvent e) {
                    JTable table = (JTable) e.getSource();
                    int modelRow = Integer.valueOf(e.getActionCommand());
                    DefaultTableModel tableModel = (DefaultTableModel) table.getModel();
                    customerDetailsPanel.preloadData(tableModel.getValueAt(modelRow, 0).toString(),
                            tableModel.getValueAt(modelRow, 1).toString(),
                            tableModel.getValueAt(modelRow, 2).toString());
                    customerDetailsPanel.setReadOnly(false);
                    customerDetailsPanel.enableEditMode();
                    ((CardLayout) (cards.getLayout())).show(cards, CUSTOMERDETAILS);
                }
            };
            new ButtonColumn(table, edit, 5);

            AbstractAction delete = new AbstractAction() {
                private static final long serialVersionUID = 302149670181733310L;

                @Override
                public void actionPerformed(ActionEvent e) {
                    JTable table = (JTable) e.getSource();
                    int modelRow = Integer.valueOf(e.getActionCommand());
                    DefaultTableModel tableModel = (DefaultTableModel) table.getModel();
                    int answer = JOptionPane.showConfirmDialog(null,
                            "Den Nutzer '" + tableModel.getValueAt(modelRow, 1).toString() + " "
                                    + tableModel.getValueAt(modelRow, 2).toString() + "' (ID: "
                                    + tableModel.getValueAt(modelRow, 0).toString() + ") wirklich löschen?",
                            "Löschen", JOptionPane.YES_NO_OPTION);
                    if (answer == 0) {
                        kundenService.delete(Integer.parseInt(tableModel.getValueAt(modelRow, 0).toString()));
                        tableModel.removeRow(modelRow);
                    }
                }
            };
            new ButtonColumn(table, delete, 6);
        }

        private void refresh() {
            Object[][] data = this.kundenService.getTableData();

            // Add Button Text to table data
            for (int i = 0; i < data.length; i++) {
                data[i] = new Object[] { data[i][0], data[i][1], data[i][2], data[i][3], "Anzeigen", "Ändern",
                        "Löschen" };
            }
            DefaultTableModel model = new DefaultTableModel(data, columnNames);
            table.setModel(model);
            addTableButtons();
        }
    }

    private class CustomerDetailsPanel extends JPanel {

        private static final long serialVersionUID = -5183867990205291443L;
        KundenService kundenService;
        JTextField id = new JTextField(20);
        JTextField name = new JTextField(20);
        JTextField lastName = new JTextField(20);
        JButton saveBtn = new JButton("Speichern");
        ActionListener saveAction = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                kundenService.create(new Kunde(Integer.parseInt(id.getText()), lastName.getText(), name.getText()));
                customerListPanel.refresh();
                ((CardLayout) (cards.getLayout())).show(cards, CUSTOMERLIST);
            }
        };
        ActionListener backAction = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                customerListPanel.refresh();
                ((CardLayout) (cards.getLayout())).show(cards, CUSTOMERLIST);
            }
        };
        ActionListener editAction = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                kundenService.update(Integer.parseInt(id.getText()), name.getText(), lastName.getText());
                customerListPanel.refresh();
                ((CardLayout) (cards.getLayout())).show(cards, CUSTOMERLIST);
            }
        };

        private CustomerDetailsPanel(KundenService kundenService) {
            this.kundenService = kundenService;
            this.setLayout(new GridLayout(4, 2));
            this.add(wrap(new JLabel("ID:")));
            id.setEditable(false);
            this.add(wrap(id));
            this.add(wrap(new JLabel("Name:")));
            this.add(wrap(name));
            this.add(wrap(new JLabel("Nachname:")));
            this.add(wrap(lastName));
            saveBtn.addActionListener(saveAction);
            this.add(wrap(saveBtn));
            JButton printBtn = new JButton("Ausdrucken");
            printBtn.addActionListener(e -> {
                System.out.println(
                        "ID: " + id.getText() + " Name: " + name.getText() + " Nachname: " + lastName.getText());
            });
            this.add(wrap(printBtn));
        }

        private void preloadData(String id, String name, String lastName) {
            this.id.setText(id);
            this.name.setText(name);
            this.lastName.setText(lastName);
        }

        private void clear() {
            this.id.setText("");
            this.name.setText("");
            this.lastName.setText("");
            this.setReadOnly(false);
        }

        private void setReadOnly(boolean readonly) {
            this.name.setEditable(!readonly);
            this.lastName.setEditable(!readonly);
            this.saveBtn.setText(readonly ? "Zurück" : "Speichern");
            this.saveBtn.removeActionListener(this.saveBtn.getActionListeners()[0]);
            this.saveBtn.addActionListener(readonly ? this.backAction : this.saveAction);
        }

        private void generateNewId() {
            this.id.setText(Integer.toString(kundenService.getUnusedId()));
        }

        private void enableEditMode() {
            this.saveBtn.removeActionListener(this.saveBtn.getActionListeners()[0]);
            this.saveBtn.addActionListener(this.editAction);
        }
    }

    private class ConfiguratorPanel extends JPanel {
        private static final long serialVersionUID = 3527260169526726295L;
        private JLabel priceLabel = new JLabel();
        private int price = 200;
        PizzaService pizzaService;

        private ConfiguratorPanel(PizzaService pizzaService) {
            this.pizzaService = pizzaService;
            this.setLayout(new GridLayout(5, 2));
            this.add(wrap(new JLabel("Name:")));
            JTextField name = new JTextField(20);
            this.add(wrap(name));
            this.add(wrap(new JLabel("Größe:")));
            String[] availPizzaSizes = new String[EnumSet.allOf(PizzaSize.class).size()];
            int i = 0;
            for (PizzaSize size : EnumSet.allOf(PizzaSize.class)) {
                availPizzaSizes[i++] = size.getName();
            }
            JList<String> pizzaSize = new JList<String>(availPizzaSizes);
            this.add(wrap(pizzaSize));
            this.add(wrap(new JLabel("Belag:")));
            String[] availToppings = new String[EnumSet.allOf(Topping.class).size()];
            i = 0;
            for (Topping topping : EnumSet.allOf(Topping.class)) {
                availToppings[i++] = topping.getName();
            }
            JList<String> toppings = new JList<String>(availToppings);
            toppings.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
            this.add(wrap(toppings));
            this.add(wrap(new JPanel()));
            this.add(wrap(priceLabel));
            JButton sendBtn = new JButton("Abschicken");
            sendBtn.addActionListener(e -> {
                if (name.getText() == "" || pizzaSize.getSelectedIndex() == -1
                        || toppings.getSelectedIndices().length == 0)
                    return;
                // List<Pizza> pizzas = PizzaIOHandler.read(null);
                List<Topping> toppingList = new ArrayList<Topping>();
                for (int t : toppings.getSelectedIndices()) {
                    toppingList.add(Topping.values()[t]);
                }
                this.pizzaService.create(
                        new Pizza(name.getText(), PizzaSize.values()[pizzaSize.getSelectedIndex()], toppingList));
                // PizzaIOHandler.write(pizzas, null);
                pizzaListPanel.refresh();
                ((CardLayout) (cards.getLayout())).show(cards, PIZZALIST);
            });
            JButton printBtn = new JButton("Ausdrucken");
            printBtn.addActionListener(e -> {
                System.out.println(Arrays.toString(pizzaService.getTableData()));
            });
            this.add(wrap(sendBtn));
            this.add(wrap(printBtn));
            setPrice(price);
        }

        public void setPrice(int price) {
            this.price = price;
            priceLabel.setText("Preis: " + price + " Cent");
        }

    }

    private class PizzaListPanel extends JPanel {

        private static final long serialVersionUID = 9065029635304808892L;
        PizzaService pizzaService;
        String[] columnNames = { "Name", "Preis", "Größe", "Toppings" };
        JTable table;

        private PizzaListPanel(PizzaService pizzaService) {
            this.pizzaService = pizzaService;
            Object[][] data = this.pizzaService.getTableData();
            DefaultTableModel model = new DefaultTableModel(data, columnNames);
            table = new JTable(model);

            JScrollPane scrollPane = new JScrollPane(table);
            table.setFillsViewportHeight(true);

            this.setLayout(new BorderLayout());
            JPanel bottomBar = new JPanel();
            JButton addPizzaBtn = new JButton("Füge Pizza hinzu");
            addPizzaBtn.addActionListener(e -> {
                ((CardLayout) (cards.getLayout())).show(cards, CONFIGURATOR);
            });
            bottomBar.add(wrap(addPizzaBtn));
            JButton printBtn = new JButton("Drucken");
            printBtn.addActionListener(e -> {
                System.out.println(Arrays.deepToString(pizzaService.getTableData()));
            });
            bottomBar.add(wrap(printBtn));
            this.add(table.getTableHeader(), BorderLayout.PAGE_START);
            this.add(bottomBar, BorderLayout.AFTER_LAST_LINE);
            this.add(scrollPane, BorderLayout.CENTER);
        }

        private void refresh() {
            Object[][] data = this.pizzaService.getTableData();
            DefaultTableModel model = new DefaultTableModel(data, columnNames);
            table.setModel(model);
        }
    }

    private JPanel wrap(Component comp) {
        JPanel panel = new JPanel();
        panel.add(comp);
        return panel;
    }
}