/*
 * 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 android.ddm;

import org.apache.harmony.dalvik.ddmc.Chunk;
import org.apache.harmony.dalvik.ddmc.ChunkHandler;
import org.apache.harmony.dalvik.ddmc.DdmServer;
import android.util.Config;
import android.util.Log;
import android.os.Debug;

import java.nio.ByteBuffer;

/**
 * Handle "hello" messages and feature discovery.
 */
public class DdmHandleHello extends ChunkHandler {

    public static final int CHUNK_HELO = type("HELO");
    public static final int CHUNK_WAIT = type("WAIT");
    public static final int CHUNK_FEAT = type("FEAT");

    private static DdmHandleHello mInstance = new DdmHandleHello();


    /* singleton, do not instantiate */
    private DdmHandleHello() {}

    /**
     * Register for the messages we're interested in.
     */
    public static void register() {
        DdmServer.registerHandler(CHUNK_HELO, mInstance);
        DdmServer.registerHandler(CHUNK_FEAT, mInstance);
    }

    /**
     * Called when the DDM server connects.  The handler is allowed to
     * send messages to the server.
     */
    public void connected() {
        if (Config.LOGV)
            Log.v("ddm-hello", "Connected!");

        if (false) {
            /* test spontaneous transmission */
            byte[] data = new byte[] { 0, 1, 2, 3, 4, -4, -3, -2, -1, 127 };
            Chunk testChunk =
                new Chunk(ChunkHandler.type("TEST"), data, 1, data.length-2);
            DdmServer.sendChunk(testChunk);
        }
    }

    /**
     * Called when the DDM server disconnects.  Can be used to disable
     * periodic transmissions or clean up saved state.
     */
    public void disconnected() {
        if (Config.LOGV)
            Log.v("ddm-hello", "Disconnected!");
    }

    /**
     * Handle a chunk of data.
     */
    public Chunk handleChunk(Chunk request) {
        if (Config.LOGV)
            Log.v("ddm-heap", "Handling " + name(request.type) + " chunk");
        int type = request.type;

        if (type == CHUNK_HELO) {
            return handleHELO(request);
        } else if (type == CHUNK_FEAT) {
            return handleFEAT(request);
        } else {
            throw new RuntimeException("Unknown packet "
                + ChunkHandler.name(type));
        }
    }

    /*
     * Handle introductory packet.
     */
    private Chunk handleHELO(Chunk request) {
        if (false)
            return createFailChunk(123, "This is a test");

        /*
         * Process the request.
         */
        ByteBuffer in = wrapChunk(request);

        int serverProtoVers = in.getInt();
        if (Config.LOGV)
            Log.v("ddm-hello", "Server version is " + serverProtoVers);

        /*
         * Create a response.
         */
        String vmName = System.getProperty("java.vm.name", "?");
        String vmVersion = System.getProperty("java.vm.version", "?");
        String vmIdent = vmName + " v" + vmVersion;

        //String appName = android.app.ActivityThread.currentPackageName();
        //if (appName == null)
        //    appName = "unknown";
        String appName = DdmHandleAppName.getAppName();

        ByteBuffer out = ByteBuffer.allocate(16
                            + vmIdent.length()*2 + appName.length()*2);
        out.order(ChunkHandler.CHUNK_ORDER);
        out.putInt(DdmServer.CLIENT_PROTOCOL_VERSION);
        out.putInt(android.os.Process.myPid());
        out.putInt(vmIdent.length());
        out.putInt(appName.length());
        putString(out, vmIdent);
        putString(out, appName);

        Chunk reply = new Chunk(CHUNK_HELO, out);

        /*
         * Take the opportunity to inform DDMS if we are waiting for a
         * debugger to attach.
         */
        if (Debug.waitingForDebugger())
            sendWAIT(0);

        return reply;
    }

    /*
     * Handle request for list of supported features.
     */
    private Chunk handleFEAT(Chunk request) {
        // TODO: query the VM to ensure that support for these features
        // is actually compiled in
        final String[] features = Debug.getVmFeatureList();

        if (Config.LOGV)
            Log.v("ddm-heap", "Got feature list request");

        int size = 4 + 4 * features.length;
        for (int i = features.length-1; i >= 0; i--)
            size += features[i].length() * 2;

        ByteBuffer out = ByteBuffer.allocate(size);
        out.order(ChunkHandler.CHUNK_ORDER);
        out.putInt(features.length);
        for (int i = features.length-1; i >= 0; i--) {
            out.putInt(features[i].length());
            putString(out, features[i]);
        }

        return new Chunk(CHUNK_FEAT, out);
    }

    /**
     * Send up a WAIT chunk.  The only currently defined value for "reason"
     * is zero, which means "waiting for a debugger".
     */
    public static void sendWAIT(int reason) {
        byte[] data = new byte[] { (byte) reason };
        Chunk waitChunk = new Chunk(CHUNK_WAIT, data, 0, 1);
        DdmServer.sendChunk(waitChunk);
    }
}

