/* TSWorkspace.m created by tsengel on Mon 01-Sep-1997 */

#import "TSWorkspace.h"

#import <MiscFoundation/MiscFoundation.h>

#import "NSString+MiscPathComparing.h"
#import "NSTask+MiscExtensions.h"

static id		sharedTSWorkspace = nil;

@implementation TSWorkspace
/*"
This class is mainly a helper class which allows us to "bypass" some of the shortcomings of the regular NSWorkspace class. However..it is not a real subclass for various reasons...and a complete hack anyway.
"*/

+ (id)sharedWorkspace
{
    if( !sharedTSWorkspace )
    {
        sharedTSWorkspace = [[self class] new];
    }
    return sharedTSWorkspace;
}

- (id)init
{
    id	theCenter = [[NSWorkspace sharedWorkspace] notificationCenter];

    self = [super init];
    if( !self ) return nil;

    // So lets register for the interesting notifications.

    [theCenter addObserver:self
                  selector:@selector(externalAppLaunched:)
                      name:NSWorkspaceDidLaunchApplicationNotification
                    object:nil];

    [theCenter addObserver:self
                  selector:@selector(externalAppTerminated:)
                      name:NSWorkspaceDidTerminateApplicationNotification
                    object:nil];

    return self;
}

- (void)dealloc
{
    [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self];

    [runningApps release];
    [mountedDrives release];

    [super dealloc];
}

- (NSArray *)runningApplications
{
    if( !runningApps )
    {
        id		psData;
        id		outputString;
        id		outputLines;
        int		i;
        int		n;
        id		psInfoParts;
        id		aString;

        runningApps = [NSMutableArray new];

        // During startup we will fill it with all the "machLaunched" apps that we can find by checking the processes command
        // /bin/ps... however.. on NT this won't work... so let's not try it if the file does not exist.
        // This is quite ugly but with the limited functionality of the NSWorkspace class this is the easiest way
        // to get our hands on the list of runnign processes.

        psData = [NSTask outputOfCommand:@"/bin/ps -xwww"];
        outputString = [[NSString alloc] initWithData:psData encoding:NSASCIIStringEncoding];

        // NSLog( @"Found ps report: \n%@", outputString );

        // Ok..thius is really brutal hardcoded evil behavior...but hey.. it works.

        outputLines = [outputString componentsSeparatedByString:@"\n"];

        for( i=0; i<[outputLines count]; i++ )
        {
            psInfoParts = [[[outputLines objectAtIndex:i] stringByTrimmingSpaces] componentsSeparatedByString:@" "];
            if( [psInfoParts containsObject:@"-MachLaunch"] )
            {
                for( n=4; n<[psInfoParts count]; n++ )
                {
                    aString = [psInfoParts objectAtIndex:n];
                    if( [aString hasPrefix:@"/"] )
                    {
                        [runningApps addObject:[aString stringByDeletingLastPathComponent]];
                        break;
                    }
                }
            }
        }
        [outputString release];
    }
    return runningApps;
}

- (NSArray *)mountedDrives
{
    if( !mountedDrives ) mountedDrives = [NSMutableArray new];
    return 	mountedDrives;
}

- (void)externalAppLaunched:(NSNotification *)notification
{
    id		appPath = [[notification userInfo] objectForKey:@"NSApplicationName"];

    // This is ugly since we should somehow be able to "track" the PIDs of the running processes...welll...

    [(NSMutableArray *)[self runningApplications] addObject:appPath];

    // Sorting is disabled right now so that the Workspace really is the first...so we get teh apps in startup
    // time order.. at least somehow startuptime dependant.

    // [runningApps autorelease];
    // runningApps = [[runningApps sortedArrayUsingSelector:@selector(compareByLastPathComponent:)] mutableCopy];

   //  NSLog( @"Workspace started application: %@", appPath );

    [[NSNotificationCenter defaultCenter] postNotificationName:@"ProcessesListChanged" object:self];
}

- (void)externalAppTerminated:(NSNotification *)notification
{
    id		appPath = [[notification userInfo] objectForKey:@"NSApplicationName"];

    // NSLog( @"Workspace terminated application: %@", appPath );

    [(NSMutableArray *)[self runningApplications] removeObject:appPath];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"ProcessesListChanged" object:self];
}

@end
