/*
 * 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.
 */

package dxconvext;

import com.android.dx.cf.direct.ClassPathOpener;
import com.android.dx.cf.direct.DirectClassFile;
import com.android.dx.cf.direct.StdAttributeFactory;
import com.android.dx.cf.iface.Member;
import com.android.dx.cf.iface.ParseObserver;
import com.android.dx.util.ByteArray;
import com.android.dx.util.FileUtils;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;

public class ClassFileParser {

    private BufferedWriter bw; // the writer to write the result to.

    /**
     * Parses a .class file and outputs a .cfh (class file in hex format) file.
     * 
     * args[0] is the absolute path to the java src directory e.g.
     * /home/fjost/android/workspace/dxconverter/src
     * 
     * args[1] is the absolute path to the classes directory e.g.
     * /home/fjost/android/workspace/out/classes_javac this is the place where
     * 
     * args[2] is the absolute path to the java source file, e.g.
     * /home/fjost/android/workspace/dxconverter/src/test/MyTest.java
     * 
     * 
     * 
     * @param args
     */
    public static void main(String[] args) throws IOException {
        ClassFileParser cfp = new ClassFileParser();
        cfp.process(args[0], args[1], args[2]);
    }

    private void process(final String srcDir, final String classesDir,
            final String absSrcFilePath) throws IOException {
        ClassPathOpener opener;

        String fileName = absSrcFilePath;
        // e.g. test/p1/MyTest.java
        String pckPath = fileName.substring(srcDir.length() + 1);
        // e.g. test/p1
        String pck = pckPath.substring(0, pckPath.lastIndexOf("/"));
        // e.g. MyTest
        String cName = pckPath.substring(pck.length() + 1);
        cName = cName.substring(0, cName.lastIndexOf("."));
        String cfName = pck+"/"+cName+".class";
        // 2. calculate the target file name:
        // e.g. <out-path>/test/p1/MyTest.class
        String inFile = classesDir + "/" + pck + "/" + cName + ".class";
        if (!new File(inFile).exists()) {
            throw new RuntimeException("cannot read:" + inFile);
        }
        byte[] bytes = FileUtils.readFile(inFile);
        // write the outfile to the same directory as the corresponding .java
        // file
        String outFile = absSrcFilePath.substring(0, absSrcFilePath
                .lastIndexOf("/"))+ "/" + cName + ".cfh";
        Writer w;
        try {
            w = new OutputStreamWriter(new FileOutputStream(new File(outFile)));
        } catch (FileNotFoundException e) {
            throw new RuntimeException("cannot write to file:"+outFile, e);
        }
        // Writer w = new OutputStreamWriter(System.out);
        ClassFileParser.this.processFileBytes(w, cfName, bytes);
    }

    /**
     *
     * @param w the writer to write the generated .cfh file to
     * @param name the relative name of the java src file, e.g.
     *        dxc/util/Util.java
     * @param allbytes the bytes of this java src file
     * @return true if everything went alright
     */
    void processFileBytes(Writer w, String name, final byte[] allbytes) throws IOException {
        String fixedPathName = fixPath(name);
        DirectClassFile cf = new DirectClassFile(allbytes, fixedPathName, true);
        bw = new BufferedWriter(w);
        String className = fixedPathName.substring(0, fixedPathName.lastIndexOf("."));
        out("//@class:" + className, 0);
        cf.setObserver(new ParseObserver() {
            private int cur_indent = 0;
            private int checkpos = 0;

            /**
             * Indicate that the level of indentation for a dump should increase
             * or decrease (positive or negative argument, respectively).
             * 
             * @param indentDelta the amount to change indentation
             */
            public void changeIndent(int indentDelta) {
                cur_indent += indentDelta;
            }

            /**
             * Indicate that a particular member is now being parsed.
             * 
             * @param bytes non-null; the source that is being parsed
             * @param offset offset into <code>bytes</code> for the start of
             *        the member
             * @param name non-null; name of the member
             * @param descriptor non-null; descriptor of the member
             */
            public void startParsingMember(ByteArray bytes, int offset,
                    String name, String descriptor) {
                // ByteArray ba = bytes.slice(offset, bytes.size());
                out("// ========== start-ParseMember:" + name + ", offset "
                        + offset + ", len:" + (bytes.size() - offset)
                        + ",desc: " + descriptor);
                // out("// "+dumpReadableString(ba));
                // out(" "+dumpBytes(ba));
            }

            /**
             * Indicate that a particular member is no longer being parsed.
             * 
             * @param bytes non-null; the source that was parsed
             * @param offset offset into <code>bytes</code> for the end of the
             *        member
             * @param name non-null; name of the member
             * @param descriptor non-null; descriptor of the member
             * @param member non-null; the actual member that was parsed
             */
            public void endParsingMember(ByteArray bytes, int offset,
                    String name, String descriptor, Member member) {
                ByteArray ba = bytes.slice(offset, bytes.size());
                out("// ========== end-ParseMember:" + name + ", desc: "
                        + descriptor);
                // out("// "+dumpReadableString(ba));
                // out(" "+dumpBytes(ba));
            }

            /**
             * Indicate that some parsing happened.
             * 
             * @param bytes non-null; the source that was parsed
             * @param offset offset into <code>bytes</code> for what was
             *        parsed
             * @param len number of bytes parsed
             * @param human non-null; human form for what was parsed
             */
            public void parsed(ByteArray bytes, int offset, int len,
                    String human) {
                human = human.replace('\n', ' ');
                out("// parsed:" + ", offset " + offset + ", len " + len
                        + ", h: " + human);
                if (len > 0) {
                    ByteArray ba = bytes.slice(offset, offset + len);
                    check(ba);
                    out("// " + dumpReadableString(ba));
                    out("   " + dumpBytes(ba));
                }
            }

            private void out(String msg) {
                ClassFileParser.this.out(msg, cur_indent);

            }

            private void check(ByteArray ba) {
                int len = ba.size();
                int offset = checkpos;
                for (int i = 0; i < len; i++) {
                    int b = ba.getByte(i);
                    byte b2 = allbytes[i + offset];
                    if (b != b2)
                        throw new RuntimeException("byte dump mismatch at pos "
                                + (i + offset));
                }
                checkpos += len;
            }

            private String dumpBytes(ByteArray ba) {
                String s = "";
                for (int i = 0; i < ba.size(); i++) {
                    int byt = ba.getUnsignedByte(i);
                    String hexVal = Integer.toHexString(byt);
                    if (hexVal.length() == 1) {
                        hexVal = "0" + hexVal;
                    }
                    s += hexVal + " ";
                }
                return s;
            }

            private String dumpReadableString(ByteArray ba) {
                String s = "";
                for (int i = 0; i < ba.size(); i++) {
                    int bb = ba.getUnsignedByte(i);
                    if (bb > 31 && bb < 127) {
                        s += (char) bb;
                    } else {
                        s += ".";
                    }
                    s += "  ";
                }
                return s;
            }
        });
        cf.setAttributeFactory(StdAttributeFactory.THE_ONE);
        // what is needed to force parsing to the end?
        cf.getMagic();
        // cf.getFields();
        // cf.getAttributes();
        // cf.getMethods();
        bw.close();
    }

    private String getIndent(int indent) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < indent * 4; i++) {
            sb.append(' ');
        }
        return sb.toString();
    }

    private void out(String msg, int cur_indent) {
        try {
            bw.write(getIndent(cur_indent) + msg);
            bw.newLine();
        } catch (IOException ioe) {
            throw new RuntimeException("error while writing to the writer", ioe);
        }
    }

    private static String fixPath(String path) {
        /*
         * If the path separator is \ (like on windows), we convert the path to
         * a standard '/' separated path.
         */
        if (File.separatorChar == '\\') {
            path = path.replace('\\', '/');
        }

        int index = path.lastIndexOf("/./");

        if (index != -1) {
            return path.substring(index + 3);
        }

        if (path.startsWith("./")) {
            return path.substring(2);
        }

        return path;
    }
}
