/*
    -----------------------------------------------------------------------------------------------
    File Name:		InspectorWindow.m
    Project:		Parakeet
    Author:		Greg Howell (with some help from Apple sample code)
    Revision Date:	22/08/2003 (0.2)
    
    Description:	InspectorWindow object implementation.
    -----------------------------------------------------------------------------------------------
*/

#import <Cocoa/Cocoa.h>
#import <Carbon/Carbon.h>
#import "AppShell.h"
#import "InspectorWindow.h"
#import "Parakeet.h"

@implementation InspectorWindow
/*
    -----------------------------------------------------------------------------------------------
    awakeFromNib
    -----------------------------------------------------------------------------------------------
*/
- (void)awakeFromNib
{
    // We're using Cocoa's mouseMoved: message to trigger updating
    //[self setAcceptsMouseMovedEvents:true];
}
/*
    -----------------------------------------------------------------------------------------------
    setCurrentAppString
    -----------------------------------------------------------------------------------------------
*/
- (void)setCurrentAppString:(NSMutableString *)currentApp
{
    [_currentApp setString:currentApp];
    [_currentApp display];
}
/*
    -----------------------------------------------------------------------------------------------
    setStartStopState
    -----------------------------------------------------------------------------------------------
*/
- (void)setStartStopState:(BOOL)onoff
{
    // set the global boolAudibleState to onoff, the variable
    // passed to the method
    boolAudibleState = onoff;
}
/*
    -----------------------------------------------------------------------------------------------
    getStartStopState
    -----------------------------------------------------------------------------------------------
*/
- (BOOL)getStartStopState
{
    return boolAudibleState;
}

/*
    -----------------------------------------------------------------------------------------------
    mouseMoved
    -----------------------------------------------------------------------------------------------
*/
- (void)mouseMoved:(NSEvent *)theEvent
{
    // Tell AppShell that the mouse moved
    // mouseMoved is used to trigger updating
    [AppShell updateCurrentUIElement];
}
/*
    -----------------------------------------------------------------------------------------------
    displayInfoForUIElement
    -----------------------------------------------------------------------------------------------
*/
- (void)displayInfoForUIElement:(AXUIElementRef)uiElement
{
    NSString *temp = [[NSString alloc] initWithString:[self stringDescriptionOfUIElement:uiElement]];
    
    [_consoleView setString:temp];
    [_consoleView display];
    [AppShell processAXString:(NSMutableString *)temp];
}
/*
    -----------------------------------------------------------------------------------------------
    lineageOfUIElement
    -----------------------------------------------------------------------------------------------
*/
- (NSArray *)lineageOfUIElement:(AXUIElementRef)element{
    NSArray *lineage = [NSArray array];
    NSString *elementDescr = [AppShell descriptionOfValue:element beingVerbose:NO];
    AXUIElementRef parent = (AXUIElementRef)[AppShell valueOfExistingAttribute:kAXParentAttribute ofUIElement:element];

    if (parent != NULL) {
        lineage = [self lineageOfUIElement:parent];
    }
    return [lineage arrayByAddingObject:elementDescr];
}
/*
    -----------------------------------------------------------------------------------------------
    lineageDescriptionOfUIElement
    -----------------------------------------------------------------------------------------------
*/
- (NSString *)lineageDescriptionOfUIElement:(AXUIElementRef)element {
    NSMutableString *result = [NSMutableString string];
    NSMutableString *indent = [NSMutableString string];
    NSArray *lineage = [self lineageOfUIElement:element];
    NSString *ancestor;
    NSEnumerator *e = [lineage objectEnumerator];
    while (ancestor = [e nextObject]) {
        [result appendFormat:@"%@%@\n", indent, ancestor];
        [indent appendString:@" "];
    }
    return result;
}
/*
    -----------------------------------------------------------------------------------------------
    stringDescriptionOfUIElement
    -----------------------------------------------------------------------------------------------
*/
- (NSString *)stringDescriptionOfUIElement:(AXUIElementRef)inElement
{
    NSMutableString * theDescriptionStr = [[NSMutableString new] autorelease];
    NSArray * theNames;
    CFIndex nameIndex;
    CFIndex numOfNames;

    [theDescriptionStr appendFormat:@"%@", [self lineageDescriptionOfUIElement:inElement]];
    
    //
    // Display attributes
    //
    AXUIElementCopyAttributeNames( inElement, (CFArrayRef *)&theNames );
    if (theNames) {
    
        numOfNames = [theNames count];
        
        if (numOfNames)
            [theDescriptionStr appendString:@"\nAttributes:\n"];

        for( nameIndex = 0; nameIndex < numOfNames; nameIndex++ ) {
            
            NSString * theName = NULL;
            id theValue = NULL;
            Boolean theSettableFlag = false;
            
            // Grab name
            theName = [theNames objectAtIndex:nameIndex];
                
            // Grab settable field
          	AXUIElementIsAttributeSettable( inElement, (CFStringRef)theName, &theSettableFlag );
            
            // Add string        
            [theDescriptionStr appendFormat:@"   %@%@:  Ò%@Ó\n", theName, (theSettableFlag?@" (W)":@""), [AppShell descriptionForUIElement:inElement attribute:theName beingVerbose:false]];
        
            [theValue release];
        }
    
        [theNames release];
    }
    
    //
    // Display actions
    //
       	AXUIElementCopyActionNames( inElement, (CFArrayRef *)&theNames );
    if (theNames) {
    
        numOfNames = [theNames count];
        
        if (numOfNames)
            [theDescriptionStr appendString:@"\nActions:\n"];

        for( nameIndex = 0; nameIndex < numOfNames; nameIndex++ ) {
            
            NSString * theName = NULL;
            NSString * theDesc = NULL;
            
            // Grab name
            theName = [theNames objectAtIndex:nameIndex];
            
            // Grab description
        	AXUIElementCopyActionDescription( inElement, (CFStringRef)theName, (CFStringRef *)&theDesc );
            
            // Add string        
            [theDescriptionStr appendFormat:@"   %@ - %@\n", theName, theDesc];
            
            [theDesc release];
        }
    
        [theNames release];
    }
    
    return theDescriptionStr;
}
/*
    -----------------------------------------------------------------------------------------------
    stringDescriptionOfCFArray
    -----------------------------------------------------------------------------------------------
*/
- (NSString *)stringDescriptionOfCFArray:(NSArray *)inArray
{

    NSMutableString * theDescriptionStr = [[NSMutableString new] autorelease];
    CFIndex theIndex;
    CFIndex numOfElements = [inArray count];

    [theDescriptionStr appendFormat:@"{"];
        
    for( theIndex = 0; theIndex < numOfElements; theIndex++ ) {
    
        id theObject = [inArray objectAtIndex:theIndex];
    
    	if (CFGetTypeID(theObject) == CFDictionaryGetTypeID()) {
    
            if (theIndex == 0)
                [theDescriptionStr appendFormat:@"(<UI Element: %d>)", theObject];
            else
                [theDescriptionStr appendFormat:@", (<UI Element: %d>)", theObject];
        }
        else {
            if (theIndex == 0)
                [theDescriptionStr appendFormat:@"%@", [inArray objectAtIndex:theIndex]];
            else
                [theDescriptionStr appendFormat:@", %@", [inArray objectAtIndex:theIndex]];
        }
    }
    
    [theDescriptionStr appendFormat:@"}"];
    
    return theDescriptionStr;
}
/*
    -----------------------------------------------------------------------------------------------
    close
    -----------------------------------------------------------------------------------------------
*/
- (void)close
{
    [super close];
    [NSApp terminate:NULL];
}
/*
    -----------------------------------------------------------------------------------------------
    stopButton
    -----------------------------------------------------------------------------------------------
*/
- (IBAction)stopButtonPressed:(id)sender
{
    [self setStartStopState:FALSE];
    if(DEBUG_PARAKEET){
        printf("InspectorWindow:stopButtonPressed (STOP)\n");
    }
}
/*
    -----------------------------------------------------------------------------------------------
    startButton
    -----------------------------------------------------------------------------------------------
*/
- (IBAction)startButtonPressed:(id)sender
{
    [self setStartStopState:TRUE];
    //[StartButton setEnabled:true];
    if(DEBUG_PARAKEET){
        printf("InspectorWindow:startButtonPressed (START)\n");
    }
}
@end
