import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.io.FileReader;
import java.util.Scanner;
import java.util.Locale;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.filechooser.FileFilter;
import java.io.File;

/**
 *
 * GUI fuer die 3D-Darstellung von Drahtmodellen
 * Es kann der Augenabstand verstellt werden
 * und es kuennen Wavefront obj-Files geladen werden.
 *
 * @version 1.0 vom 10.04.2011
 * @author Thomas Schaller
 */

public class DrawIt3DGUI extends JFrame {
    // Anfang Attribute
    private Board3D board1 = new Board3D();
    private JButton jBAugenabstandPlus = new JButton();
    private JButton jBAugenabstandMinus = new JButton();
    private JButton jBLoad = new JButton();
    private static JFileChooser dateiauswahldialog = new JFileChooser(System.getProperty("user.dir"));
    // Ende Attribute

    public DrawIt3DGUI(String title) {
        // Frame-Initialisierung
        super(title);
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        int frameWidth = 1026; 
        int frameHeight = 732;
        setSize(frameWidth, frameHeight);
        Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
        int x = (d.width - getSize().width) / 2;
        int y = (d.height - getSize().height) / 2;
        setLocation(x, y);
        Container cp = getContentPane();
        cp.setLayout(null);
        // Anfang Komponenten

        board1.setBounds(0, 0, 900, 700);
        cp.add(board1);
        jBAugenabstandPlus.setBounds(912, 56, 99, 25);
        jBAugenabstandPlus.setText("Augenabs. +");
        jBAugenabstandPlus.setMargin(new Insets(2, 2, 2, 2));
        jBAugenabstandPlus.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent evt) {
                    jBAugenabstandPlus_ActionPerformed(evt);
                }
            });
        jBAugenabstandPlus.setFont(new Font("Dialog", Font.PLAIN, 13));
        cp.add(jBAugenabstandPlus);
        jBAugenabstandMinus.setBounds(912, 96, 99, 25);
        jBAugenabstandMinus.setText("Augenabs. -");
        jBAugenabstandMinus.setMargin(new Insets(2, 2, 2, 2));
        jBAugenabstandMinus.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent evt) {
                    jBAugenabstandMinus_ActionPerformed(evt);
                }
            });
        jBAugenabstandMinus.setFont(new Font("Dialog", Font.PLAIN, 13));
        cp.add(jBAugenabstandMinus);
        jBLoad.setBounds(912, 192, 99, 25);
        jBLoad.setText("Bild laden");
        jBLoad.setMargin(new Insets(2, 2, 2, 2));
        jBLoad.addActionListener(new ActionListener() { 
                public void actionPerformed(ActionEvent evt) { 
                    jBLoad_ActionPerformed(evt);
                }
            });
        cp.add(jBLoad);
        // Ende Komponenten

        Punkt p1 = new Punkt(-2,-3,2);
        Punkt p2 = new Punkt(2,-3,2);
        Punkt p3 = new Punkt(2,-3,-2);
        Punkt p4 = new Punkt(-2,-3,-2);
        Punkt p5 = new Punkt(-2,2,2);
        Punkt p6 = new Punkt(2,2,2);
        Punkt p7 = new Punkt(2,2,-2);
        Punkt p8 = new Punkt(-2,2,-2);
        Punkt p9 = new Punkt(0,6,0);
        board1.addStrecke(new Strecke(p1,p2));
        board1.addStrecke(new Strecke(p2,p3));
        board1.addStrecke(new Strecke(p3,p4));
        board1.addStrecke(new Strecke(p4,p1));
        board1.addStrecke(new Strecke(p5,p6));
        board1.addStrecke(new Strecke(p6,p7));
        board1.addStrecke(new Strecke(p7,p8));
        board1.addStrecke(new Strecke(p8,p5));
        board1.addStrecke(new Strecke(p1,p5));
        board1.addStrecke(new Strecke(p2,p6));
        board1.addStrecke(new Strecke(p3,p7));
        board1.addStrecke(new Strecke(p4,p8));
        board1.addStrecke(new Strecke(p5,p9));
        board1.addStrecke(new Strecke(p6,p9));
        board1.addStrecke(new Strecke(p7,p9));
        board1.addStrecke(new Strecke(p8,p9));

        p1 = new Punkt(2,-3,1.5);
        p2 = new Punkt(6,-3,1.5);
        p3 = new Punkt(6,-3,-1);
        p4 = new Punkt(2,-3,-1);
        p5 = new Punkt(2,0,1.5);
        p6 = new Punkt(6,0,1.5);
        p7 = new Punkt(6,0,-1);
        p8 = new Punkt(2,0,-1);
        board1.addStrecke(new Strecke(p1,p2));
        board1.addStrecke(new Strecke(p2,p3));
        board1.addStrecke(new Strecke(p3,p4));
        board1.addStrecke(new Strecke(p4,p1));
        board1.addStrecke(new Strecke(p5,p6));
        board1.addStrecke(new Strecke(p6,p7));
        board1.addStrecke(new Strecke(p7,p8));
        board1.addStrecke(new Strecke(p8,p5));
        board1.addStrecke(new Strecke(p1,p5));
        board1.addStrecke(new Strecke(p2,p6));
        board1.addStrecke(new Strecke(p3,p7));
        board1.addStrecke(new Strecke(p4,p8));

        cp.setBackground(Color.black);

        setResizable(false);
        setVisible(true);
    }

    // Anfang Methoden
    public void jBAugenabstandPlus_ActionPerformed(ActionEvent evt) {
        // TODO hier Quelltext einfuegen
        board1.setAugenabstand(0.1);
        board1.repaint();

    }

    public void jBAugenabstandMinus_ActionPerformed(ActionEvent evt) {
        // TODO hier Quelltext einfuegen
        board1.setAugenabstand(-0.1);
        board1.repaint();
    }

    /** Luedt ein Wavefront obj-File. Allerdings muessen in dem obj-File
     * vorher die Punkte durch Kommas ersetzt werden.
     */
    public void jBLoad_ActionPerformed(ActionEvent evt) {
        // Dateiauswahldialog fuer *.obj Files anbieten
        dateiauswahldialog.setFileFilter(new FileFilter() {
                public boolean accept(File f) {
                    return f.getName().toLowerCase().endsWith(".obj") || f.isDirectory();
                }

                public String getDescription() {
                    return "WavaFront Obj-Dateien";
                }
            });
        // Nur weitermachen, wenn Benutzer wirklich File gewuehlt hat
        int ergebnis = dateiauswahldialog.showOpenDialog(this);
        if(ergebnis != JFileChooser.APPROVE_OPTION) { // abgebrochen
            return;
        }

        // Alte Szene lueschen
        board1.clearSzene();

        // Einlesen: plist speichert alle Punkte, slist die Kanten die schon eingefuegt sind
        ArrayList<Punkt> plist = new ArrayList<Punkt>();
        ArrayList<Long> slist = new ArrayList<Long>();

        try {
            FileReader fin = new FileReader(dateiauswahldialog.getSelectedFile());
            Scanner src = new Scanner(fin);
            String str;
            // Dateiinformation sind durch Leerzeichen getrennt. So kuennen die Werte einzeln eingelesen werden
            while (src.hasNextLine()) {
                String zeile = src.nextLine();
                Scanner scZeile = new Scanner(zeile);
                scZeile.useLocale(Locale.ENGLISH);
                if (scZeile.hasNext()) {

                    String  kennung = scZeile.next();
                    // Alles ignorieren auueer Zahlen, die nach einem "v" = Vertex oder "f" = Face kommen
                    if (kennung.equals("v")) {  // Punkt einlesen, es folgen drei Kommezahlen fuer die Koordinaten
                        plist.add(new Punkt(scZeile.nextDouble(),scZeile.nextDouble(),scZeile.nextDouble()));
                    } // end of if
                    if (kennung.equals("f")) {  // Flueche, es folgen die Nummern der Eckpunkte der Flueche => Randbegrenzungen einfuegen
                        int start;   // erster Eckpunkt, damit man am Ende die Figur schlieueen kann
                        int akt;
                        int next;
                        String eintrag = scZeile.next();
                        Scanner scEintrag = new Scanner(eintrag);
                        scEintrag.useDelimiter("/");
                        start = scEintrag.nextInt();
                        akt = start;
                        while (scZeile.hasNext()) {
                            eintrag = scZeile.next(); // nuechster Eckpunkt der Flueche
                            scEintrag = new Scanner(eintrag);
                            scEintrag.useDelimiter("/");
                            next = scEintrag.nextInt();

                            long l = akt * plist.size() + next;  // Kontrollieren, welche Kanten schon eingefuegt sind. Doppelte Kanten fuehren zur Auslueschung des Bildes
                            if (!slist.contains(l)) {
                                board1.addStrecke(new Strecke(plist.get(akt-1),plist.get(next-1)));
                                slist.add(l);
                                l = next*plist.size()+akt;         // Kante von a nach b ist die gleiche wie von b nach a
                                slist.add(l);
                            } // end of if
                            // end of if
                            akt = next;
                        } // end of while
                        // Figur schlieueen
                        long l = akt * plist.size() + start;
                        if (!slist.contains(l)) {
                            board1.addStrecke(new Strecke(plist.get(start-1),plist.get(akt-1)));
                            slist.add(l);
                            l = start*plist.size()+akt;
                            slist.add(l);
                        }

                    } // end of if
                } // end of if

            }
            fin.close();
        } catch(Exception e) {
            System.out.println(e);
        } // end of try

        board1.repaint();
    } // end of jBLoad_ActionPerformed

    // Ende Methoden

    public static void main(String[] args) {
        new DrawIt3DGUI("DrawIt3DGUI");
    }
}
