/*
 * Copyright (c) 2001-2008 Caucho Technology, Inc.  All rights reserved.
 *
 * The Apache Software License, Version 1.1
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowlegement:
 *       "This product includes software developed by the
 *        Caucho Technology (http://www.caucho.com/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 *
 * 4. The names "Burlap", "Resin", and "Caucho" must not be used to
 *    endorse or promote products derived from this software without prior
 *    written permission. For written permission, please contact
 *    info@caucho.com.
 *
 * 5. Products derived from this software may not be called "Resin"
 *    nor may "Resin" appear in their names without prior written
 *    permission of Caucho Technology.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @author Scott Ferguson
 */

package com.alibaba.com.caucho.hessian.io;

import java.io.IOException;
import java.io.OutputStream;
import java.util.IdentityHashMap;

/**
 * Output stream for Hessian requests, compatible with microedition
 * Java.  It only uses classes and types available in JDK.
 * <p>
 * <p>Since HessianOutput does not depend on any classes other than
 * in the JDK, it can be extracted independently into a smaller package.
 * <p>
 * <p>HessianOutput is unbuffered, so any client needs to provide
 * its own buffering.
 * <p>
 * <pre>
 * OutputStream os = ...; // from http connection
 * HessianOutput out = new HessianOutput(os);
 * String value;
 *
 * out.startCall("hello");  // start hello call
 * out.writeString("arg1"); // write a string argument
 * out.completeCall();      // complete the call
 * </pre>
 */
public class HessianOutput extends AbstractHessianOutput {
    // the output stream/
    protected OutputStream os;
    // map of references
    private IdentityHashMap _refs;
    private int _version = 1;

    /**
     * Creates a new Hessian output stream, initialized with an
     * underlying output stream.
     *
     * @param os the underlying output stream.
     */
    public HessianOutput(OutputStream os) {
        init(os);
    }

    /**
     * Creates an uninitialized Hessian output stream.
     */
    public HessianOutput() {
    }

    /**
     * Initializes the output
     */
    @Override
    public void init(OutputStream os) {
        this.os = os;

        _refs = null;

        if (_serializerFactory == null)
            _serializerFactory = new SerializerFactory();
    }

    /**
     * Sets the client's version.
     */
    public void setVersion(int version) {
        _version = version;
    }

    /**
     * Writes a complete method call.
     */
    @Override
    public void call(String method, Object[] args)
            throws IOException {
        int length = args != null ? args.length : 0;

        startCall(method, length);

        for (int i = 0; i < length; i++)
            writeObject(args[i]);

        completeCall();
    }

    /**
     * Starts the method call.  Clients would use <code>startCall</code>
     * instead of <code>call</code> if they wanted finer control over
     * writing the arguments, or needed to write headers.
     * <p>
     * <code><pre>
     * c major minor
     * m b16 b8 method-name
     * </pre></code>
     *
     * @param method the method name to call.
     */
    @Override
    public void startCall(String method, int length)
            throws IOException {
        os.write('c');
        os.write(_version);
        os.write(0);

        os.write('m');
        int len = method.length();
        os.write(len >> 8);
        os.write(len);
        printString(method, 0, len);
    }

    /**
     * Writes the call tag.  This would be followed by the
     * headers and the method tag.
     * <p>
     * <code><pre>
     * c major minor
     * </pre></code>
     *
     * @param method the method name to call.
     */
    @Override
    public void startCall()
            throws IOException {
        os.write('c');
        os.write(0);
        os.write(1);
    }

    /**
     * Writes the method tag.
     * <p>
     * <code><pre>
     * m b16 b8 method-name
     * </pre></code>
     *
     * @param method the method name to call.
     */
    @Override
    public void writeMethod(String method)
            throws IOException {
        os.write('m');
        int len = method.length();
        os.write(len >> 8);
        os.write(len);
        printString(method, 0, len);
    }

    /**
     * Completes.
     * <p>
     * <code><pre>
     * z
     * </pre></code>
     */
    @Override
    public void completeCall()
            throws IOException {
        os.write('z');
    }

    /**
     * Starts the reply
     * <p>
     * <p>A successful completion will have a single value:
     * <p>
     * <pre>
     * r
     * </pre>
     */
    @Override
    public void startReply()
            throws IOException {
        os.write('r');
        os.write(1);
        os.write(0);
    }

    /**
     * Completes reading the reply
     * <p>
     * <p>A successful completion will have a single value:
     * <p>
     * <pre>
     * z
     * </pre>
     */
    @Override
    public void completeReply()
            throws IOException {
        os.write('z');
    }

    /**
     * Writes a header name.  The header value must immediately follow.
     * <p>
     * <code><pre>
     * H b16 b8 foo <em>value</em>
     * </pre></code>
     */
    @Override
    public void writeHeader(String name)
            throws IOException {
        int len = name.length();

        os.write('H');
        os.write(len >> 8);
        os.write(len);

        printString(name);
    }

    /**
     * Writes a fault.  The fault will be written
     * as a descriptive string followed by an object:
     * <p>
     * <code><pre>
     * f
     * &lt;string>code
     * &lt;string>the fault code
     * <p>
     * &lt;string>message
     * &lt;string>the fault mesage
     * <p>
     * &lt;string>detail
     * mt\x00\xnnjavax.ejb.FinderException
     *     ...
     * z
     * z
     * </pre></code>
     *
     * @param code the fault code, a three digit
     */
    @Override
    public void writeFault(String code, String message, Object detail)
            throws IOException {
        os.write('f');
        writeString("code");
        writeString(code);

        writeString("message");
        writeString(message);

        if (detail != null) {
            writeString("detail");
            writeObject(detail);
        }
        os.write('z');
    }

    /**
     * Writes any object to the output stream.
     */
    @Override
    public void writeObject(Object object)
            throws IOException {
        if (object == null) {
            writeNull();
            return;
        }

        Serializer serializer;

        serializer = _serializerFactory.getSerializer(object.getClass());

        serializer.writeObject(object, this);
    }

    /**
     * Writes the list header to the stream.  List writers will call
     * <code>writeListBegin</code> followed by the list contents and then
     * call <code>writeListEnd</code>.
     * <p>
     * <code><pre>
     * V
     * t b16 b8 type
     * l b32 b24 b16 b8
     * </pre></code>
     */
    @Override
    public boolean writeListBegin(int length, String type)
            throws IOException {
        os.write('V');

        if (type != null) {
            os.write('t');
            printLenString(type);
        }

        if (length >= 0) {
            os.write('l');
            os.write(length >> 24);
            os.write(length >> 16);
            os.write(length >> 8);
            os.write(length);
        }

        return true;
    }

    /**
     * Writes the tail of the list to the stream.
     */
    @Override
    public void writeListEnd()
            throws IOException {
        os.write('z');
    }

    /**
     * Writes the map header to the stream.  Map writers will call
     * <code>writeMapBegin</code> followed by the map contents and then
     * call <code>writeMapEnd</code>.
     * <p>
     * <code><pre>
     * Mt b16 b8 (<key> <value>)z
     * </pre></code>
     */
    @Override
    public void writeMapBegin(String type)
            throws IOException {
        os.write('M');
        os.write('t');
        printLenString(type);
    }

    /**
     * Writes the tail of the map to the stream.
     */
    @Override
    public void writeMapEnd()
            throws IOException {
        os.write('z');
    }

    /**
     * Writes a remote object reference to the stream.  The type is the
     * type of the remote interface.
     * <p>
     * <code><pre>
     * 'r' 't' b16 b8 type url
     * </pre></code>
     */
    public void writeRemote(String type, String url)
            throws IOException {
        os.write('r');
        os.write('t');
        printLenString(type);
        os.write('S');
        printLenString(url);
    }

    /**
     * Writes a boolean value to the stream.  The boolean will be written
     * with the following syntax:
     * <p>
     * <code><pre>
     * T
     * F
     * </pre></code>
     *
     * @param value the boolean value to write.
     */
    @Override
    public void writeBoolean(boolean value)
            throws IOException {
        if (value)
            os.write('T');
        else
            os.write('F');
    }

    /**
     * Writes an integer value to the stream.  The integer will be written
     * with the following syntax:
     * <p>
     * <code><pre>
     * I b32 b24 b16 b8
     * </pre></code>
     *
     * @param value the integer value to write.
     */
    @Override
    public void writeInt(int value)
            throws IOException {
        os.write('I');
        os.write(value >> 24);
        os.write(value >> 16);
        os.write(value >> 8);
        os.write(value);
    }

    /**
     * Writes a long value to the stream.  The long will be written
     * with the following syntax:
     * <p>
     * <code><pre>
     * L b64 b56 b48 b40 b32 b24 b16 b8
     * </pre></code>
     *
     * @param value the long value to write.
     */
    @Override
    public void writeLong(long value)
            throws IOException {
        os.write('L');
        os.write((byte) (value >> 56));
        os.write((byte) (value >> 48));
        os.write((byte) (value >> 40));
        os.write((byte) (value >> 32));
        os.write((byte) (value >> 24));
        os.write((byte) (value >> 16));
        os.write((byte) (value >> 8));
        os.write((byte) (value));
    }

    /**
     * Writes a double value to the stream.  The double will be written
     * with the following syntax:
     * <p>
     * <code><pre>
     * D b64 b56 b48 b40 b32 b24 b16 b8
     * </pre></code>
     *
     * @param value the double value to write.
     */
    @Override
    public void writeDouble(double value)
            throws IOException {
        long bits = Double.doubleToLongBits(value);

        os.write('D');
        os.write((byte) (bits >> 56));
        os.write((byte) (bits >> 48));
        os.write((byte) (bits >> 40));
        os.write((byte) (bits >> 32));
        os.write((byte) (bits >> 24));
        os.write((byte) (bits >> 16));
        os.write((byte) (bits >> 8));
        os.write((byte) (bits));
    }

    /**
     * Writes a date to the stream.
     * <p>
     * <code><pre>
     * T  b64 b56 b48 b40 b32 b24 b16 b8
     * </pre></code>
     *
     * @param time the date in milliseconds from the epoch in UTC
     */
    @Override
    public void writeUTCDate(long time)
            throws IOException {
        os.write('d');
        os.write((byte) (time >> 56));
        os.write((byte) (time >> 48));
        os.write((byte) (time >> 40));
        os.write((byte) (time >> 32));
        os.write((byte) (time >> 24));
        os.write((byte) (time >> 16));
        os.write((byte) (time >> 8));
        os.write((byte) (time));
    }

    /**
     * Writes a null value to the stream.
     * The null will be written with the following syntax
     * <p>
     * <code><pre>
     * N
     * </pre></code>
     *
     * @param value the string value to write.
     */
    @Override
    public void writeNull()
            throws IOException {
        os.write('N');
    }

    /**
     * Writes a string value to the stream using UTF-8 encoding.
     * The string will be written with the following syntax:
     * <p>
     * <code><pre>
     * S b16 b8 string-value
     * </pre></code>
     * <p>
     * If the value is null, it will be written as
     * <p>
     * <code><pre>
     * N
     * </pre></code>
     *
     * @param value the string value to write.
     */
    @Override
    public void writeString(String value)
            throws IOException {
        if (value == null) {
            os.write('N');
        } else {
            int length = value.length();
            int offset = 0;

            while (length > 0x8000) {
                int sublen = 0x8000;

                // chunk can't end in high surrogate
                char tail = value.charAt(offset + sublen - 1);

                if (0xd800 <= tail && tail <= 0xdbff)
                    sublen--;

                os.write('s');
                os.write(sublen >> 8);
                os.write(sublen);

                printString(value, offset, sublen);

                length -= sublen;
                offset += sublen;
            }

            os.write('S');
            os.write(length >> 8);
            os.write(length);

            printString(value, offset, length);
        }
    }

    /**
     * Writes a string value to the stream using UTF-8 encoding.
     * The string will be written with the following syntax:
     * <p>
     * <code><pre>
     * S b16 b8 string-value
     * </pre></code>
     * <p>
     * If the value is null, it will be written as
     * <p>
     * <code><pre>
     * N
     * </pre></code>
     *
     * @param value the string value to write.
     */
    @Override
    public void writeString(char[] buffer, int offset, int length)
            throws IOException {
        if (buffer == null) {
            os.write('N');
        } else {
            while (length > 0x8000) {
                int sublen = 0x8000;

                // chunk can't end in high surrogate
                char tail = buffer[offset + sublen - 1];

                if (0xd800 <= tail && tail <= 0xdbff)
                    sublen--;

                os.write('s');
                os.write(sublen >> 8);
                os.write(sublen);

                printString(buffer, offset, sublen);

                length -= sublen;
                offset += sublen;
            }

            os.write('S');
            os.write(length >> 8);
            os.write(length);

            printString(buffer, offset, length);
        }
    }

    /**
     * Writes a byte array to the stream.
     * The array will be written with the following syntax:
     * <p>
     * <code><pre>
     * B b16 b18 bytes
     * </pre></code>
     * <p>
     * If the value is null, it will be written as
     * <p>
     * <code><pre>
     * N
     * </pre></code>
     *
     * @param value the string value to write.
     */
    @Override
    public void writeBytes(byte[] buffer)
            throws IOException {
        if (buffer == null)
            os.write('N');
        else
            writeBytes(buffer, 0, buffer.length);
    }

    /**
     * Writes a byte array to the stream.
     * The array will be written with the following syntax:
     * <p>
     * <code><pre>
     * B b16 b18 bytes
     * </pre></code>
     * <p>
     * If the value is null, it will be written as
     * <p>
     * <code><pre>
     * N
     * </pre></code>
     *
     * @param value the string value to write.
     */
    @Override
    public void writeBytes(byte[] buffer, int offset, int length)
            throws IOException {
        if (buffer == null) {
            os.write('N');
        } else {
            while (length > 0x8000) {
                int sublen = 0x8000;

                os.write('b');
                os.write(sublen >> 8);
                os.write(sublen);

                os.write(buffer, offset, sublen);

                length -= sublen;
                offset += sublen;
            }

            os.write('B');
            os.write(length >> 8);
            os.write(length);
            os.write(buffer, offset, length);
        }
    }

    /**
     * Writes a byte buffer to the stream.
     * <p>
     * <code><pre>
     * </pre></code>
     */
    @Override
    public void writeByteBufferStart()
            throws IOException {
    }

    /**
     * Writes a byte buffer to the stream.
     * <p>
     * <code><pre>
     * b b16 b18 bytes
     * </pre></code>
     */
    @Override
    public void writeByteBufferPart(byte[] buffer, int offset, int length)
            throws IOException {
        while (length > 0) {
            int sublen = length;

            if (0x8000 < sublen)
                sublen = 0x8000;

            os.write('b');
            os.write(sublen >> 8);
            os.write(sublen);

            os.write(buffer, offset, sublen);

            length -= sublen;
            offset += sublen;
        }
    }

    /**
     * Writes a byte buffer to the stream.
     * <p>
     * <code><pre>
     * b b16 b18 bytes
     * </pre></code>
     */
    @Override
    public void writeByteBufferEnd(byte[] buffer, int offset, int length)
            throws IOException {
        writeBytes(buffer, offset, length);
    }

    /**
     * Writes a reference.
     * <p>
     * <code><pre>
     * R b32 b24 b16 b8
     * </pre></code>
     *
     * @param value the integer value to write.
     */
    @Override
    public void writeRef(int value)
            throws IOException {
        os.write('R');
        os.write(value >> 24);
        os.write(value >> 16);
        os.write(value >> 8);
        os.write(value);
    }

    /**
     * Writes a placeholder.
     * <p>
     * <code><pre>
     * P
     * </pre></code>
     */
    public void writePlaceholder()
            throws IOException {
        os.write('P');
    }

    /**
     * If the object has already been written, just write its ref.
     *
     * @return true if we're writing a ref.
     */
    @Override
    public boolean addRef(Object object)
            throws IOException {
        if (_refs == null)
            _refs = new IdentityHashMap();

        Integer ref = (Integer) _refs.get(object);

        if (ref != null) {
            int value = ref.intValue();

            writeRef(value);
            return true;
        } else {
            _refs.put(object, new Integer(_refs.size()));

            return false;
        }
    }

    /**
     * Resets the references for streaming.
     */
    @Override
    public void resetReferences() {
        if (_refs != null)
            _refs.clear();
    }

    /**
     * Removes a reference.
     */
    @Override
    public boolean removeRef(Object obj)
            throws IOException {
        if (_refs != null) {
            _refs.remove(obj);

            return true;
        } else
            return false;
    }

    /**
     * Replaces a reference from one object to another.
     */
    @Override
    public boolean replaceRef(Object oldRef, Object newRef)
            throws IOException {
        Integer value = (Integer) _refs.remove(oldRef);

        if (value != null) {
            _refs.put(newRef, value);
            return true;
        } else
            return false;
    }

    /**
     * Prints a string to the stream, encoded as UTF-8 with preceeding length
     *
     * @param v the string to print.
     */
    public void printLenString(String v)
            throws IOException {
        if (v == null) {
            os.write(0);
            os.write(0);
        } else {
            int len = v.length();
            os.write(len >> 8);
            os.write(len);

            printString(v, 0, len);
        }
    }

    /**
     * Prints a string to the stream, encoded as UTF-8
     *
     * @param v the string to print.
     */
    public void printString(String v)
            throws IOException {
        printString(v, 0, v.length());
    }

    /**
     * Prints a string to the stream, encoded as UTF-8
     *
     * @param v the string to print.
     */
    public void printString(String v, int offset, int length)
            throws IOException {
        for (int i = 0; i < length; i++) {
            char ch = v.charAt(i + offset);

            if (ch < 0x80)
                os.write(ch);
            else if (ch < 0x800) {
                os.write(0xc0 + ((ch >> 6) & 0x1f));
                os.write(0x80 + (ch & 0x3f));
            } else {
                os.write(0xe0 + ((ch >> 12) & 0xf));
                os.write(0x80 + ((ch >> 6) & 0x3f));
                os.write(0x80 + (ch & 0x3f));
            }
        }
    }

    /**
     * Prints a string to the stream, encoded as UTF-8
     *
     * @param v the string to print.
     */
    public void printString(char[] v, int offset, int length)
            throws IOException {
        for (int i = 0; i < length; i++) {
            char ch = v[i + offset];

            if (ch < 0x80)
                os.write(ch);
            else if (ch < 0x800) {
                os.write(0xc0 + ((ch >> 6) & 0x1f));
                os.write(0x80 + (ch & 0x3f));
            } else {
                os.write(0xe0 + ((ch >> 12) & 0xf));
                os.write(0x80 + ((ch >> 6) & 0x3f));
                os.write(0x80 + (ch & 0x3f));
            }
        }
    }

    @Override
    public void flush()
            throws IOException {
        if (this.os != null)
            this.os.flush();
    }

    @Override
    public void close()
            throws IOException {
        if (this.os != null)
            this.os.flush();
    }
}
