/*
 * Copyright 2007 Google Inc.
 *
 * 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.tonicsystems.jarjar.util;

import java.io.*;
import java.lang.reflect.Array;
import java.util.*;

public class ClassHeaderReader {
  private int access;
  private String thisClass;
  private String superClass;
  private String[] interfaces;

  private InputStream in;
  private byte[] b = new byte[0x2000];
  private int[] items = new int[1000];
  private int bsize = 0;
  private MyByteArrayInputStream bin = new MyByteArrayInputStream();
  private DataInputStream data = new DataInputStream(bin);

  public int getAccess() {
    return access;
  }

  public String getClassName() {
    return thisClass;
  }

  public String getSuperName() {
    return superClass;
  }

  public String[] getInterfaces() {
    return interfaces;
  }

  public void read(InputStream in) throws IOException {
    try {
      this.in = in;
      bsize = 0;
      access = 0;
      thisClass = superClass = null;
      interfaces = null;

      try {
        buffer(4);
      } catch (IOException e) {
        // ignore
      }
      if (b[0] != (byte) 0xCA
          || b[1] != (byte) 0xFE
          || b[2] != (byte) 0xBA
          || b[3] != (byte) 0xBE) {
        throw new ClassFormatError("Bad magic number");
      }

      buffer(6);
      readUnsignedShort(4); // minorVersion
      readUnsignedShort(6); // majorVersion
      // TODO: check version
      int constant_pool_count = readUnsignedShort(8);
      items = (int[]) resizeArray(items, constant_pool_count);

      int index = 10;
      for (int i = 1; i < constant_pool_count; i++) {
        int size;
        buffer(index + 3); // TODO: reduce calls to buffer
        int tag = b[index];
        items[i] = index + 1;
        switch (tag) {
          case 9: // Fieldref
          case 10: // Methodref
          case 11: // InterfaceMethodref
          case 3: // Integer
          case 4: // Float
          case 12: // NameAndType
            size = 4;
            break;
          case 5: // Long
          case 6: // Double
            size = 8;
            i++;
            break;
          case 1: // Utf8
            size = 2 + readUnsignedShort(index + 1);
            break;
          case 7: // Class
          case 8: // String
            size = 2;
            break;
          default:
            throw new IllegalStateException("Unknown constant pool tag " + tag);
        }
        index += size + 1;
      }
      buffer(index + 8);
      access = readUnsignedShort(index);
      thisClass = readClass(index + 2);
      superClass = readClass(index + 4);
      int interfaces_count = readUnsignedShort(index + 6);

      index += 8;
      buffer(index + interfaces_count * 2);
      interfaces = new String[interfaces_count];
      for (int i = 0; i < interfaces_count; i++) {
        interfaces[i] = readClass(index);
        index += 2;
      }
    } finally {
      in.close();
    }
  }

  private String readClass(int index) throws IOException {
    index = readUnsignedShort(index);
    if (index == 0) {
      return null;
    }
    index = readUnsignedShort(items[index]);
    bin.readFrom(b, items[index]);
    return data.readUTF();
  }

  private int readUnsignedShort(int index) {
    byte[] b = this.b;
    return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
  }

  private static final int CHUNK = 2048;

  private void buffer(int amount) throws IOException {
    if (amount > b.length) {
      b = (byte[]) resizeArray(b, b.length * 2);
    }
    if (amount > bsize) {
      int rounded = (int) (CHUNK * Math.ceil((float) amount / CHUNK));
      bsize += read(in, b, bsize, rounded - bsize);
      if (amount > bsize) {
        throw new EOFException();
      }
    }
  }

  private static int read(InputStream in, byte[] b, int off, int len) throws IOException {
    int total = 0;
    while (total < len) {
      int result = in.read(b, off + total, len - total);
      if (result == -1) {
        break;
      }
      total += result;
    }
    return total;
  }

  private static Object resizeArray(Object array, int length) {
    if (Array.getLength(array) < length) {
      Object newArray = Array.newInstance(array.getClass().getComponentType(), length);
      System.arraycopy(array, 0, newArray, 0, Array.getLength(array));
      return newArray;
    } else {
      return array;
    }
  }

  private static class MyByteArrayInputStream extends ByteArrayInputStream {
    public MyByteArrayInputStream() {
      super(new byte[0]);
    }

    public void readFrom(byte[] buf, int pos) {
      this.buf = buf;
      this.pos = pos;
      count = buf.length;
    }
  }
}
