/*
 * Copyright (C) 2007 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 org.apache.harmony.dalvik.ddmc;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

/**
 * Handle a chunk of data sent from a DDM server.
 *
 * To handle a chunk type, sub-class ChunkHandler and register your class
 * with DdmServer.
 */
public abstract class ChunkHandler {

    public static final ByteOrder CHUNK_ORDER = ByteOrder.BIG_ENDIAN;

    public static final int CHUNK_FAIL = type("FAIL");


    public ChunkHandler() {}

    /**
     * Called when the DDM server connects.  The handler is allowed to
     * send messages to the server.
     */
    public abstract void connected();

    /**
     * Called when the DDM server disconnects.  Can be used to disable
     * periodic transmissions or clean up saved state.
     */
    public abstract void disconnected();

    /**
     * Handle a single chunk of data.  "request" includes the type and
     * the chunk payload.
     *
     * Returns a response in a Chunk.
     */
    public abstract Chunk handleChunk(Chunk request);

    /**
     * Create a FAIL chunk.  The "handleChunk" methods can use this to
     * return an error message when they are not able to process a chunk.
     */
    public static Chunk createFailChunk(int errorCode, String msg) {
        if (msg == null)
            msg = "";

        ByteBuffer out = ByteBuffer.allocate(8 + msg.length() * 2);
        out.order(ChunkHandler.CHUNK_ORDER);
        out.putInt(errorCode);
        out.putInt(msg.length());
        putString(out, msg);

        return new Chunk(CHUNK_FAIL, out);
    }

    /**
     * Utility function to wrap a ByteBuffer around a Chunk.
     */
    public static ByteBuffer wrapChunk(Chunk request) {
        ByteBuffer in;

        in = ByteBuffer.wrap(request.data, request.offset, request.length);
        in.order(CHUNK_ORDER);
        return in;
    }


    /**
     * Utility function to copy a String out of a ByteBuffer.
     *
     * This is here because multiple chunk handlers can make use of it,
     * and there's nowhere better to put it.
     */
    public static String getString(ByteBuffer buf, int len) {
        char[] data = new char[len];
        for (int i = 0; i < len; i++)
            data[i] = buf.getChar();
        return new String(data);
    }

    /**
     * Utility function to copy a String into a ByteBuffer.
     */
    public static void putString(ByteBuffer buf, String str) {
        int len = str.length();
        for (int i = 0; i < len; i++)
            buf.putChar(str.charAt(i));
    }

    /**
     * Convert a 4-character string to a 32-bit type.
     */
    public static int type(String typeName)
    {
        int val = 0;

        if (typeName.length() != 4)
            throw new RuntimeException();

        for (int i = 0; i < 4; i++) {
            val <<= 8;
            val |= (byte) typeName.charAt(i);
        }

        return val;
    }

    /**
     * Convert an integer type to a 4-character string.
     */
    public static String name(int type)
    {
        char[] ascii = new char[4];

        ascii[0] = (char) ((type >> 24) & 0xff);
        ascii[1] = (char) ((type >> 16) & 0xff);
        ascii[2] = (char) ((type >> 8) & 0xff);
        ascii[3] = (char) (type & 0xff);

        return new String(ascii);
    }

}

