package einkaufsliste5;

import java.io.IOException;

import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Choice;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.List;
import javax.microedition.lcdui.TextField;
import javax.microedition.lcdui.Ticker;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;

public class EinkaufsListeUI extends MIDlet {

    private List dispList;
    private Display display;
    private Command exitCom;
    private Command insertCom;
    private Command deleteCom;
    private Form newArticleForm;
    private RecordStore store;
    private final String RECORD_NAME = "einkaufsliste";
    
    /**
     * Konstruktor, der die UI-Elemente erstellt, den RecordStore öffnet
     * oder ggf. einen neuen anlegt.
     *
     * @author Ralf Kunze (rkunze@uos.de), Institut fuer Informatik, Universitaet
     *         Osnabrueck
     * @date 29.06.2007
     */
    public EinkaufsListeUI() {
        
        // Liste erstellen
        dispList = new List("Einkaufsliste", Choice.MULTIPLE);
        
        // RecordStore öffnen
        try {
            store = RecordStore.openRecordStore(RECORD_NAME, true,
                    RecordStore.AUTHMODE_PRIVATE, true);

            
            if (store.getNumRecords() == 0) {   // Falls kein Eintrag vorhanden ...
                createNewList();                // Neue Liste erstellen
            } else {                            // Falls Einträge vorhanden
                loadList();                     // Liste laden
            }

        } catch (Exception e1) {
            alert("Konstruktor: Daten können nicht gespeichert werden!", e1);
        }
        
        // Form anlegen, um einen neuen Artikel einzustellen
        newArticleForm = createNewArticleForm();
        
        // Exit-Kommando
        exitCom = new Command("Exit", Command.EXIT, 1);
        dispList.addCommand(exitCom);
    
        // insert-Kommando
        insertCom = new Command("Insert", Command.SCREEN, 1);
        dispList.addCommand(insertCom);
        
        // delete-Kommando
        deleteCom = new Command("Delete Articles", Command.SCREEN, 2);
        dispList.addCommand(deleteCom);
        
        // Listener anhängen
        dispList.setCommandListener(new CommandListener() {
            public void commandAction(Command c, Displayable d) {
                if (c == exitCom) { // Programm beenden
                    try {
                        destroyApp(false);
                        notifyDestroyed();
                    } catch (MIDletStateChangeException e) {
                        e.printStackTrace();
                    }
                } else if(c == insertCom) { // Artikel einfügen
                    display.setCurrent(newArticleForm);
                } else if(c == deleteCom) { // Artikel löschen
                    deleteArticles();
                }
            }
        });
    }

    /**
     * Applikation beenden.
     * @param arg0 If true when this method is called, the MIDlet must cleanup and release all resources.
     * If false the MIDlet may throw MIDletStateChangeException to indicate it does not want to be destroyed at this time.
     */
    protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
        try {
            storeList();
            store.closeRecordStore();
        } catch (Exception e) {
            alert("Speichern nicht möglich", e);
        }

    }

    /**
     * Anwendung im Hintergrund.
     */
    protected void pauseApp() {
        // TODO Auto-generated method stub

    }

    /**
     * Anwendung ab jetzt im Vordergrund
     */
    protected void startApp() throws MIDletStateChangeException {
        if(display == null) {   // Display nur einmal holen
            display = Display.getDisplay(this);
            display.setCurrent(dispList);   // Liste sichtbar machen
        }
    }

    /**
     * Form erzeugen, um einen Artikel einzufuegen
     * @return Form mit einem Textfeld und Listener
     */
    private Form createNewArticleForm() {
        // Form erstellen
        final Form form = new Form("Neuer Artikel");
        
        // TextField erstellen
        final TextField textEingabe = new TextField("Neuer Eintrag:", null, 40, TextField.ANY);
        form.append(textEingabe);
        
        // Kommandos erstellen
        final Command okCom = new Command("OK", Command.OK, 1);
        final Command cancelCom = new Command("Cancel", Command.CANCEL, 2);
        
        form.addCommand(okCom);
        form.addCommand(cancelCom);
        
        // Listener setzen
        form.setCommandListener(new CommandListener() {
            public void commandAction(Command c, Displayable d) {
                if(c == okCom) {    // Falls OK ausgewählt wird
                                    // Artikel einfuegen
                    insertArticle(textEingabe.getString());
                                    // TextFeld löschen
                    textEingabe.setString("");
                                    // Liste wieder sichtbar machen
                    display.setCurrent(dispList);
                } else if(c == cancelCom) { // Falls Cancel gewählt wird ...
                    textEingabe.setString("");
                    display.setCurrent(dispList);
                }
            }
            
        });
        return form;    // Form zurueckliefern
    }
    
    /**
     * Einen String zur Liste hinzufuegen.
     * @param s Hinzuzufuegender String
     */
    private void insertArticle(String s) {
        if(s != null && s.compareTo("")!=0) {
            int index = 0;
                // Liste durchlaufen und die passende Stelle suchen
            while (index < dispList.size()
                    && s.toLowerCase().compareTo(dispList.getString(index).toLowerCase()) > 0) {
                index++;
            }
                // an der passenden Stelle einfuegen
            dispList.insert(index, s, null);
            try {   // Zur sicherheit gleich abspeichern
                storeList();
            } catch (Exception e) {
                alert("Speichern nicht möglich", e);
            }
        }
    }
    
    /**
     * List zum loeschen vobn Artikeln erzeugen und anzeigen.
     */
    private void deleteArticles() {
        // Neue List anlegen
        final List deleteList = new List("Elemente löschen", List.MULTIPLE);
        
        // Ticker (Lauftext) erzeugen und einhaengen
        deleteList.setTicker(new Ticker("Wählen Sie Elemente zum löschen aus"));
        
        // Die Liste mit Werten fuellen
        for(int i = 0; i<dispList.size(); i++) {
            deleteList.append(dispList.getString(i), null);
        }
        
        // Kommandos erzeugen und setzen
        final Command okCom = new Command("Löschen", Command.OK,1);
        final Command cancelCom = new Command("Abbrechen", Command.CANCEL, 1);
        
        deleteList.addCommand(okCom);
        deleteList.addCommand(cancelCom);
        
        // Listener setzen
        deleteList.setCommandListener(new CommandListener() {

            public void commandAction(Command c, Displayable d) {
                if(c == okCom) {    // Wenn geloescht werden soll
                                    // boolean-Array mit den selectierten Werten holen 
                    boolean[] flags = new boolean[deleteList.size()];
                    deleteList.getSelectedFlags(flags);
                    
                                    // Liste durchlaufen und gewaehlte Eintraege loeschen
                    for(int i = deleteList.size()-1; i>=0; i--) {
                        if(flags[i]) {
                            dispList.delete(i);
                        }
                    }
                                    // aktualisierte Liste anzeigen
                    display.setCurrent(dispList);
                    try {           // Zur Sicherheit gleich abspeichern
                        storeList();
                    } catch (Exception e) {
                        alert("Speichern nicht möglich", e);
                    }
                } else if(c == cancelCom) {
                                    // Falls abgebrochen werden soll wieder urspruengliche List anzeigen
                    display.setCurrent(dispList);
                }
            }
        });
        
        display.setCurrent(deleteList); // List zum loeschen anzeigen
    }
    
    /**
     * Speichern der List-Eintraege im RecordStore
     * @throws RecordStoreException
     * @throws IOException
     */
    private void storeList() throws RecordStoreException, IOException {

        // List Groesse und Flags besorgen
        int entries = dispList.size();
        boolean[] flags = new boolean[entries];
        dispList.getSelectedFlags(flags);

        // Die Eintraege durchlaufen
        for (int i = 0; i < entries; i++) {
                    // jeweils ein Artikel-Objekt erzeugen und in ein byte-Array umwandeln
            Artikel a = new Artikel(flags[i], dispList.getString(i));
            byte[] record = a.getBytes();

                    // Falls ein Record "recycled" wird diesen ueberschreiben
            if (i + 1 <= store.getNumRecords()) {
                store.setRecord(i + 1, record, 0, record.length);
            } else { // Falls ein Record neu angelegt werden soll ...
                store.addRecord(record, 0, record.length);
            }
        }
                    // Falls noch records im Store uebrig sind diese mit einem dummy-Objekt ueberschreiben
        byte[] dummyRecord = new Artikel().getBytes();
        for(int i = entries+1; i<=store.getNumRecords(); i++) {
            store.setRecord(i, dummyRecord, 0, dummyRecord.length);
        }
    }
    
    /**
     * Eine neue Liste erzeugen. Dazu ein Artikel-Objekt erzeugen,
     * in ein byte-Array umwandeln, in den RecordStore schreiben und
     * in das List-Objekt einfuegen.
     * 
     * @throws IOException
     * @throws RecordStoreException
     */
    private void createNewList() throws IOException, RecordStoreException {
        Artikel a;
        byte[] record;

        a = new Artikel("Bier");
        record = a.getBytes();
        store.addRecord(record, 0, record.length);
        dispList.append(a.getName(), null);

        a = new Artikel("Butter");
        record = a.getBytes();
        store.addRecord(record, 0, record.length);
        dispList.append(a.getName(), null);

        a = new Artikel("Käse");
        record = a.getBytes();
        store.addRecord(record, 0, record.length);
        dispList.append(a.getName(), null);

        a = new Artikel("Wasser");
        record = a.getBytes();
        store.addRecord(record, 0, record.length);
        dispList.append(a.getName(), null);

        a = new Artikel("Wurst");
        record = a.getBytes();
        store.addRecord(record, 0, record.length);
        dispList.append(a.getName(), null);

        a = new Artikel("Zucker");
        record = a.getBytes();
        store.addRecord(record, 0, record.length);
        dispList.append(a.getName(), null);
    }
    
    /**
     * Eine im RecordStore gespeicherte List laden.
     * 
     * @throws RecordStoreException
     * @throws IOException
     */
    private void loadList() throws RecordStoreException, IOException {
        // Den RecordStore durchlaufen
        for(int i = 1; i<= store.getNumRecords(); i++) {
            byte[] record = store.getRecord(i);     // Record holen
            Artikel a = new Artikel();              // Daraus Artikel-Objekt erzeugen
            a.setBytes(record);
            if(a.getName().compareTo("")!=0) {      // Falls kein Dummy-Element in die List eintragen
                dispList.append(a.getName(), null);
                dispList.setSelectedIndex(i-1, a.isSelected());
            }
        }
    }
    
    /**
     * Erzeugt einen Alert und zeigt diesen an.
     * @param msg Fehlermeldung
     * @param e Exception (nur fuer Debug-Zwecke im Emulator eines WTK)
     */
    private void alert(String msg, Exception e) {
        Alert alert = new Alert("Fehler", msg, null, AlertType.ERROR);
        alert.setTimeout(2000);
        display.setCurrent(alert);
        System.out.println(msg + e);
    }
}
