/*
 * Decompiled with CFR 0_132.
 */
package main;

import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JTabbedPane;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.filechooser.FileFilter;
import main.ChronoPanel;
import main.DialogBox;
import main.Main;
import save.Filter;
import save.Slot;
import signals.AsyncBus;
import signals.AsyncSignal;
import signals.Clock;
import signals.Signals;
import signals.SyncBus;
import signals.SyncSignal;
import useful.ButtonTabComponent;

public class ChronoWindow
extends JFrame
implements KeyListener,
ChangeListener {
    private static final long serialVersionUID = 1L;
    public static int WIDTH = 800;
    public static int HEIGHT = 500;
    public static ArrayList<ChronoPanel> chrono = new ArrayList();
    public static int active = 0;
    public static JTabbedPane tabs;
    private JMenuBar menuBar = new JMenuBar();
    JFileChooser docChooser = new JFileChooser();
    JFileChooser imgChooser = new JFileChooser();
    private JMenu file = new JMenu("File");
    private JMenuItem file_new = new JMenuItem("New");
    private JMenuItem file_open = new JMenuItem("Open");
    private JMenuItem file_save = new JMenuItem("Save");
    private JMenuItem file_save_as = new JMenuItem("Save As..");
    private JMenuItem file_export = new JMenuItem("Export to..");
    private JMenuItem file_quit = new JMenuItem("Quit");
    private JMenu add = new JMenu("Add");
    private JMenuItem add_clock = new JMenuItem("Clock");
    private JMenuItem add_sync_signal = new JMenuItem("Synchronous Signal");
    private JMenuItem add_sync_bus = new JMenuItem("Synchronous Bus");
    private JMenuItem add_async_signal = new JMenuItem("Asynchronous Signal");
    private JMenuItem add_async_bus = new JMenuItem("Asynchronous Bus");
    private JMenu tools = new JMenu("Tools");
    private JMenu tools_timeLapse = new JMenu("Time Lapse");
    private JMenuItem tools_timeLapse_add = new JMenuItem("Add");
    private JMenuItem tools_timeLapse_removeAll = new JMenuItem("Remove all");
    private JMenu tools_back_lines = new JMenu("Background Lines");
    private JMenuItem tools_back_lines_show = new JMenuItem("Show/Hide");
    private JMenu tools_antialiasing = new JMenu("Antialiasing");
    private JMenuItem tools_antialiasing_on = new JMenuItem("On/Off");
    private JMenu tools_assertion = new JMenu("Assertion");
    private JMenuItem tools_assertion_add = new JMenuItem("Add");
    private JMenuItem tools_assertion_delete_all = new JMenuItem("Delete All");

    public ChronoWindow() {
        this.setTitle("Chronogram Editor v" + Main.version);
        this.setSize(WIDTH, HEIGHT);
        this.setLocationRelativeTo(null);
        this.addKeyListener(this);
        UIManager.put("TabbedPane.borderHightlightColor", Color.BLACK);
        UIManager.put("TabbedPane.contentAreaColor", Color.WHITE);
        UIManager.put("TabbedPane.selected", Color.WHITE);
        tabs = new JTabbedPane();
        tabs.addChangeListener(this);
        tabs.setFocusable(false);
        this.docChooser.addChoosableFileFilter(new Filter(".chr", "Chronogram File"));
        this.imgChooser.addChoosableFileFilter(new Filter(".jpg, .png, .gif", ""));
        this.addComponentListener(new ComponentAdapter(){

            @Override
            public void componentResized(ComponentEvent e) {
                String sizeA = e.paramString().split(" ")[2];
                String size = "";
                int i = 0;
                while (i < sizeA.length()) {
                    if (sizeA.charAt(i) != ')') {
                        size = String.valueOf(size) + sizeA.charAt(i);
                    }
                    ++i;
                }
                ChronoWindow.WIDTH = Integer.parseInt(size.split("x")[0]);
                ChronoWindow.HEIGHT = Integer.parseInt(size.split("x")[1]);
                ChronoWindow.this.repaint();
            }
        });
        this.setDefaultCloseOperation(0);
        this.addWindowListener(new WindowAdapter(){

            @Override
            public void windowClosing(WindowEvent e) {
                ChronoWindow.this.quit();
            }
        });
        this.file_new.setAccelerator(KeyStroke.getKeyStroke(78, 2));
        this.file.add(this.file_new);
        this.file_open.setAccelerator(KeyStroke.getKeyStroke(79, 2));
        this.file.add(this.file_open);
        this.file_save.setAccelerator(KeyStroke.getKeyStroke(83, 2));
        this.file.add(this.file_save);
        this.file.add(this.file_save_as);
        this.file.addSeparator();
        this.file_export.setAccelerator(KeyStroke.getKeyStroke(69, 2));
        this.file.add(this.file_export);
        this.file.addSeparator();
        this.file.add(this.file_quit);
        this.add.add(this.add_clock);
        this.add.addSeparator();
        this.add.add(this.add_sync_signal);
        this.add.add(this.add_sync_bus);
        this.add.addSeparator();
        this.add.add(this.add_async_signal);
        this.add.add(this.add_async_bus);
        this.tools_timeLapse.add(this.tools_timeLapse_add);
        this.tools_timeLapse.add(this.tools_timeLapse_removeAll);
        this.tools.add(this.tools_timeLapse);
        this.tools_back_lines.add(this.tools_back_lines_show);
        this.tools.add(this.tools_back_lines);
        this.tools_antialiasing.add(this.tools_antialiasing_on);
        this.tools.add(this.tools_antialiasing);
        this.tools_assertion.add(this.tools_assertion_add);
        this.tools_assertion.add(this.tools_assertion_delete_all);
        this.tools.add(this.tools_assertion);
        this.initButtons();
        this.menuBar.add(this.file);
        this.menuBar.add(this.add);
        this.menuBar.add(this.tools);
        this.setJMenuBar(this.menuBar);
        this.getContentPane().add(tabs);
        this.setVisible(true);
    }

    public void initButtons() {
        this.file_new.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent arg0) {
                ChronoWindow.this.newChrono();
                ChronoWindow.this.repaint();
            }
        });
        this.file_open.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent arg0) {
                ChronoWindow.this.docChooser.setCurrentDirectory(new File("."));
                if (ChronoWindow.this.docChooser.showOpenDialog(null) == 0) {
                    File choosenFile = ChronoWindow.this.docChooser.getSelectedFile();
                    if (ChronoWindow.this.docChooser.getFileFilter().accept(choosenFile)) {
                        ChronoWindow.this.newChrono();
                        Slot.load(choosenFile);
                        int maxId = 0;
                        int i = 0;
                        while (i < ChronoWindow.chrono.get((int)ChronoWindow.active).signals.size()) {
                            maxId = Math.max(maxId, ChronoWindow.chrono.get((int)ChronoWindow.active).signals.get((int)i).id);
                            ++i;
                        }
                        Signals.setIdBank(maxId + 1);
                        ChronoWindow.chrono.get((int)ChronoWindow.active).openedFile = choosenFile;
                        ChronoWindow.chrono.get((int)ChronoWindow.active).saveFileOk = true;
                        ChronoWindow.this.changeActiveTabTitle(choosenFile.getName());
                    } else {
                        JOptionPane.showMessageDialog(null, "File extension did not match \nExptected .chr", "Error", 0);
                    }
                }
                ChronoWindow.this.repaint();
            }
        });
        this.file_save.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent arg0) {
                ChronoWindow.this.save(false, ChronoWindow.active);
            }
        });
        this.file_save_as.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent arg0) {
                ChronoWindow.this.save(true, ChronoWindow.active);
            }
        });
        this.file_export.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent arg0) {
                ChronoWindow.this.export();
            }
        });
        this.file_quit.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent arg0) {
                ChronoWindow.this.quit();
            }
        });
        this.add_clock.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent arg0) {
                DialogBox db = new DialogBox(null, "Add clock", new Clock(""));
                db.showDialog();
                if (db.name != null) {
                    if (db.clockDomain != -1 && db.ratio > 0.0f) {
                        ChronoWindow.chrono.get(ChronoWindow.active).add(new Clock(db.name, db.freq, db.clockDomain, db.ratio));
                    } else {
                        ChronoWindow.chrono.get(ChronoWindow.active).add(new Clock(db.name, db.freq));
                    }
                }
            }
        });
        this.add_sync_signal.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent arg0) {
                DialogBox db = new DialogBox(null, "Add synchronous signal", new SyncSignal(""));
                db.showDialog();
                if (db.name != null) {
                    ChronoWindow.chrono.get(ChronoWindow.active).add(new SyncSignal(db.name, db.clockDomain));
                }
            }
        });
        this.add_sync_bus.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent arg0) {
                DialogBox db = new DialogBox(null, "Add synchronous bus", new SyncBus(""));
                db.showDialog();
                if (db.name != null) {
                    ChronoWindow.chrono.get(ChronoWindow.active).add(new SyncBus(db.name, db.clockDomain));
                }
            }
        });
        this.add_async_signal.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent arg0) {
                DialogBox db = new DialogBox(null, "Add asynchronous signal", new AsyncSignal(""));
                db.showDialog();
                if (db.name != null) {
                    ChronoWindow.chrono.get(ChronoWindow.active).add(new AsyncSignal(db.name, db.freq));
                }
            }
        });
        this.add_async_bus.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent arg0) {
                DialogBox db = new DialogBox(null, "Add asynchronous bus", new AsyncBus(""));
                db.showDialog();
                if (db.name != null) {
                    ChronoWindow.chrono.get(ChronoWindow.active).add(new AsyncBus(db.name, db.freq));
                }
            }
        });
        this.tools_timeLapse_add.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent arg0) {
                if (ChronoWindow.chrono.get((int)ChronoWindow.active).nbrTimeLapse < 5) {
                    ChronoWindow.chrono.get(ChronoWindow.active).addTimeLapse();
                    ChronoWindow.this.repaint();
                } else {
                    JOptionPane.showMessageDialog(null, "Can not set more than 5 timelapses", "Error", 0);
                }
            }
        });
        this.tools_timeLapse_removeAll.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent arg0) {
                ChronoWindow.chrono.get(ChronoWindow.active).removeTimeLapse();
                ChronoWindow.this.tools_timeLapse_add.setEnabled(true);
                ChronoWindow.this.repaint();
            }
        });
        this.tools_back_lines_show.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent arg0) {
                ChronoWindow.chrono.get((int)ChronoWindow.active).displayBackLines = !ChronoWindow.chrono.get((int)ChronoWindow.active).displayBackLines;
                ChronoWindow.chrono.get((int)ChronoWindow.active).modifToSave = true;
                ChronoWindow.this.repaint();
            }
        });
        this.tools_antialiasing_on.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent arg0) {
                ChronoWindow.chrono.get((int)ChronoWindow.active).antialiasing = !ChronoWindow.chrono.get((int)ChronoWindow.active).antialiasing;
                ChronoWindow.chrono.get((int)ChronoWindow.active).modifToSave = true;
                ChronoWindow.this.repaint();
            }
        });
        this.tools_assertion_add.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent arg0) {
                ChronoWindow.chrono.get(ChronoWindow.active).newAssertion();
                ChronoWindow.chrono.get((int)ChronoWindow.active).modifToSave = true;
                ChronoWindow.this.repaint();
            }
        });
        this.tools_assertion_delete_all.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent arg0) {
                ChronoWindow.chrono.get(ChronoWindow.active).removeAssertions();
                ChronoWindow.chrono.get((int)ChronoWindow.active).modifToSave = true;
                ChronoWindow.this.repaint();
            }
        });
    }

    public void quit() {
        boolean okToQuit = true;
        int i = 0;
        while (i < chrono.size()) {
            if (ChronoWindow.chrono.get((int)i).modifToSave) {
                okToQuit = false;
            }
            ++i;
        }
        if (!okToQuit) {
            int option = JOptionPane.showConfirmDialog(null, "Some chronograms are not saved.\nExit Chronogram Editor ?", "Confirm exit", 1, 3);
            if (option != 2 && option != -1 && option == 0) {
                System.exit(0);
            }
        } else {
            System.exit(0);
        }
    }

    public void export() {
        if (ChronoWindow.chrono.get((int)ChronoWindow.active).openedFile != null) {
            this.imgChooser.setCurrentDirectory(ChronoWindow.chrono.get((int)ChronoWindow.active).openedFile.getParentFile());
            this.imgChooser.setSelectedFile(new File(ChronoWindow.chrono.get((int)ChronoWindow.active).openedFile.getName().replace("chr", "png")));
        } else {
            this.imgChooser.setCurrentDirectory(new File("."));
        }
        if (this.imgChooser.showSaveDialog(null) == 0) {
            File choosenFile = this.imgChooser.getSelectedFile();
            if (this.imgChooser.getFileFilter().accept(choosenFile)) {
                chrono.get(active).releaseSelection();
                BufferedImage bufImg = new BufferedImage((int)chrono.get(active).getSize().getWidth(), (int)chrono.get(active).getSize().getHeight(), 5);
                Graphics g = bufImg.getGraphics();
                chrono.get(active).paint(g);
                try {
                    if (choosenFile.getName().endsWith("jpg")) {
                        ImageIO.write((RenderedImage)bufImg, "JPG", choosenFile);
                    }
                    if (choosenFile.getName().endsWith("png")) {
                        ImageIO.write((RenderedImage)bufImg, "PNG", choosenFile);
                    }
                    if (choosenFile.getName().endsWith("gif")) {
                        ImageIO.write((RenderedImage)bufImg, "GIF", choosenFile);
                    }
                }
                catch (FileNotFoundException e) {
                    JOptionPane.showMessageDialog(null, "File directory error", "Error", 0);
                }
                catch (IOException e) {
                    JOptionPane.showMessageDialog(null, "Error during exportation", "Error", 0);
                }
            } else {
                JOptionPane.showMessageDialog(null, "File extension error", "Error", 0);
            }
        }
    }

    public void save(boolean saveAs, int chronoIndex) {
        if (ChronoWindow.chrono.get((int)chronoIndex).saveFileOk && !saveAs) {
            Slot.save(ChronoWindow.chrono.get((int)chronoIndex).openedFile);
            ChronoWindow.chrono.get((int)chronoIndex).modifToSave = false;
        } else {
            if (ChronoWindow.chrono.get((int)chronoIndex).openedFile != null) {
                this.docChooser.setCurrentDirectory(ChronoWindow.chrono.get((int)chronoIndex).openedFile.getParentFile());
                this.docChooser.setSelectedFile(new File(ChronoWindow.chrono.get((int)ChronoWindow.active).openedFile.getName()));
            } else {
                this.docChooser.setCurrentDirectory(new File("."));
            }
            if (this.docChooser.showSaveDialog(null) == 0) {
                File choosenFile = this.docChooser.getSelectedFile();
                String[] tmp = choosenFile.getName().split("[.]");
                String ext = "";
                if (tmp.length == 2) {
                    ext = tmp[1];
                }
                if (ext == "") {
                    choosenFile = new File(String.valueOf(choosenFile.getPath()) + ".chr");
                    System.out.println(choosenFile.getPath());
                }
                if (this.docChooser.getFileFilter().accept(choosenFile)) {
                    Slot.save(choosenFile);
                    ChronoWindow.chrono.get((int)chronoIndex).modifToSave = false;
                    ChronoWindow.chrono.get((int)chronoIndex).saveFileOk = true;
                    ChronoWindow.chrono.get((int)chronoIndex).openedFile = choosenFile;
                    this.changeActiveTabTitle(choosenFile.getName());
                } else {
                    JOptionPane.showMessageDialog(null, "File extension error", "Error", 0);
                }
            }
        }
        this.checkModifToSave();
    }

    public void newChrono() {
        chrono.add(new ChronoPanel());
        active = chrono.size() - 1;
        tabs.addTab("New", chrono.get(active));
        tabs.setTabComponentAt(active, new ButtonTabComponent("New", active));
        tabs.setSelectedIndex(active);
        ChronoWindow.chrono.get((int)ChronoWindow.active).saveFileOk = false;
    }

    public void changeActiveTabTitle(String title) {
        tabs.setTabComponentAt(active, new ButtonTabComponent(title, active));
        ChronoWindow.chrono.get((int)ChronoWindow.active).fileName = title;
    }

    public void checkModifToSave() {
        if (ChronoWindow.chrono.get((int)ChronoWindow.active).modifToSave) {
            if (!ChronoWindow.chrono.get((int)ChronoWindow.active).fileName.endsWith("*")) {
                tabs.setTabComponentAt(active, new ButtonTabComponent(String.valueOf(ChronoWindow.chrono.get((int)ChronoWindow.active).fileName) + "*", active));
                ChronoWindow.chrono.get((int)ChronoWindow.active).fileName = String.valueOf(ChronoWindow.chrono.get((int)ChronoWindow.active).fileName) + "*";
            }
        } else if (ChronoWindow.chrono.get((int)ChronoWindow.active).fileName.endsWith("*")) {
            ChronoWindow.chrono.get((int)ChronoWindow.active).fileName = ChronoWindow.chrono.get((int)ChronoWindow.active).fileName.substring(0, ChronoWindow.chrono.get((int)ChronoWindow.active).fileName.length() - 1);
            tabs.setTabComponentAt(active, new ButtonTabComponent(ChronoWindow.chrono.get((int)ChronoWindow.active).fileName, active));
        }
    }

    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == 127) {
            chrono.get(active).removeSelected();
            this.repaint();
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void stateChanged(ChangeEvent e) {
        JTabbedPane pane = (JTabbedPane)e.getSource();
        active = pane.getSelectedIndex();
    }

}

