/*
 * BookCheck.java
 *
 * Created on October 8, 2003, 12:46 AM
 */

package org.tienshiao.BookCheck;

import java.io.*;
import java.util.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import org.tienshiao.XMLLite.*;

/**
 * @author  tma
 * @version
 */
public class BookCheck extends MIDlet implements CommandListener {
    private Command okCommand;
    private Command exitCommand;
    private Command cancelCommand;
    private Command backCommand;
    private Command nextCommand;
    private Command reviewCommand;
    private ISBNForm isbnForm;
    private Form responseForm;
    private Vector reviewForms;
    private Display display;    // The display for this MIDlet
    
    public BookCheck() {
        reviewForms = new Vector(3);    // I think Amazon only returns 3
        display = Display.getDisplay(this);
        okCommand = new Command("OK", Command.OK, 1);
        exitCommand = new Command("Exit", Command.EXIT, 1);
        isbnForm = new ISBNForm();
        
        isbnForm.addCommand(okCommand);
        isbnForm.addCommand(exitCommand);
        isbnForm.setCommandListener(this);
        
    }
    
    /**
     * Start up the Hello MIDlet by creating the TextBox and associating
     * the exit command and listener.
     */
    public void startApp() {        
        display.setCurrent(isbnForm);
    }
    
    /**
     * Pause is a no-op since there are no background activities or
     * record stores that need to be closed.
     */
    public void pauseApp() {
    }
    
    /**
     * Destroy must cleanup everything not handled by the garbage collector.
     * In this case there is nothing to cleanup.
     */
    public void destroyApp(boolean unconditional) {
    }
    
    /*
     * Respond to commands, including exit
     * On the exit command, cleanup and notify that the MIDlet has been destroyed.
     */
    public void commandAction(Command c, Displayable d){
        if (c == okCommand) {
            String isbn = isbnForm.getISBN();
            if (isbn.length() != 10) {
                Alert alert = new Alert("BookCheck", "Your entry was not a valid ISBN.", null, null);
                alert.setTimeout(Alert.FOREVER);
                display.setCurrent(alert);
                return;
            }
            int scratch = 0;
            for (int i = 0; i < 9; i++) {
                scratch += (10 - i) * Integer.parseInt(isbn.substring(i, i+1));                
            }
            if (isbn.charAt(9) == 'X') {
                scratch += 10;
            } else {
                scratch += Integer.parseInt(isbn.substring(9, 10));
            }
            if (scratch % 11 != 0) {
                    Alert alert = new Alert("BookCheck", "Your entry was not a valid ISBN.", null, null);
                    alert.setTimeout(Alert.FOREVER);
                    display.setCurrent(alert);
                    return;                                    
            }
/*          // Old Broken on '0' code
            if (scratch % 11 == 1) {
                if (isbn.charAt(9) != 'X') {
                    Alert alert = new Alert("BookCheck", "Your entry was not a valid ISBN.", null, null);
                    alert.setTimeout(Alert.FOREVER);
                    display.setCurrent(alert);
                    return;                                    
                }                
            } else if (11 - (scratch % 11) != Integer.parseInt(isbn.substring(9, 10))) {
                Alert alert = new Alert("BookCheck", "Your entry was not a valid ISBN.", null, null);
                alert.setTimeout(Alert.FOREVER);
                display.setCurrent(alert);
                return;                
            }*/
            DownloadForm next = new DownloadForm(isbn, this);
            cancelCommand =  new Command("Cancel", Command.CANCEL, 1);
            next.addCommand(cancelCommand);
            next.setCommandListener(this);
            display.setCurrent(next);
        } else if (c == exitCommand) {
            destroyApp(false);
            notifyDestroyed();            
        } else if (c == cancelCommand) {
            display.setCurrent(isbnForm);
        } else if (c == backCommand) {
            if (d == (Displayable) responseForm) {
                reviewForms.removeAllElements();
                display.setCurrent(isbnForm);
                responseForm = null;
            } else {
                for (int i = 0; i < reviewForms.size(); i++) {
                    if (d == reviewForms.elementAt(i)) {
                        if (i == 0) {
                            display.setCurrent(responseForm);
                        } else {
                            display.setCurrent((Displayable)reviewForms.elementAt(i - 1));
                        }
                    }
                }
            }
        } else if (c == reviewCommand) {
            if (!reviewForms.isEmpty()) {
                display.setCurrent((Displayable)reviewForms.firstElement());
            }
        } else if (c == nextCommand) {
            for (int i = 0; i < reviewForms.size(); i++) {
                if (d == reviewForms.elementAt(i)) {
                    display.setCurrent((Displayable)reviewForms.elementAt(i + 1));
                }
            }
        }
    }
    
    private String processHTML(String html) {
        XMLPullParser xpp = new XMLPullParser(new InputStreamReader(new ByteArrayInputStream(html.getBytes())));
        StringBuffer text = new StringBuffer();
        while (xpp.getType() != XMLPullParser.EOF) {
            try {
                xpp.getNextToken();
                if (xpp.getType() == XMLPullParser.START_TAG ||
                    xpp.getType() == XMLPullParser.EMPTY_TAG) {                        
                    String name = xpp.getName().toLowerCase();
                    if (name.equals("p") || name.equals("br")) {
                        text.append("\n\n ");
                    }
                } else if (xpp.getType() == XMLPullParser.TEXT) {
                    text.append(xpp.getText());
                }
                
            } catch (IOException ioe) {
                Alert alert = new Alert("BookCheck", "Error parsing review: " + ioe.toString(), null, null);
                alert.setTimeout(Alert.FOREVER);
                display.setCurrent(alert);                
            } catch (XMLParserException xpe) {
                Alert alert = new Alert("BookCheck", "Error parsing review: " + xpe.toString(), null, null);
                alert.setTimeout(Alert.FOREVER);
                display.setCurrent(alert);
                return text.toString();
            }
        }
        return text.toString();
    }
    
    public ISBNForm getISBNForm() {
        return isbnForm;
    }

    public void displayResponse(XMLElement response) {
        if (!response.getName().equals("ProductInfo")) {
            Alert alert = new Alert("BookCheck", "Error communicating with Amazon (unrecognized response).", null, null);
            alert.setTimeout(Alert.FOREVER);
            display.setCurrent(alert, isbnForm);
            return;
        }
        for (Enumeration responseEnum = response.enumerateChildren(); responseEnum.hasMoreElements();) {            
            XMLElement child = (XMLElement) responseEnum.nextElement();
            if (child.getName().equals("Details")) {
                backCommand = new Command("Back", Command.BACK, 1);
                String title = null;
                String authors = null;
                String catalog = null;
                String media = null;
                String listPrice = null;
                String ourPrice = null;
                String usedPrice = null;
                String thirdPartyNewPrice = null;
                String availability = null;
                String description = null;
                String aveRating = null;
                String numReviews = null;
                //TODO: strip html
                for (Enumeration detailEnum = child.enumerateChildren(); detailEnum.hasMoreElements();) {
                    XMLElement detail = (XMLElement)detailEnum.nextElement();
                    String detailName = detail.getName();
                    if (detailName.equals("ProductName")) {
                        title = detail.getContent().trim();
                    } else if (detailName.equals("Catalog")) {
                        catalog = detail.getContent().trim();
                    } else if (detailName.equals("Authors")) {
                        StringBuffer sbAuthors = new StringBuffer();
                        for (Enumeration authorsEnum = detail.enumerateChildren(); authorsEnum.hasMoreElements();) {
                            XMLElement currAuthor = (XMLElement) authorsEnum.nextElement();
                            if (currAuthor.getName().equals("Author")) {
                                sbAuthors.append(currAuthor.getContent().trim());
                                if (authorsEnum.hasMoreElements()) {
                                    sbAuthors.append(", ");
                                }
                            }
                        }
                        authors = sbAuthors.toString();
                    } else if (detailName.equals("ListPrice")) {
                        listPrice = detail.getContent().trim();
                    } else if (detailName.equals("OurPrice")) {
                        ourPrice = detail.getContent().trim();
                    } else if (detailName.equals("UsedPrice")) {
                        usedPrice = detail.getContent().trim();
                    } else if (detailName.equals("ThirdPartyNewPrice")) {
                        thirdPartyNewPrice = detail.getContent().trim();
                    } else if (detailName.equals("Media")) {
                        media = detail.getContent().trim();
                    } else if (detailName.equals("Availability")) {
                        availability = detail.getContent().trim();
                    } else if (detailName.equals("ProductDescription")) {
                        description = detail.getContent().trim();
                    } else if (detailName.equals("Reviews")) {
                        nextCommand = new Command("Next", Command.SCREEN, 1);
                        for (Enumeration reviewEnum = detail.enumerateChildren(); reviewEnum.hasMoreElements(); ) {
                            XMLElement reviewChild = (XMLElement) reviewEnum.nextElement();
                            String childName = reviewChild.getName();
                            if (childName.equals("AvgCustomerRating")) {
                                aveRating = reviewChild.getContent().trim();
                            } else if (childName.equals("TotalCustomerReviews")) {
                                numReviews = reviewChild.getContent().trim();
                            } else if (childName.equals("CustomerReview")) {
                                Form reviewForm = new Form("Review");
                                String rating = null;
                                String summary = null;
                                String comment = null;
                                for (Enumeration custRevEnum = reviewChild.enumerateChildren(); custRevEnum.hasMoreElements();) {
                                    XMLElement reviewElement = (XMLElement)custRevEnum.nextElement();
                                    String tag = reviewElement.getName();
                                    if (tag.equals("Rating")) {
                                        rating = reviewElement.getContent().trim();
                                    } else if (tag.equals("Summary")) {
                                        summary = reviewElement.getContent().trim();
                                    } else if (tag.equals("Comment")) {
                                        comment = processHTML(reviewElement.getContent().trim());
                                    }
                                }
                                reviewForm.append(new StringItem("Rating", rating));
                                reviewForm.append(new StringItem("Summary", summary));
                                reviewForm.append(new StringItem("Comment", comment));
                                reviewForm.addCommand(backCommand);
                                if (reviewEnum.hasMoreElements()) {
                                    reviewForm.addCommand(nextCommand);
                                }
                                reviewForm.setCommandListener(this);
                                reviewForms.addElement(reviewForm);
                            }
                        }
                    }
                }
                responseForm = new Form("BookCheck");
                responseForm.append(new StringItem("Title ", title));
                responseForm.append(new StringItem("Authors ", authors));
                responseForm.append(new StringItem("Type ", catalog + ", " + media));
                responseForm.append(new StringItem("List Price ", listPrice));
                responseForm.append(new StringItem("Amazon Price ", ourPrice));
                responseForm.append(new StringItem("Used Price ", usedPrice));
                responseForm.append(new StringItem("Third Party New Price ", thirdPartyNewPrice));
                responseForm.append(new StringItem("Availability ", availability));
                responseForm.append(new StringItem("Average Rating ", aveRating));
                responseForm.append(new StringItem("Number of Reviews ", numReviews));
                 
                responseForm.addCommand(backCommand);
                if (!reviewForms.isEmpty()) {
                    reviewCommand = new Command("Reviews", Command.SCREEN, 1);
                    responseForm.addCommand(reviewCommand);
                }
                responseForm.setCommandListener(this);
                display.setCurrent(responseForm);
            } else if (child.getName().equals("ErrorMsg")) {
                Alert alert = new Alert("BookCheck", "Amazon says: " + child.getContent().trim(), null, null);
                alert.setTimeout(Alert.FOREVER);
                display.setCurrent(alert, isbnForm);                    
            }
        }
    }
}
