/*
 * Copyright (C) 2009 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.cooliris.picasa;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

import android.text.format.Time;

public final class GDataParser implements ContentHandler {
    public static final String APP_NAMESPACE = "http://www.w3.org/2007/app";
    public static final String ATOM_NAMESPACE = "http://www.w3.org/2005/Atom";
    public static final String GD_NAMESPACE = "http://schemas.google.com/g/2005";
    public static final String GPHOTO_NAMESPACE = "http://schemas.google.com/photos/2007";
    public static final String MEDIA_RSS_NAMESPACE = "http://search.yahoo.com/mrss/";
    public static final String GML_NAMESPACE = "http://www.opengis.net/gml";
    private static final String FEED_ELEMENT = "feed";
    private static final String ENTRY_ELEMENT = "entry";

    private static final int STATE_DOCUMENT = 0;
    private static final int STATE_FEED = 1;
    private static final int STATE_ENTRY = 2;

    private static final int NUM_LEVELS = 5;

    private Entry mEntry = null;
    private EntryHandler mHandler = null;
    private int mState = STATE_DOCUMENT;
    private int mLevel = 0;
    private String[] mUri = new String[NUM_LEVELS];
    private String[] mName = new String[NUM_LEVELS];
    private AttributesImpl[] mAttributes = new AttributesImpl[NUM_LEVELS];
    private final StringBuilder mValue = new StringBuilder(128);

    public interface EntryHandler {
        void handleEntry(Entry entry);
    }

    public GDataParser() {
        AttributesImpl[] attributes = mAttributes;
        for (int i = 0; i != NUM_LEVELS; ++i) {
            attributes[i] = new AttributesImpl();
        }
    }

    public void setEntry(Entry entry) {
        mEntry = entry;
    }

    public void setHandler(EntryHandler handler) {
        mHandler = handler;
    }

    public static long parseAtomTimestamp(String timestamp) {
        Time time = new Time();
        time.parse3339(timestamp);
        return time.toMillis(true);
    }

    public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException {
        switch (mState) {
        case STATE_DOCUMENT:
            // Expect an atom:feed element.
            if (uri.equals(ATOM_NAMESPACE) && localName.equals(FEED_ELEMENT)) {
                mState = STATE_FEED;
            } else {
                throw new SAXException();
            }
            break;
        case STATE_FEED:
            // Expect a feed property element or an atom:entry element.
            if (uri.equals(ATOM_NAMESPACE) && localName.equals(ENTRY_ELEMENT)) {
                mState = STATE_ENTRY;
                mEntry.clear();
            } else {
                startProperty(uri, localName, attrs);
            }
            break;
        case STATE_ENTRY:
            startProperty(uri, localName, attrs);
            break;
        }
    }

    public void endElement(String uri, String localName, String qName) throws SAXException {
        if (mLevel > 0) {
            // Handle property exit.
            endProperty();
        } else {
            // Handle state exit.
            switch (mState) {
            case STATE_DOCUMENT:
                throw new SAXException();
            case STATE_FEED:
                mState = STATE_DOCUMENT;
                break;
            case STATE_ENTRY:
                mState = STATE_FEED;
                mHandler.handleEntry(mEntry);
                break;
            }
        }
    }

    private void startProperty(String uri, String localName, Attributes attrs) {
        // Push element information onto the property stack.
        int level = mLevel + 1;
        mLevel = level;
        mValue.setLength(0);
        mUri[level] = uri;
        mName[level] = localName;
        mAttributes[level].setAttributes(attrs);
    }

    private void endProperty() {
        // Apply property to the entry, then pop the stack.
        int level = mLevel;
        mEntry.setPropertyFromXml(mUri[level], mName[level], mAttributes[level], mValue.toString());
        mLevel = level - 1;
    }

    public void characters(char[] ch, int start, int length) throws SAXException {
        mValue.append(ch, start, length);
    }

    public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
        // Ignored.
    }

    public void processingInstruction(String target, String data) throws SAXException {
        // Ignored.
    }

    public void setDocumentLocator(Locator locator) {
        // Ignored.
    }

    public void skippedEntity(String name) throws SAXException {
        // Ignored.
    }

    public void startDocument() throws SAXException {
        // Ignored.
    }

    public void endDocument() throws SAXException {
        // Ignored.
    }

    public void startPrefixMapping(String prefix, String uri) throws SAXException {
        // Ignored.
    }

    public void endPrefixMapping(String prefix) throws SAXException {
        // Ignored.
    }
}
