/*
\\              Functions In Here Are For Class's and Objects
*/

        #include <Global/Main_Global.h>

BOOL Scan_Classes()
{
        /*
         directory and Fills There Name In The Class List.
         This Function Is Called Before MUI Is Running. It Scans The ClassModules
        */

        BPTR DirectoryLock;
        struct FileInfoBlock	*fib;
        struct Class		*New_Class;
        char			*Parse_Buffer;
        KPrintF("Classes.c : Scan_Classes()\n");    
       
        if( !(DirectoryLock = Lock( "PROGDIR:ClassModules/", ACCESS_READ ) ) )
        {
                Display( "Unable To Locate ClassModules Drawer." );
                return( FALSE );
        }
        if( !(fib = AllocDosObjectTags( DOS_FIB, TAG_DONE) ) )
        {
                Display( "Not Enoungh Memory For FIB!" );
                UnLock( DirectoryLock );
                return( FALSE );
        }
        Parse_Buffer = AllocPooled(Global->MemoryPool,1024);
        Examine( DirectoryLock, fib );
        ParsePatternNoCase( "#?.ext", Parse_Buffer, 1024 );
        while( ExNext( DirectoryLock, fib ) )
        {
          if(MatchPatternNoCase( Parse_Buffer, fib->fib_FileName ))
           {
            New_Class = AllocPooled( Global->MemoryPool, sizeof(struct Class));
            AddTail( (struct List *) &Global->ClassList, (struct Node *) New_Class ); 
            New_Class->ClassName = AllocPooled( Global->MemoryPool, 50);
            strncpy( New_Class->ClassName, fib->fib_FileName,strlen(fib->fib_FileName)-4);
           }
        }
        FreePooled(Global->MemoryPool,Parse_Buffer,1024);
        FreeDosObject( DOS_FIB, fib );
        UnLock( DirectoryLock );

        if( !FirstNode( &Global->ClassList ) )
        {
                Display( "Class Module Directory Is Empty?" );
                return( FALSE );
        }
        SortList( (struct List *) &Global->ClassList, sizeof( struct MinNode ) );
        return( TRUE );
}

struct Class * FindClass( UBYTE *classname )
{
        //      Attempt to find the named class

        struct Class *cl;
        KPrintF("Classes.c : FindClass( %s )\n",classname);   
        for( cl = FirstNode( &Global->ClassList ); cl; cl = NextNode( cl ) )
        {
                if( !strcmp( classname, cl->ClassName ) )
                        return( cl );
        }
        return( NULL );
}


BOOL Load_Class( struct Class *EM_Class )

{
        /* This Function Simply Loads A Required Class Into Memory And Sets Its Flags */

        char            *ClassFilePath;
        struct EMC_Data *Xfer;
        
        ASM ULONG (*Launch_Pad)( REG(d0) struct EMC_Data * );             // Function Pointer For Class
        KPrintF("Classes.c : Load_Class()\n");   
        if( !EM_Class ) return( NULL );  // In Case Of NULL Pointer.
        if( !EM_Class->UseCount )        // If Class Is Already Loaded?
        {
           Xfer 	 = AllocPooled(Global->MemoryPool,sizeof(struct EMC_Data));
           ClassFilePath = AllocPooled(Global->MemoryPool,255);
               
           sprintf( ClassFilePath, "PROGDIR:ClassModules/%s.ext", EM_Class->ClassName );
           if( !(EM_Class->SegList = LoadSeg( ClassFilePath ) ) )                
                        return( FALSE );
           EM_Class->Launcher = (((ULONG)EM_Class->SegList)<<2) + 4;// Code starts seglist + 4;               
           Init_EMC_Data( EM_Class->ClassName,Xfer,FALSE,FALSE,FALSE);
           Xfer->Command = EXTMOD_INIT;
           Launch_Pad = EM_Class->Launcher;
           EM_Class->Flags = Launch_Pad( Xfer );
                
           FreePooled(Global->MemoryPool,ClassFilePath,255);
           FreePooled(Global->MemoryPool,Xfer,sizeof(struct EMC_Data));
        }
        EM_Class->UseCount++;	//Class Is Now Being Used.					
        return( TRUE );
}

BOOL UnLoad_Class( struct Class *cl )
{	
	/* This Function Closes A Single Class */
	KPrintF("Classes.c : UnLoad_Class()\n");   
        if( cl->UseCount ) return( FALSE );      	//Class Is Not Loaded!
        if( cl->SegList ) UnLoadSeg( cl->SegList );
        cl->SegList = NULL;
        return( TRUE );
}

void Clear_Classes()
{
	/* This Function Calls CloseClass() On All The Classes. */
        struct Class *cl;
        KPrintF("Classes.c : Clear_Classes()\n");   
        for( cl = FirstNode( &Global->ClassList ); cl; cl = NextNode( cl ) )
        {
                cl->UseCount = 0;               // Allow Class to be closed.
                UnLoad_Class( cl );		// Close The Class.
        }
}

void Clear_Modules()
{
	/* This Function Calls CloseClass() On All The Classes. */
        struct  Module *Victim;
           KPrintF("Classes.c : Clear_Modules()\n");   
        for( Victim = FirstNode( &Global->ObjectList ); Victim; Victim = NextNode( Victim ) )
        {
        	Kill_Object(Victim);
                //FreePooled(Global->MemoryPool,Victim,sizeof(struct Module));
        }
}
void Set_Data( struct Module *o, struct EMC_Data *emd )
{
        //Set MUI Objects from Module......

        UBYTE tchar[2] = { 0, 0 };
        KPrintF("Classes.c : Set_Data()\n");   
        if( o->Width )
        {
                set( emd->widthcheck, MUIA_Selected, TRUE );
                set( emd->width, MUIA_String_Integer, o->Width );
        }
        if( o->Height )
        {
                set( emd->heightcheck, MUIA_Selected, TRUE );
                set( emd->height, MUIA_String_Integer, o->Height );
        }
        set( emd->weight,                       MUIA_Slider_Level, o->Weight );
        if( (o->Flags & CLASS_NEEDSNAME) && !o->Name )
        {
            //    sprintf( linebuffer, "%s_%ld", o->Class->ClassName, defaultobjnum++ );
            //    o->Name = copystr( linebuffer );
        }
        set( emd->name,                 MUIA_String_Contents, o->Name );
        set( emd->help,                 MUIA_String_Contents, o->ShortHelp );
        set( emd->frametitle,           MUIA_String_Contents, o->FrameTitle );
        set( emd->backcycle,            MUIA_Cycle_Active, o->Background );
        set( emd->framecycle,           MUIA_Cycle_Active, o->Frame_Type );
        set( emd->phantomhoriz,         MUIA_Selected, o->objflags & OBJ_FPHANTOM );
        set( emd->disabled,             MUIA_Selected, o->objflags & OBJ_DISABLED );
        set( emd->input,                MUIA_Selected, o->objflags & OBJ_INPUT );
        set( emd->exid,                 MUIA_Selected, o->objflags & OBJ_EXID );
        tchar[0] = o->ctrlchar;
        set( emd->ctrlchar,             MUIA_String_Contents, tchar );
}

void Get_Data( struct Module *o, struct EMC_Data *emd )
{
        KPrintF("Classes.c : Get_Data()\n");   
        //Get Data From MUI Objects.......

        //FreePooled( Global->MemoryPool,o->Name, );
        //FreePooled( Global->MemoryPool,o->ShortHelp, );
        //FreePooled( Global->MemoryPool,o->FrameTitle, );
        
        o->Width                        = Get( emd->widthcheck, MUIA_Selected )
                                        ? Get( emd->width, MUIA_String_Integer )
                                        : 0;
        o->Height                       = Get( emd->heightcheck, MUIA_Selected )
                                        ? Get( emd->height, MUIA_String_Integer )
                                        : 0;
        o->Weight                       = Get( emd->weight, MUIA_Slider_Level );
        o->Name                         = copystr( (UBYTE *) Get( emd->name, MUIA_String_Contents ) );
        o->ShortHelp                    = copystr( (UBYTE *) Get( emd->help, MUIA_String_Contents ) );
        o->FrameTitle                   = copystr( (UBYTE *) Get( emd->frametitle, MUIA_String_Contents ) );
        o->Background                   = Get( emd->backcycle, MUIA_Cycle_Active );
        o->Frame_Type                   = Get( emd->framecycle, MUIA_Cycle_Active );
        o->objflags                     = Get( emd->phantomhoriz, MUIA_Selected )? OBJ_FPHANTOM:0 |
                                          Get( emd->disabled, MUIA_Selected )    ? OBJ_DISABLED:0 |
                                          Get( emd->input, MUIA_Selected )       ? OBJ_INPUT:0 |
                                          Get( emd->exid, MUIA_Selected )        ? OBJ_EXID:0;
                                                  
}

/*  The artist formally known as New_Object */

void Start_GUI( void )
{
	#define DropGroupObject NewObject(Global->SelectClass->mcc_Class,NULL

        ASM ULONG (*Launch_Pad)( REG(d0) struct EMC_Data * );
        
        struct EMC_Data *Xfer;
        struct Class    *Window_Class;
        struct Class	*Group_Class;
        
        struct Module   *Window_Module;
        struct Module   *Group_Module;
        KPrintF("Classes.c : Start_GUI()\n");   
        
        Window_Class = FindClass("Window");
        Load_Class(Window_Class);
        Group_Class  = FindClass("Group");
        Load_Class(Group_Class);
        if(!Group_Class || !Window_Class)
            Display("Trouble With Window And Group Class!");
            
               Window_Module = AllocPooled(Global->MemoryPool,sizeof(struct Module));
                Group_Module = AllocPooled(Global->MemoryPool,sizeof(struct Module));
               printf("Created Group  %p\n",Group_Module  );
               printf("Created Window %p\n",Window_Module );
               
        Group_Module->MUI_Object	= DropGroupObject,GroupFrame,
                                            MUIA_Group_Child,RectangleObject,End,
                                          End;
	                             
        Window_Module->Parent		= NULL;
        Window_Module->Class		= Window_Class;
        Window_Module->Flags		= Window_Class->Flags;
        Window_Module->MUI_Object	= WindowObject,
                                               MUIA_Window_RootObject,Group_Module->MUI_Object,
                                               MUIA_Window_ID,"TEST",
                                               MUIA_Window_NeedsMouseObject,TRUE,
                                          End; 
        Global->TestWindow 		= Window_Module->MUI_Object;
        Group_Module->Class		= Group_Class;
        Group_Module->Parent		= Window_Module;
        Group_Module->Flags		= Group_Class->Flags;
        
	
     
        NewList( (struct List *) &Window_Module->Children );
        NewList( (struct List *) &Group_Module->Children );
        AddTail( (struct List *) &Window_Module->Children, (struct Node *) Group_Module );
        AddTail( (struct List *) &Global->ObjectList, (struct Node *) Window_Module ); 
        AddTail( (struct List *) &Global->ObjectList, (struct Node *) Group_Module );
        DoMethod(App->App,OM_ADDMEMBER,Window_Module->MUI_Object);
       
}

struct Module * NewObject_FromClass( struct Class *Super_Class, BOOL needed ,BOOL Gui)
{

	 /* Open Configuration Window And Create A New Object Based on Results */
	 
        ASM ULONG (*Launch_Pad)( REG(d0) struct EMC_Data * );
        
        struct EMC_Data *Xfer;
        struct Module   *New_Object;
        KPrintF("Classes.c : NewObject_FromClass()\n");   
        if(!Load_Class( Super_Class)) 
                return( NULL );
        
        if(!(New_Object = AllocPooled(Global->MemoryPool,sizeof(struct Module)   )))
                return( NULL );
                
        if(!(Xfer       = AllocPooled(Global->MemoryPool,sizeof(struct EMC_Data) )))
                return( NULL );
                
        Init_EMC_Data( Super_Class->ClassName,Xfer,FALSE,FALSE,FALSE);
        
        New_Object->Class  = Super_Class;
        New_Object->Flags  = Super_Class->Flags;
        New_Object->Weight = 100;
    
        NewList( (struct List *) &New_Object->Children );
        Launch_Pad = Super_Class->Launcher;
        
        Xfer->This_Module = New_Object;
        Xfer->Command     = EXTMOD_EDIT;
        set( App->App, MUIA_Application_Sleep, TRUE );
        if( !Init_EMC_Data( Super_Class->ClassName, Xfer,TRUE, (BOOL) (New_Object->Flags & CLASS_GLOBSET), needed ) )
        {
                FreePooled(Global->MemoryPool ,New_Object,sizeof(struct Module) );
                New_Object = NULL;             
        }
        else 
        {
                Launch_Pad(Xfer);
                Xfer->Command= EXTMOD_INPT;
                Launch_Pad(Xfer);
                Get_Data(New_Object,Xfer);
                DisposeMUIEditWindow(Xfer); 
               
                /* Some Kind Of Object Checking Code Needs To Be Written */
        }

        set( App->App, MUIA_Application_Sleep, FALSE );
        FreePooled(Global->MemoryPool, Xfer, sizeof(struct EMC_Data));
        
        return( New_Object );
}



Object * Make_MUIObject( struct Module *Current_Module)
{
	/* Function Makes Current Object MUI Ready and
	   Returns an MUI Pointer.
	 */
        struct Class    *Class_Used;
        struct EMC_Data *Xfer;

        ASM ULONG (*Launch_Pad)( REG(d0) struct EMC_Data *);
         KPrintF("Classes.c : Make_MUIObject()\n");   
        Class_Used = Current_Module->Class;        
        if(!Class_Used) return( NULL);
        Xfer = AllocPooled(Global->MemoryPool,sizeof(struct EMC_Data));
        Init_EMC_Data( Class_Used->ClassName,Xfer,FALSE,FALSE,FALSE );    
        Xfer->Command     = EXTMOD_MAKE;
        Xfer->This_Module = Current_Module;
        Launch_Pad        = Class_Used->Launcher;
        Current_Module->MUI_Object= Launch_Pad(Xfer);
        FreePooled(Global->MemoryPool,Xfer,sizeof(struct EMC_Data));
        return((Object *)Current_Module->MUI_Object);
}

void Describe( struct Module *Current_Module )
{
        // Ask module for description of object

	struct EMC_Data *Xfer;
        ASM ULONG (*Launch_Pad)( REG(d0) struct EMC_Data * );
         KPrintF("Classes.c : Describe()\n");   
	Xfer = AllocPooled(Global->MemoryPool,sizeof(struct EMC_Data));
	
        Xfer->This_Module = Current_Module;
        Xfer->Command     = EXTMOD_DESC;
        Launch_Pad = Current_Module->Class->Launcher;
        Init_EMC_Data( Current_Module->Class->ClassName,Xfer,FALSE,FALSE,FALSE );
        if( Launch_Pad( Xfer ) )
          FreePooled(Global->MemoryPool,Xfer ,sizeof(struct EMC_Data));
         set( App->Objects_Status, MUIA_Floattext_Text, Current_Module->Description );
}



void Kill_Object( struct Module *Victim_Module )
{
        struct Module   *Spawn;
        struct EMC_Data *Xfer;
        ASM ULONG (*Launch_Pad)( REG(d0) struct EMC_Data * );
        
         KPrintF("Classes.c : Kill_Object()\n");   
        while( Spawn = FirstNode( &Victim_Module->Children ) )
                Kill_Object( Spawn );
        printf("Killing %s %p\n",Victim_Module->Class->ClassName,Victim_Module);
	Xfer = AllocPooled(Global->MemoryPool,sizeof(struct EMC_Data));
        Remove( (struct Node *) Victim_Module );
        Xfer->This_Module = Victim_Module;
        Xfer->Command     = EXTMOD_KILL;
        Launch_Pad = Victim_Module->Class->Launcher;
        Init_EMC_Data( Victim_Module->Class->ClassName,Xfer,FALSE,FALSE,FALSE);
        Launch_Pad( Xfer);
        FreePooled( Global->MemoryPool,Victim_Module,sizeof(struct Module));
        FreePooled( Global->MemoryPool,Xfer,sizeof(struct EMC_Data));
        
}

struct Module *Edit_Object( struct Module *EM_Object )
{
        struct EMC_Data *Xfer;
        ASM ULONG (*Launch_Pad)( REG(d0) struct EMC_Data * );
         KPrintF("Classes.c : Edit_Object()\n");   
        Xfer = AllocPooled(Global->MemoryPool,sizeof(struct EMC_Data));
        Xfer->This_Module = EM_Object;
        Xfer->Command     = EXTMOD_EDIT;
        Launch_Pad = EM_Object->Class->Launcher;
        set( App->App, MUIA_Application_Sleep, TRUE );        
        if(Init_EMC_Data( EM_Object->Class->ClassName, Xfer,TRUE, (BOOL) (EM_Object->Flags & CLASS_GLOBSET), FALSE ) )
        {
            
            Set_Data( EM_Object, Xfer );  
            Launch_Pad(Xfer);
            Xfer->Command = EXTMOD_INPT;
            Launch_Pad(Xfer);
            Get_Data(EM_Object,Xfer);
            DisposeMUIEditWindow(Xfer); 
            Launch_Pad( Xfer );
            FreePooled(Global->MemoryPool,Xfer,sizeof(struct EMC_Data));
        }
        set( App->App, MUIA_Application_Sleep, FALSE );
        return( EM_Object );
}

