/*
 * Copyright (C) 2008-2009 Marc Blank
 * Licensed to The Android Open Source Project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.exchange.adapter;

import java.io.*;
import java.util.ArrayList;

import com.android.exchange.EasException;

import android.content.Context;
import android.util.Log;

/**
 * Extremely fast and lightweight WBXML parser, implementing only the subset of WBXML that
 * EAS uses (as defined in the EAS specification)
 *
 */
public abstract class EasParser {

    private static final String TAG = "EasParser";

    // The following constants are Wbxml standard
    public static final int START_DOCUMENT = 0;
    public static final int DONE = 1;
    public static final int START = 2;
    public static final int END = 3;
    public static final int TEXT = 4;
    public static final int END_DOCUMENT = 3;
    private static final int NOT_FETCHED = Integer.MIN_VALUE;
    private static final int NOT_ENDED = Integer.MIN_VALUE;
    private static final int EOF_BYTE = -1;
    private boolean debug = false;
    private boolean capture = false;

    private ArrayList<Integer> captureArray;

    // The input stream for this parser
    private InputStream in;

    // The current tag depth
    private int depth;

    // The upcoming (saved) id from the stream
    private int nextId = NOT_FETCHED;

    // The current tag table (i.e. the tag table for the current page)
    private String[] tagTable;

    // An array of tag tables, as defined in EasTags
    static private String[][] tagTables = new String[24][];

    // The stack of names of tags being processed; used when debug = true
    private String[] nameArray = new String[32];

    // The stack of tags being processed
    private int[] startTagArray = new int[32];

    // The following vars are available to all to avoid method calls that represent the state of
    // the parser at any given time
    public int endTag = NOT_ENDED;

    public int startTag;

    // The type of the last token read
    public int type;

    // The current page
    public int page;

    // The current tag
    public int tag;

    // The name of the current tag
    public String name;

    // Whether the current tag is associated with content (a value)
    private boolean noContent;

    // The value read, as a String.  Only one of text or num will be valid, depending on whether the
    // value was requested as a String or an int (to avoid wasted effort in parsing)
    public String text;

    // The value read, as an int
    public int num;

    public class EofException extends IOException {
        private static final long serialVersionUID = 1L;
    }

    public class EodException extends IOException {
        private static final long serialVersionUID = 1L;
    }

    public class EasParserException extends IOException {
        private static final long serialVersionUID = 1L;
    }

    public boolean parse() throws IOException, EasException {
        return false;
    }

    /**
     * Initialize the tag tables; they are constant
     *
     */
    {
        String[][] pages = EasTags.pages;
        for (int i = 0; i < pages.length; i++) {
            String[] page = pages[i];
            if (page.length > 0) {
                tagTables[i] = page;
            }
        }
    }

    public EasParser(InputStream in) throws IOException {
        setInput(in);
    }

    /**
     * Set the debug state of the parser.  When debugging is on, every token is logged (Log.v) to
     * the console.
     *
     * @param val the desired state for debug output
     */
    public void setDebug(boolean val) {
        debug = val;
    }

    /**
     * Turns on data capture; this is used to create test streams that represent "live" data and
     * can be used against the various parsers.
     */
    public void captureOn() {
        capture = true;
        captureArray = new ArrayList<Integer>();
    }

    /**
     * Turns off data capture; writes the captured data to a specified file.
     */
    public void captureOff(Context context, String file) {
        try {
            FileOutputStream out = context.openFileOutput(file, Context.MODE_WORLD_WRITEABLE);
            out.write(captureArray.toString().getBytes());
            out.close();
        } catch (FileNotFoundException e) {
            // This is debug code; exceptions aren't interesting.
        } catch (IOException e) {
            // This is debug code; exceptions aren't interesting.
        }
    }

    /**
     * Return the value of the current tag, as a String
     *
     * @return the String value of the current tag
     * @throws IOException
     */
    public String getValue() throws IOException {
        // The false argument tells getNext to return the value as a String
        getNext(false);
        // Save the value
        String val = text;
        // Read the next token; it had better be the end of the current tag
        getNext(false);
        // If not, throw an exception
        if (type != END) {
            throw new IOException("No END found!");
        }
        endTag = startTag;
        return val;
    }

    /**
     * Return the value of the current tag, as an integer
     *
     * @return the integer value of the current tag
     * @throws IOException
     */
   public int getValueInt() throws IOException {
        // The true argument to getNext indicates the desire for an integer return value
        getNext(true);
        // Save the value
        int val = num;
        // Read the next token; it had better be the end of the current tag
        getNext(false);
        // If not, throw an exception
        if (type != END) {
            throw new IOException("No END found!");
        }
        endTag = startTag;
        return val;
    }

    /**
     * Return the next tag found in the stream; special tags END and END_DOCUMENT are used to
     * mark the end of the current tag and end of document.  If we hit end of document without
     * looking for it, generate an EodException.  The tag returned consists of the page number
     * shifted PAGE_SHIFT bits OR'd with the tag retrieved from the stream.  Thus, all tags returned
     * are unique.
     *
     * @param endingTag the tag that would represent the end of the tag we're processing
     * @return the next tag found
     * @throws IOException
     */
    public int nextTag(int endingTag) throws IOException {
        // Lose the page information
        endTag = endingTag &= EasTags.PAGE_MASK;
        while (getNext(false) != DONE) {
            // If we're a start, set tag to include the page and return it
            if (type == START) {
                tag = page | startTag;
                return tag;
            // If we're at the ending tag we're looking for, return the END signal
            } else if (type == END && startTag == endTag) {
                return END;
            }
        }
        // We're at end of document here.  If we're looking for it, return END_DOCUMENT
        if (endTag == START_DOCUMENT) {
            return END_DOCUMENT;
        }
        // Otherwise, we've prematurely hit end of document, so exception out
        // EodException is a subclass of IOException; this will be treated as an IO error by
        // SyncManager.
        throw new EodException();
    }

    /**
     * Skip anything found in the stream until the end of the current tag is reached.  This can be
     * used to ignore stretches of xml that aren't needed by the parser.
     *
     * @throws IOException
     */
    public void skipTag() throws IOException {
        int thisTag = startTag;
        // Just loop until we hit the end of the current tag
        while (getNext(false) != DONE) {
            if (type == END && startTag == thisTag) {
                return;
            }
        }

        // If we're at end of document, that's bad
        throw new EofException();
    }

    /**
     * Retrieve the next token from the input stream
     *
     * @return the token found
     * @throws IOException
     */
    public int nextToken() throws IOException {
        getNext(false);
        return type;
    }

    /**
     * Initializes the parser with an input stream; reads the first 4 bytes (which are always the
     * same in EAS, and then sets the tag table to point to page 0 (by definition, the starting
     * page).
     *
     * @param in the InputStream associated with this parser
     * @throws IOException
     */
    public void setInput(InputStream in) throws IOException {
        this.in = in;
        readByte(); // version
        readInt();  // ?
        readInt();  // 106 (UTF-8)
        readInt();  // string table length
        tagTable = tagTables[0];
    }

    /**
     * Return the next piece of data from the stream.  The return value indicates the type of data
     * that has been retrieved - START (start of tag), END (end of tag), DONE (end of stream), or
     * TEXT (the value of a tag)
     *
     * @param asInt whether a TEXT value should be parsed as a String or an int.
     * @return the type of data retrieved
     * @throws IOException
     */
    private final int getNext(boolean asInt) throws IOException {
        if (type == END) {
            depth--;
        } else {
            endTag = NOT_ENDED;
        }

        if (noContent) {
            type = END;
            noContent = false;
            return type;
        }

        text = null;
        name = null;

        int id = nextId ();
        while (id == Wbxml.SWITCH_PAGE) {
            nextId = NOT_FETCHED;
            // Get the new page number
            int pg = readByte();
            // Save the shifted page to add into the startTag in nextTag
            page = pg << EasTags.PAGE_SHIFT;
            // Retrieve the current tag table
            tagTable = tagTables[pg];
            id = nextId();
        }
        nextId = NOT_FETCHED;

        switch (id) {
            case EOF_BYTE:
                // End of document
                type = DONE;
                break;

            case Wbxml.END:
                // End of tag
                type = END;
                if (debug) {
                    name = nameArray[depth];
                    Log.v(TAG, "</" + name + '>');
                }
                // Retrieve the now-current startTag from our stack
                startTag = endTag = startTagArray[depth];
                break;

            case Wbxml.STR_I:
                // Inline string
                type = TEXT;
                if (asInt) {
                    num = readInlineInt();
                } else {
                    text = readInlineString();
                }
                if (debug) {
                    Log.v(TAG, asInt ? Integer.toString(num) : text);
                }
                break;

            default:
                // Start of tag
                type = START;
                // The tag is in the low 6 bits
                startTag = id & 0x3F;
                // If the high bit is set, there is content (a value) to be read
                noContent = (id & 0x40) == 0;
                depth++;
                if (debug) {
                    name = tagTable[startTag - 5];
                    Log.v(TAG, '<' + name + '>');
                    nameArray[depth] = name;
                }
                // Save the startTag to our stack
                startTagArray[depth] = startTag;
        }

        // Return the type of data we're dealing with
        return type;
    }

    /**
     * Read an int from the input stream, and capture it if necessary for debugging.  Seems a small
     * price to pay...
     *
     * @return the int read
     * @throws IOException
     */
    private int read() throws IOException {
        int i;
        i = in.read();
        if (capture) {
            captureArray.add(i);
        }
        return i;
    }

    private int nextId() throws IOException {
        if (nextId == NOT_FETCHED) {
            nextId = read();
        }
        return nextId;
    }

    private int readByte() throws IOException {
        int i = read();
        if (i == EOF_BYTE) {
            throw new EofException();
        }
        return i;
    }

    /**
     * Read an integer from the stream; this is called when the parser knows that what follows is
     * an inline string representing an integer (e.g. the Read tag in Email has a value known to
     * be either "0" or "1")
     *
     * @return the integer as parsed from the stream
     * @throws IOException
     */
    private int readInlineInt() throws IOException {
        int result = 0;

        while (true) {
            int i = readByte();
            // Inline strings are always terminated with a zero byte
            if (i == 0) {
                return result;
            }
            if (i >= '0' && i <= '9') {
                result = (result * 10) + (i - '0');
            } else {
                throw new IOException("Non integer");
            }
        }
    }

    private int readInt() throws IOException {
        int result = 0;
        int i;

        do {
            i = readByte();
            result = (result << 7) | (i & 0x7f);
        } while ((i & 0x80) != 0);

        return result;
    }

    /**
     * Read an inline string from the stream
     *
     * @return the String as parsed from the stream
     * @throws IOException
     */
    private String readInlineString() throws IOException {
        StringBuilder sb = new StringBuilder(256);

        while (true) {
            int i = read();
            if (i == 0) {
                break;
            } else if (i == EOF_BYTE) {
                throw new EofException();
            }
            sb.append((char)i);
        }
        String res = sb.toString();
        return res;
    }
}