/* 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 = "Serializer";
    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();
    }

}
