/*
 * Copyright (C) 2008 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.
 */

/**
 * One line from the loaded-classes file.
 */
class Record {

    /**
     * The delimiter character we use, {@code :}, conflicts with some other
     * names. In that case, manually replace the delimiter with something else.
     */
    private static final String[] REPLACE_CLASSES = {
            "com.google.android.apps.maps:FriendService",
            "com.google.android.apps.maps\\u003AFriendService",
            "com.google.android.apps.maps:driveabout",
            "com.google.android.apps.maps\\u003Adriveabout",
            "com.google.android.apps.maps:LocationFriendService",
            "com.google.android.apps.maps\\u003ALocationFriendService",
    };

    enum Type {
        /** Start of initialization. */
        START_LOAD,

        /** End of initialization. */
        END_LOAD,

        /** Start of initialization. */
        START_INIT,

        /** End of initialization. */
        END_INIT
    }

    /** Parent process ID. */
    final int ppid;

    /** Process ID. */
    final int pid;

    /** Thread ID. */
    final int tid;

    /** Process name. */
    final String processName;

    /** Class loader pointer. */
    final int classLoader;

    /** Type of record. */
    final Type type;

    /** Name of loaded class. */
    final String className;

    /** Record time (ns). */
    final long time;
    
    /** Source file line# */
    int sourceLineNumber;

    /**
     * Parses a line from the loaded-classes file.
     */
    Record(String line, int lineNum) {
        char typeChar = line.charAt(0);
        switch (typeChar) {
            case '>': type = Type.START_LOAD; break;
            case '<': type = Type.END_LOAD; break;
            case '+': type = Type.START_INIT; break;
            case '-': type = Type.END_INIT; break;
            default: throw new AssertionError("Bad line: " + line);
        }

        sourceLineNumber = lineNum;

        for (int i = 0; i < REPLACE_CLASSES.length; i+= 2) {
            line = line.replace(REPLACE_CLASSES[i], REPLACE_CLASSES[i+1]);
        }
        
        line = line.substring(1);
        String[] parts = line.split(":");

        ppid = Integer.parseInt(parts[0]);
        pid = Integer.parseInt(parts[1]);
        tid = Integer.parseInt(parts[2]);

        processName = decode(parts[3]).intern();

        classLoader = Integer.parseInt(parts[4]);
        className = vmTypeToLanguage(decode(parts[5])).intern();

        time = Long.parseLong(parts[6]);
    }
    
    /**
     * Decode any escaping that may have been written to the log line.
     * 
     * Supports unicode-style escaping:  \\uXXXX = character in hex
     * 
     * @param rawField the field as it was written into the log
     * @result the same field with any escaped characters replaced
     */
    String decode(String rawField) {
        String result = rawField;
        int offset = result.indexOf("\\u");
        while (offset >= 0) {
            String before = result.substring(0, offset);
            String escaped = result.substring(offset+2, offset+6);
            String after = result.substring(offset+6);
            
            result = String.format("%s%c%s", before, Integer.parseInt(escaped, 16), after);

            // find another but don't recurse  
            offset = result.indexOf("\\u", offset + 1);          
        }
        return result;
    }

    /**
     * Converts a VM-style name to a language-style name.
     */
    String vmTypeToLanguage(String typeName) {
        // if the typename is (null), just return it as-is.  This is probably in dexopt and 
        // will be discarded anyway.  NOTE: This corresponds to the case in dalvik/vm/oo/Class.c
        // where dvmLinkClass() returns false and we clean up and exit.
        if ("(null)".equals(typeName)) {
            return typeName;
        }
        
        if (!typeName.startsWith("L") || !typeName.endsWith(";") ) {
            throw new AssertionError("Bad name: " + typeName + " in line " + sourceLineNumber);
        }

        typeName = typeName.substring(1, typeName.length() - 1);
        return typeName.replace("/", ".");
    }
}
