package dyvilx.tools.compiler.ast.classes.metadata;

import dyvil.reflect.Modifiers;
import dyvilx.tools.compiler.ast.classes.IClass;
import dyvilx.tools.compiler.ast.constructor.IConstructor;
import dyvilx.tools.compiler.ast.context.IContext;
import dyvilx.tools.compiler.ast.field.IField;
import dyvilx.tools.compiler.ast.header.ClassCompilable;
import dyvilx.tools.compiler.ast.header.IClassCompilableList;
import dyvilx.tools.compiler.ast.header.ICompilableList;
import dyvilx.tools.compiler.ast.member.MemberKind;
import dyvilx.tools.compiler.ast.method.IMethod;
import dyvilx.tools.compiler.backend.classes.ClassWriter;
import dyvilx.tools.compiler.backend.exception.BytecodeException;
import dyvilx.tools.compiler.backend.method.MethodWriter;
import dyvilx.tools.compiler.phase.Resolvable;
import dyvilx.tools.parsing.marker.MarkerList;

import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
import java.util.Set;

public interface IClassMetadata extends ClassCompilable, Resolvable
{
	// =============== Static Methods ===============

	static IClassMetadata getClassMetadata(IClass forClass, long modifiers)
	{
		if ((modifiers & Modifiers.ANNOTATION) != 0)
		{
			return new AnnotationMetadata(forClass);
		}
		if ((modifiers & Modifiers.TRAIT) != 0)
		{
			return new TraitMetadata(forClass);
		}
		if ((modifiers & Modifiers.INTERFACE) != 0)
		{
			return new InterfaceMetadata(forClass);
		}
		if ((modifiers & Modifiers.ENUM) != 0)
		{
			return new EnumClassMetadata(forClass);
		}
		if ((modifiers & Modifiers.OBJECT) != 0)
		{
			return new ObjectClassMetadata(forClass);
		}
		if ((modifiers & Modifiers.EXTENSION) != 0)
		{
			return new ExtensionMetadata(forClass);
		}
		// All modifiers above are single-bit flags
		if ((modifiers & Modifiers.CASE_CLASS) != 0)
		{
			return new CaseClassMetadata(forClass);
		}
		return new ClassMetadata(forClass);
	}

	// =============== Methods ===============

	MemberKind getKind();

	default IField getInstanceField()
	{
		return null;
	}

	default void setInstanceField(IField field)
	{
	}

	default IConstructor getConstructor()
	{
		return null;
	}

	default IMethod getFunctionalMethod()
	{
		return null;
	}

	default void setFunctionalMethod(IMethod method)
	{
	}

	// Annotations

	default RetentionPolicy getRetention()
	{
		return null;
	}

	default boolean isTarget(ElementType target)
	{
		return false;
	}

	default Set<ElementType> getTargets()
	{
		return null;
	}

	// Resolve

	@Override
	default void resolveTypes(MarkerList markers, IContext context)
	{
		throw new UnsupportedOperationException();
	}

	default void resolveTypesAfterAttributes(MarkerList markers, IContext context)
	{
	}

	/**
	 * Called before the class body goes through RESOLVE_TYPES. Super-types and -interfaces and type parameters have
	 * already been resolved.
	 */
	default void resolveTypesBeforeBody(MarkerList markers, IContext context)
	{
	}

	/**
	 * Called after the class body went through RESOLVE_TYPES.<p/> Checks which synthetic members have to be generated
	 */
	default void resolveTypesAfterBody(MarkerList markers, IContext context)
	{
	}

	/**
	 * Generates the signatures of the synthetic members. Concrete implementations should be added in {@link
	 * #resolve(MarkerList, IContext)}.
	 */
	default void resolveTypesGenerate(MarkerList markers, IContext context)
	{
	}

	@Override
	default void resolve(MarkerList markers, IContext context)
	{
	}

	@Override
	default void checkTypes(MarkerList markers, IContext context)
	{
	}

	@Override
	default void check(MarkerList markers, IContext context)
	{
	}

	@Override
	default void foldConstants()
	{
	}

	@Override
	default void cleanup(ICompilableList compilableList, IClassCompilableList classCompilableList)
	{
	}

	default void writePost(ClassWriter writer)
	{
	}

	default void writeStaticInitPost(MethodWriter writer) throws BytecodeException
	{
	}

	default void writeClassInitPost(MethodWriter writer) throws BytecodeException
	{
	}
}

@@ -1921,22 +1921,25 @@
 ======= 
-Method
+Propertie
 s ======
@@ -1954,29 +1954,285 @@
 =%0A%0A%09
-MemberKind getKind();
+// --------------- Kind ---------------%0A%0A%09MemberKind getKind();%0A%0A%09// --------------- Default Constructor (regular and case classes) ---------------%0A%0A%09default IConstructor getConstructor()%0A%09%7B%0A%09%09return null;%0A%09%7D%0A%0A%09// --------------- Instance Field (object classes) ---------------
 %0A%0A%09d
@@ -2343,66 +2343,73 @@
 %7D%0A%0A%09
-default IConstructor getConstructor()%0A%09%7B%0A%09%09return null;%0A%09%7D
+// --------------- Functional Method (interfaces) ---------------
 %0A%0A%09d
@@ -2532,19 +2532,74 @@
 %09// 
-Annotations
+--------------- Retention and Target (annotations) ---------------
 %0A%0A%09d
@@ -2796,15 +2796,102 @@
 %09// 
-Resolve
+=============== Methods ===============%0A%0A%09// --------------- Resolution Phases ---------------
 %0A%0A%09@
@@ -3846,32 +3846,87 @@
 context)%0A%09%7B%0A%09%7D%0A%0A
+%09// --------------- Diagnostic Phases ---------------%0A%0A
 %09@Override%0A%09defa
@@ -4058,32 +4058,92 @@
 context)%0A%09%7B%0A%09%7D%0A%0A
+%09// --------------- Pre-Compilation Phases ---------------%0A%0A
 %09@Override%0A%09defa
@@ -4280,32 +4280,81 @@
 bleList)%0A%09%7B%0A%09%7D%0A%0A
+%09// --------------- Compilation ---------------%0A%0A
 %09default void wr

Clean up IClassMetadata