//
//  Runtime.m
//  CamelBones
//
//  Copyright (c) 2002 Sherm Pendley. All rights reserved.
//

#ifdef GNUSTEP
#import <objc/objc-api.h>
#else
#import <objc/objc-runtime.h>
#endif

#import "Runtime.h"
#import "PerlImports.h"

// Create Perl wrappers for all registered ObjC classes
void CBWrapRegisteredClasses(void) {
#ifdef GNUSTEP
	void *enum_state;
	Class thisClass;
	
	enum_state = NULL;
	while ((thisClass = objc_next_class(&enum_state))) {
		CBWrapObjectiveCClass(thisClass);
	}
#else
	int numClasses;
    Class *classes;
    int i;

    classes = NULL;
    numClasses = objc_getClassList(NULL, 0);
    if (numClasses > 0) {
        classes = malloc(sizeof(Class) * numClasses);
        objc_getClassList(classes, numClasses);
        for(i=0; i < numClasses; i++) {
            CBWrapObjectiveCClass(classes[i]);
        }
        free(classes);
    }
#endif
}

// Create a Perl wrapper for a single ObjC class
void CBWrapObjectiveCClass(Class aClass) {
    // Define a Perl context
    dTHX;

    // Create the @ClassName::ISA = qw(SuperClass);
    const char *className = aClass->name;
    int ISALen = strlen(className) + 6;
    char *ISAName = malloc(ISALen);
    const char *SuperName = NULL;
    AV *newIsaAV = NULL;
    SV *newParentSV = NULL;

    // Get the super class name; default to "NSObject" for root classes
    if (aClass->super_class != NULL) {
        SuperName = aClass->super_class->name;
    } else {
        SuperName = "NSObject";
    }

    // Build up the PackageName::ISA array name and create the array
    sprintf(ISAName, "%s::ISA", className);
    newIsaAV = get_av(ISAName, TRUE);

    // Clear any existing elements
    av_clear(newIsaAV);
            
    // Add the superclass element
    newParentSV = newSVpv(SuperName, 0);
    av_push(newIsaAV, newParentSV);

    // Free the mallocs!
    free(ISAName);
}
