/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The  above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE. */

//Contributors: Jonathan Cox, Bogdan Onoiu, Jerry Tian
// Greatly simplified for Google, Inc. by Marc Blank

package com.android.exchange.adapter;

import android.content.ContentValues;

import com.android.exchange.Eas;
import com.android.exchange.utility.FileLogger;
import com.android.mail.utils.LogUtils;
import com.google.common.annotations.VisibleForTesting;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class Serializer {
    private static final String TAG = Eas.LOG_TAG;
    private static final int BUFFER_SIZE = 16*1024;
    private static final int NOT_PENDING = -1;

    private final OutputStream mOutput;
    private int mPendingTag = NOT_PENDING;
    private int mDepth;
    private String[] mNameStack = new String[20];
    private int mTagPage = 0;
    private boolean mLogging = LogUtils.isLoggable(TAG, LogUtils.VERBOSE);

    public Serializer() throws IOException {
        this(new ByteArrayOutputStream(), true);
    }

    public Serializer(OutputStream os) throws IOException {
        this(os, true);
    }

    @VisibleForTesting
    public Serializer(boolean startDocument) throws IOException {
        this(new ByteArrayOutputStream(), startDocument);
    }

    /**
     * Base constructor
     * @param outputStream the stream we're serializing to
     * @param startDocument whether or not to start a document
     * @param _logging whether or not to log our output
     * @throws IOException
     */
    public Serializer(OutputStream outputStream, boolean startDocument) throws IOException {
        super();
        mOutput = outputStream;
        if (startDocument) {
            startDocument();
        } else {
            mOutput.write(0);
        }
    }

    void log(String str) {
        int cr = str.indexOf('\n');
        if (cr > 0) {
            str = str.substring(0, cr);
        }
        LogUtils.v(TAG, str);
        if (Eas.FILE_LOG) {
            FileLogger.log(TAG, str);
        }
    }

    public void done() throws IOException {
        if (mDepth != 0) {
            throw new IOException("Done received with unclosed tags");
        }
        mOutput.flush();
    }

    public void startDocument() throws IOException{
        mOutput.write(0x03); // version 1.3
        mOutput.write(0x01); // unknown or missing public identifier
        mOutput.write(106);  // UTF-8
        mOutput.write(0);    // 0 length string array
    }

    public void checkPendingTag(boolean degenerated) throws IOException {
        if (mPendingTag == NOT_PENDING)
            return;

        int page = mPendingTag >> Tags.PAGE_SHIFT;
        int tag = mPendingTag & Tags.PAGE_MASK;
        if (page != mTagPage) {
            mTagPage = page;
            mOutput.write(Wbxml.SWITCH_PAGE);
            mOutput.write(page);
        }

        mOutput.write(degenerated ? tag : tag | Wbxml.WITH_CONTENT);
        if (mLogging) {
            String name = Tags.pages[page][tag - 5];
            mNameStack[mDepth] = name;
            log("<" + name + '>');
        }
        mPendingTag = NOT_PENDING;
    }

    public Serializer start(int tag) throws IOException {
        checkPendingTag(false);
        mPendingTag = tag;
        mDepth++;
        return this;
    }

    public Serializer end() throws IOException {
        if (mPendingTag >= 0) {
            checkPendingTag(true);
        } else {
            mOutput.write(Wbxml.END);
            if (mLogging) {
                log("</" + mNameStack[mDepth] + '>');
            }
        }
        mDepth--;
        return this;
    }

    public Serializer tag(int t) throws IOException {
        start(t);
        end();
        return this;
    }

    public Serializer data(int tag, String value) throws IOException {
        if (value == null) {
            LogUtils.e(TAG, "Writing null data for tag: " + tag);
        }
        start(tag);
        text(value);
        end();
        return this;
    }

    public Serializer text(String text) throws IOException {
        if (text == null) {
            LogUtils.e(TAG, "Writing null text for pending tag: " + mPendingTag);
        }
        checkPendingTag(false);
        mOutput.write(Wbxml.STR_I);
        writeLiteralString(mOutput, text);
        if (mLogging) {
            log(text);
        }
        return this;
    }

    public Serializer opaque(InputStream is, int length) throws IOException {
        checkPendingTag(false);
        mOutput.write(Wbxml.OPAQUE);
        writeInteger(mOutput, length);
        if (mLogging) {
            log("Opaque, length: " + length);
        }
        // Now write out the opaque data in batches
        byte[] buffer = new byte[BUFFER_SIZE];
        while (length > 0) {
            int bytesRead = is.read(buffer, 0, Math.min(BUFFER_SIZE, length));
            if (bytesRead == -1) {
                break;
            }
            mOutput.write(buffer, 0, bytesRead);
            length -= bytesRead;
        }
        return this;
    }

    public Serializer opaqueWithoutData(int length) throws IOException {
        checkPendingTag(false);
        mOutput.write(Wbxml.OPAQUE);
        writeInteger(mOutput, length);
        return this;
    }

    void writeInteger(OutputStream out, int i) throws IOException {
        byte[] buf = new byte[5];
        int idx = 0;

        do {
            buf[idx++] = (byte) (i & 0x7f);
            i = i >> 7;
        } while (i != 0);

        while (idx > 1) {
            out.write(buf[--idx] | 0x80);
        }
        out.write(buf[0]);
        if (mLogging) {
            log(Integer.toString(i));
        }
    }

    void writeLiteralString(OutputStream out, String s) throws IOException {
        byte[] data = s.getBytes("UTF-8");
        out.write(data);
        out.write(0);
    }

    public void writeStringValue (ContentValues cv, String key, int tag) throws IOException {
        String value = cv.getAsString(key);
        if (value != null && value.length() > 0) {
            data(tag, value);
        } else {
            tag(tag);
        }
    }

    @Override
    public String toString() {
        if (mOutput instanceof ByteArrayOutputStream) {
            return ((ByteArrayOutputStream)mOutput).toString();
        }
        throw new IllegalStateException();
    }

    public byte[] toByteArray() {
        if (mOutput instanceof ByteArrayOutputStream) {
            return ((ByteArrayOutputStream)mOutput).toByteArray();
        }
        throw new IllegalStateException();
    }

}
