/*
 * 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 dalvik.annotation.compat.UnsupportedAppUsage;
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.
 *
 * @hide
 */
@libcore.api.CorePlatformApi
public abstract class ChunkHandler {

    @UnsupportedAppUsage
    @libcore.api.CorePlatformApi
    public static final ByteOrder CHUNK_ORDER = ByteOrder.BIG_ENDIAN;

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


    @libcore.api.CorePlatformApi
    public ChunkHandler() {}

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

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

    /**
     * Handle a single chunk of data.  "request" includes the type and
     * the chunk payload.
     *
     * Returns a response in a Chunk.
     */
    @libcore.api.CorePlatformApi
    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.
     */
    @libcore.api.CorePlatformApi
    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.
     */
    @libcore.api.CorePlatformApi
    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.
     */
    @libcore.api.CorePlatformApi
    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.
     */
    @libcore.api.CorePlatformApi
    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.
     */
    @libcore.api.CorePlatformApi
    public static int type(String typeName) {
        if (typeName.length() != 4) {
            throw new IllegalArgumentException("Bad type name: " + typeName);
        }
        int result = 0;
        for (int i = 0; i < 4; ++i) {
            result = ((result << 8) | (typeName.charAt(i) & 0xff));
        }
        return result;
    }

    /**
     * Convert an integer type to a 4-character string.
     */
    @libcore.api.CorePlatformApi
    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);
    }

}
