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

import java.io.IOException;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;

/**
 * Handle the "hello" chunk (HELO) and feature discovery.
 */
final class HandleHello extends ChunkHandler {

    public static final int CHUNK_HELO = ChunkHandler.type("HELO");
    public static final int CHUNK_FEAT = ChunkHandler.type("FEAT");

    private static final HandleHello mInst = new HandleHello();

    private HandleHello() {}

    /**
     * Register for the packets we expect to get from the client.
     */
    public static void register(MonitorThread mt) {
        mt.registerChunkHandler(CHUNK_HELO, mInst);
    }

    /**
     * Client is ready.
     */
    @Override
    public void clientReady(Client client) throws IOException {
        Log.d("ddm-hello", "Now ready: " + client);
    }

    /**
     * Client went away.
     */
    @Override
    public void clientDisconnected(Client client) {
        Log.d("ddm-hello", "Now disconnected: " + client);
    }

    /**
     * Sends HELLO-type commands to the VM after a good handshake.
     * @param client
     * @param serverProtocolVersion
     * @throws IOException
     */
    public static void sendHelloCommands(Client client, int serverProtocolVersion)
            throws IOException {
        sendHELO(client, serverProtocolVersion);
        sendFEAT(client);
        HandleProfiling.sendMPRQ(client);
    }

    /**
     * Chunk handler entry point.
     */
    @Override
    public void handleChunk(Client client, int type, ByteBuffer data, boolean isReply, int msgId) {

        Log.d("ddm-hello", "handling " + ChunkHandler.name(type));

        if (type == CHUNK_HELO) {
            assert isReply;
            handleHELO(client, data);
        } else if (type == CHUNK_FEAT) {
            handleFEAT(client, data);
        } else {
            handleUnknownChunk(client, type, data, isReply, msgId);
        }
    }

    /*
     * Handle a reply to our HELO message.
     */
    private static void handleHELO(Client client, ByteBuffer data) {
        int version, pid, vmIdentLen, appNameLen;
        String vmIdent, appName;

        version = data.getInt();
        pid = data.getInt();
        vmIdentLen = data.getInt();
        appNameLen = data.getInt();

        vmIdent = ByteBufferUtil.getString(data, vmIdentLen);
        appName = ByteBufferUtil.getString(data, appNameLen);

        // Newer devices send user id in the APNM packet.
        int userId = -1;
        boolean validUserId = false;
        if (data.hasRemaining()) {
            try {
                userId = data.getInt();
                validUserId = true;
            } catch (BufferUnderflowException e) {
                // five integers + two utf-16 strings
                int expectedPacketLength = 20 + appNameLen * 2 + vmIdentLen * 2;

                Log.e("ddm-hello", "Insufficient data in HELO chunk to retrieve user id.");
                Log.e("ddm-hello", "Actual chunk length: " + data.capacity());
                Log.e("ddm-hello", "Expected chunk length: " + expectedPacketLength);
            }
        }

        // check if the VM has reported information about the ABI
        boolean validAbi = false;
        String abi = null;
        if (data.hasRemaining()) {
            try {
                int abiLength = data.getInt();
                abi = ByteBufferUtil.getString(data, abiLength);
                validAbi = true;
            } catch (BufferUnderflowException e) {
                Log.e("ddm-hello", "Insufficient data in HELO chunk to retrieve ABI.");
            }
        }

        boolean hasJvmFlags = false;
        String jvmFlags = null;
        if (data.hasRemaining()) {
            try {
                int jvmFlagsLength = data.getInt();
                jvmFlags = ByteBufferUtil.getString(data, jvmFlagsLength);
                hasJvmFlags = true;
            } catch (BufferUnderflowException e) {
                Log.e("ddm-hello", "Insufficient data in HELO chunk to retrieve JVM flags");
            }
        }

        Log.d("ddm-hello", "HELO: v=" + version + ", pid=" + pid
            + ", vm='" + vmIdent + "', app='" + appName + "'");

        ClientData cd = client.getClientData();

        if (cd.getPid() == pid) {
            cd.setVmIdentifier(vmIdent);
            cd.setClientDescription(appName);
            cd.isDdmAware(true);

            if (validUserId) {
                cd.setUserId(userId);
            }

            if (validAbi) {
                cd.setAbi(abi);
            }

            if (hasJvmFlags) {
                cd.setJvmFlags(jvmFlags);
            }
        } else {
            Log.e("ddm-hello", "Received pid (" + pid + ") does not match client pid ("
                    + cd.getPid() + ")");
        }

        client = checkDebuggerPortForAppName(client, appName);

        if (client != null) {
            client.update(Client.CHANGE_NAME);
        }
    }


    /**
     * Send a HELO request to the client.
     */
    public static void sendHELO(Client client, int serverProtocolVersion)
        throws IOException
    {
        ByteBuffer rawBuf = allocBuffer(4);
        JdwpPacket packet = new JdwpPacket(rawBuf);
        ByteBuffer buf = getChunkDataBuf(rawBuf);

        buf.putInt(serverProtocolVersion);

        finishChunkPacket(packet, CHUNK_HELO, buf.position());
        Log.d("ddm-hello", "Sending " + name(CHUNK_HELO)
            + " ID=0x" + Integer.toHexString(packet.getId()));
        client.sendAndConsume(packet, mInst);
    }

    /**
     * Handle a reply to our FEAT request.
     */
    private static void handleFEAT(Client client, ByteBuffer data) {
        int featureCount;
        int i;

        featureCount = data.getInt();
        for (i = 0; i < featureCount; i++) {
            int len = data.getInt();
            String feature = ByteBufferUtil.getString(data, len);
            client.getClientData().addFeature(feature);

            Log.d("ddm-hello", "Feature: " + feature);
        }
    }

    /**
     * Send a FEAT request to the client.
     */
    public static void sendFEAT(Client client) throws IOException {
        ByteBuffer rawBuf = allocBuffer(0);
        JdwpPacket packet = new JdwpPacket(rawBuf);
        ByteBuffer buf = getChunkDataBuf(rawBuf);

        // no data

        finishChunkPacket(packet, CHUNK_FEAT, buf.position());
        Log.d("ddm-heap", "Sending " + name(CHUNK_FEAT));
        client.sendAndConsume(packet, mInst);
    }
}

