package aQute.bnd.compatibility;

import java.io.*;

import aQute.bnd.osgi.*;
import aQute.bnd.osgi.Descriptors.TypeRef;

public class ParseSignatureBuilder {
	final Scope	root;

	public ParseSignatureBuilder(Scope root) {
		this.root = root;
	}

	public void add(Jar jar) throws Exception {
		for (Resource r : jar.getResources().values()) {
			InputStream in = r.openInputStream();
			try {
				parse(in);
			}
			finally {
				in.close();
			}
		}
	}

	public Scope getRoot() {
		return root;
	}

	public void parse(InputStream in) throws Exception {
		Analyzer analyzer = new Analyzer();
		Clazz clazz = new Clazz(analyzer, "", null);

		clazz.parseClassFile(in, new ClassDataCollector() {
			Scope	s;
			Scope	enclosing;
			Scope	declaring;

			@Override
			public void classBegin(int access, TypeRef name) {
				s = root.getScope(name.getBinary());
				s.access = Access.modifier(access);
				s.kind = Kind.CLASS;
			}

			@Override
			public void extendsClass(TypeRef name) {
				// s.setBase(new GenericType(name));
			}

			@Override
			public void implementsInterfaces(TypeRef names[]) {
				s.setParameterTypes(convert(names));
			}

			GenericType[] convert(TypeRef names[]) {
				GenericType tss[] = new GenericType[names.length];
				for (int i = 0; i < names.length; i++) {
					// tss[i] = new GenericType(names[i]);
				}
				return tss;
			}

			@Override
			public void method(Clazz.MethodDef defined) {
				String descriptor;
				Kind kind;
				if (defined.isConstructor()) {
					descriptor = ":" + defined.getDescriptor();
					kind = Kind.CONSTRUCTOR;
				} else {
					descriptor = defined.getName() + ":" + defined.getDescriptor();
					kind = Kind.METHOD;
				}
				Scope m = s.getScope(descriptor);
				m.access = Access.modifier(defined.getAccess());
				m.kind = kind;
				m.declaring = s;
				s.add(m);
			}

			@Override
			public void field(Clazz.FieldDef defined) {
				String descriptor = defined.getName() + ":" + defined.getDescriptor();
				Kind kind = Kind.FIELD;
				Scope m = s.getScope(descriptor);
				m.access = Access.modifier(defined.getAccess());
				m.kind = kind;
				m.declaring = s;
				s.add(m);
			}

			@Override
			public void classEnd() {
				if (enclosing != null)
					s.setEnclosing(enclosing);
				if (declaring != null)
					s.setDeclaring(declaring);
			}

			@Override
			public void enclosingMethod(TypeRef cName, String mName, String mDescriptor) {
				enclosing = root.getScope(cName.getBinary());
				if (mName != null) {
					enclosing = enclosing.getScope(Scope.methodIdentity(mName, mDescriptor));
				}
			}

			@Override
			public void innerClass(TypeRef innerClass, TypeRef outerClass, String innerName, int innerClassAccessFlags) {
				if (outerClass != null && innerClass != null && innerClass.getBinary().equals(s.name))
					declaring = root.getScope(outerClass.getBinary());
			}
		});

	}
}
