//~--- non-JDK imports --------------------------------------------------------

import Dating.Time;

import Exceptions.*;

import LAF.LAF;

//Imports für m4a-Codec
import org.jaudiotagger.audio.*;
import org.jaudiotagger.audio.exceptions.*;
import org.jaudiotagger.tag.*;

//~--- JDK imports ------------------------------------------------------------

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;

import java.io.*;

import javax.imageio.*;

import javax.swing.*;

public class audiobook extends JFrame implements ActionListener {

    // Componenten deklarieren
    private static Dimension ScreenSize = Toolkit.getDefaultToolkit().getScreenSize();
    static audiobook         maker;
    private boolean          hasImage = false;
    private Time             time     = new Time(0, 0, 0);
    private BufferedImage    Cover;
    private String           CoverName;
    private JPanel           buttonPanel;
    private ButtonGroup      chapterGroup;
    private JButton          chooseImage;
    private JButton          create;
    private File[]           files;
    private JButton          output;
    private String           outputFolder;
    private JLabel           selectedFolder;
    private JLabel           selectedImage;
    private JRadioButton     typeSelf;
    private JRadioButton     useFilenames;
    private JRadioButton     useNumbers;

    // Konstruktor
    public audiobook() {
        this("iPod Audiobook Maker");
    }

    public audiobook(String s) {
        super(s);
        initComponents();
    }

    public void initComponents() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setIconImage(new ImageIcon(this.getClass().getResource("/Data\\icon.gif")).getImage());
        setLayout(new FlowLayout());

//      labelPanel zeigt ausgewählten Ordner und Cover an
        JPanel labelPanel = new JPanel(new FlowLayout());

        selectedFolder = new JLabel("Ordner: <Keiner> -");
        selectedImage  = new JLabel("Cover: <Keins>");
        labelPanel.add(selectedFolder);
        labelPanel.add(selectedImage);

//      Das buttonPanel ist das Panel in dem alle Komponenten angezeigt werden
        buttonPanel  = new JPanel(new GridLayout(0, 1));
        chooseImage  = new JButton("Cover auswählen");
        output       = new JButton("Ordner");
        create       = new JButton(".POD Datei erstellen");
        chapterGroup = new ButtonGroup();

//      Die Radiobuttons um die Art der Kapitelbezeichnung zu wählen
        useNumbers   = new JRadioButton("Kapitel durchnummerieren", true);
        useFilenames = new JRadioButton("Dateinamen als Kapitelnamen verwenden", false);
        typeSelf     = new JRadioButton("Kapitel selber benennen", false);

//      Tooltips der Radiobuttons
        output.setToolTipText(
            "<html><head></head><body><b>Der Name des Unterordners im Slideshow Assembler-Verzeichnis</b>, in dem die Audiodateien liegen<br />"
            + "und in dem die .POD Datei und die .m4b Datei gespeichert werden sollen</body></html>");
        chooseImage.setToolTipText("Der Name der Bilddatei im \"Ordner\", die als Cover verwendet werden soll");
        useNumbers.setToolTipText("Die Namen der Kapitel werden \"001, 002, ...\" genannt");
        useFilenames.setToolTipText(
            "<html><head></head><body>Die Namen der Kapitel werden nach den Namen der dazugehörigen Dateien benannt.<br />"
            + "Oft werden die Namen dadurch <b>besonders lang</b>.</body></html>");
        typeSelf.setToolTipText("Kapitelnamen selber angeben");

//      Den Buttons ActionListener registrieren
        chooseImage.addActionListener(this);
        output.addActionListener(this);
        create.addActionListener(this);

//      Hinzufügen zur Radiobutton group
        chapterGroup.add(useNumbers);
        chapterGroup.add(useFilenames);
        chapterGroup.add(typeSelf);

//      Hinzufügen zum Buttonpanel
        buttonPanel.add(labelPanel);
        buttonPanel.add(output);
        buttonPanel.add(chooseImage);
        buttonPanel.add(create);
        buttonPanel.add(useNumbers);
        buttonPanel.add(useFilenames);
        buttonPanel.add(typeSelf);

//      Buttonpanel zum Hauptfenster hinzufügen
        add(buttonPanel);

//      Größe, Position, ... des Fensters einstellen
        pack();
        setLocation((ScreenSize.width - getWidth()) / 2, (ScreenSize.height - getHeight()) / 2);
        setResizable(true);
        setVisible(true);
    }

    public static void main(String[] args) {

//      Auswählen des Look-and-Feels
        LAF.setLAF(LAF.Mac);

//      Neues audiobook-Fenster erzeugen
        maker = new audiobook();
    }

    public void actionPerformed(ActionEvent e) {

//      ActionListener um den Ordner auszuwählen
        if (e.getActionCommand().equals("Ordner")) {

//          Input-Dialog anzeigen um den Namen einzugeben
            outputFolder = JOptionPane.showInputDialog(null, "Bitte Namen des Ordners angeben", "Eingabe",
                    JOptionPane.PLAIN_MESSAGE);

//          Überprüfen ob der Ordner existiert
            try {
                File f = new File(outputFolder);

                if (!f.exists() ||!f.isDirectory()) {

//                  Exception falls der Ordner nicht existiert
                    throw new FolderException();
                }

//              Alle passenden Dateien zum files-Array hinzufügen
                files = f.listFiles(new FileFilter() {
                    public boolean accept(File pathname) {
                        return pathname.getName().endsWith(".m4a");
                    }
                });
                selectedFolder.setText("Ordner: " + outputFolder + " -");
                selectedFolder.repaint();

//              Abfangen der Exception falls der Ordner nicht existiert
            } catch (FolderException exc) {
                JOptionPane.showMessageDialog(null, "Ordner wurde nicht gefunden", "Fehler", JOptionPane.ERROR_MESSAGE);
                outputFolder = null;
            }
        }

//      ActionListener um das Cover auszuwählen
        if (e.getActionCommand().equals("Cover auswählen")) {

//          Ausgabeordner auf Existenz überprüfen
            if (outputFolder != null) {

//              Input-Dialog um Dateinamen anzugeben
                String s = JOptionPane.showInputDialog(null, "Bitte Namen der Bilddatei eingeben", "Eingabe",
                               JOptionPane.PLAIN_MESSAGE);

                try {
                    if (s == null) {

//                      Abbruchbefehl des Dialogs behandeln
                        throw new IOException("go");
                    }

//                  Auf falsche Dateiendungen reagieren
                    if (!s.toLowerCase().endsWith(".jpg")) {
                        if (!s.toLowerCase().endsWith(".png")) {
                            throw new EndingException();
                        }
                    }

                    Cover         = ImageIO.read(new File(outputFolder + "\\" + s));
                    this.hasImage = true;
                    selectedImage.setText("Cover: " + s);
                }

//              Behandeln möglicher Fehler (falsche Dateiendung, Bilddatei existiert nicht)
//              Falls Abbruchbefehl gewählt wurde, keine Reaktion
                catch (IOException exc) {
                    if (!exc.getMessage().equals("go")) {
                        Cover = null;
                        JOptionPane.showMessageDialog(null, "Bilddatei wurde nicht gefunden", "Fehler",
                                                      JOptionPane.WARNING_MESSAGE);
                        this.hasImage = false;
                    }
                } catch (EndingException exc) {
                    JOptionPane.showMessageDialog(null, "Das Cover muss eine .jpg oder .png Datei sein", "Fehler",
                                                  JOptionPane.ERROR_MESSAGE);
                    Cover         = null;
                    this.hasImage = false;
                }

                if (Cover != null) {
                    this.hasImage  = true;
                    this.CoverName = s;
                }
            } else {
                JOptionPane.showMessageDialog(null, "Bitte geben sie zuerst einen Ausgabeordner an", "Fehler",
                                              JOptionPane.ERROR_MESSAGE);
            }
        }

//      Funktion um .POD Datei zu erstellen
        if (e.getActionCommand().equals(".POD Datei erstellen")) {

//          Cursor auf Arbeitscursor stellen
            this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

//          Ordner, Cover überprüfen
            try {
                if (outputFolder == null) {
                    throw new NoFolderSelectedException();
                }

                if (!hasImage) {
                    if (JOptionPane.showConfirmDialog(null,
                                                      "Es wurde kein Cover ausgewählt.\nDatei trotzdem erstellen?",
                                                      "Kein Cover", JOptionPane.YES_OPTION) == JOptionPane.NO_OPTION) {
                        throw new EndingException();
                    }
                }

//              Zählvariable
                int i = 0;

                try {
                    FileWriter     fWriter = new FileWriter(outputFolder + "\\Podcast.POD");
                    BufferedWriter writer  = new BufferedWriter(fWriter);

//                  angegebene Informationen (Ordnername, Bild, Bildmaße, Dateianzahl) in die Datei schreiben
                    writer.write("[Podcast]\n");
                    writer.write("altfolder1=" + outputFolder + "\n");
                    writer.write("basename=" + outputFolder + "\n");
                    writer.write("audiobook=true" + "\n");

                    if (this.hasImage) {
                        writer.write("artwork=" + CoverName + "\n");
                        writer.write("imgwidth=" + Cover.getWidth() + "\n");
                        writer.write("imgheight=" + Cover.getHeight() + "\n");
                    }

                    writer.write("editpointcount=" + files.length + "\n\n\n");

//                  "Editpoint" für jede Musikdatei in .POD Datei schreiben
                    for (i = 0; i < files.length; i++) {
                        writer.write("[Editpoint_" + (i + 1) + "]\n");

                        if (this.hasImage) {
                            writer.write("image=" + CoverName + "\n");
                        }

                        writer.write("audiofile=" + files[i].getName() + "\n");

//                      Kapitelnamen durchnummerieren
                        if (useNumbers.isSelected()) {
                            writer.write("chapter=");

                            if ((i + 1) < 100) {
                                writer.write("0");

                                if ((i + 1) < 10) {
                                    writer.write("0");
                                }
                            }

                            writer.write((i + 1) + "\n");

//                          Dateinamen als Kapitelnamen
                        } else if (useFilenames.isSelected()) {
                            writer.write("chapter=" + files[i].getName() + "\n");

//                          Kapitelnamen selber angeben
                        } else if (typeSelf.isSelected()) {
                            String s = JOptionPane.showInputDialog(null,
                                           "Kapitelname der Datei " + files[i].getName() + " angeben (" + (i + 1)
                                           + " von " + files.length + ")", "Kapitelnamen eingeben",
                                               JOptionPane.PLAIN_MESSAGE);

                            if (s == null) {
                                throw new EndingException();
                            }

                            writer.write("chapter=" + s + "\n");
                        }

//                      Startzeit des Kapitels schreiben
                        writer.write("start=" + time.asString() + ".00\n\n");

//                      Dauer der Datei zur gesammtzeit addieren
                        AudioFile af = AudioFileIO.read(files[i]);

                        time.add(0, 0, af.getAudioHeader().getTrackLength());
                    }

                    writer.close();
                    JOptionPane.showMessageDialog(null, "Fertig!\nDas Program schließt automatisch", "Fertig",
                                                  JOptionPane.INFORMATION_MESSAGE);
                    System.exit(0);

//                  Reagieren auf Fehler(Datei nicht lesbar, fehlender Ausgabeordner, anderes)
                } catch (CannotReadException exc) {
                    JOptionPane.showMessageDialog(null,
                                                  "<html><head></head><body>Die Datei<br><b>" + files[i]
                                                  + "</b><br>konnte nicht gelesen werden</body></html>", "Fehler",
                                                      JOptionPane.ERROR_MESSAGE);
                } catch (TagException exc) {
                    JOptionPane.showMessageDialog(
                        null,
                        "<html><head></head><body>Es ist ein unbekannter Fehler bei der Datei<br><b>" + files[i]
                        + "</b><br>aufgetreten</body></html>", "Fehler", JOptionPane.ERROR_MESSAGE);
                } catch (ReadOnlyFileException exc) {
                    JOptionPane.showMessageDialog(null,
                                                  "<html><head></head><body>Die Datei<br><b>" + files[i]
                                                  + "</b><br>ist eine Read-Only Datei</body></html>", "Fehler",
                                                      JOptionPane.ERROR_MESSAGE);
                } catch (InvalidAudioFrameException exc) {
                    JOptionPane.showMessageDialog(
                        null,
                        "<html><head></head><body>Es ist ein unbekannter Fehler bei der Datei<br><b>" + files[i]
                        + "</b><br>aufgetreten</body></html>", "Fehler", JOptionPane.ERROR_MESSAGE);
                } catch (IOException exc) {
                    JOptionPane.showMessageDialog(null, "Es ist ein unbekannter Fehler aufgetreten", "Fehler",
                                                  JOptionPane.ERROR_MESSAGE);
                }
            } catch (NoFolderSelectedException exc) {
                JOptionPane.showMessageDialog(null, "Bitte wählen sie einen Ausgabeordner an", "Fehler",
                                              JOptionPane.ERROR_MESSAGE);
            } catch (EndingException exc) {}

//          Cursor auf Std setzen
            this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
        }
    }
}


//~ Formatted by Jindent --- http://www.jindent.com
