// Copyright 1997-2002 Omni Development, Inc.  All rights reserved.
//
// This software may only be used and reproduced according to the
// terms in the file OmniSourceLicense.html, which should be
// distributed with this project and can also be found at
// http://www.omnigroup.com/DeveloperResources/OmniSourceLicense.html.

#import <Foundation/Foundation.h>
#import <OmniBase/OmniBase.h>
#import <OmniFoundation/OmniFoundation.h>
#import <OWF/OWF.h>

#import <Foundation/NSDate.h>

#import "OWFWebPounder.h"
#import "OWAnchorsProcessor.h"

RCS_ID("$Header: /Network/Source/CVS/OmniGroup/Frameworks/OWF/Tests/OWFWebPounder/OWFWebPounder.m,v 1.7 2002/03/09 01:53:53 kc Exp $")

#define ACTIVE_COUNT (30)

//static OFMessageQueue  *messageQueue;
static NSConditionLock *startMoreLock;
static unsigned int     activeCount = 0;

int main(int argc, char *argv[])
{
    NSString *urlString;
    NSAutoreleasePool *pool;
    
    if (argc != 2) {
        fprintf(stderr, "usage: %s url\n", argv[0]);
        exit(1);
    }

    pool = [[NSAutoreleasePool alloc] init];
    [OBPostLoader processClasses];
    [[OFController sharedController] didInitialize];
    [[OFController sharedController] startedRunning];
    
    urlString = [[NSString alloc] initWithCString: argv[1]];
    
//    messageQueue = [[OFMessageQueue alloc] init];
//    [messageQueue startBackgroundProcessors: 4];
    
    startMoreLock = [[NSConditionLock alloc] initWithCondition: YES];
    
//    [OFMessageQueue setDebug: YES];
//    [OWHTTPSession setDebug: YES];
//    [OWPipeline setDebug: YES];

    [NSThread detachNewThreadSelector:@selector(logStatus) toTarget:[OWFWebPounder class] withObject: nil];
    [NSThread detachNewThreadSelector:@selector(queueThread:) toTarget:[OWFWebPounder class] withObject: urlString];
    [pool release];
    
    [[NSRunLoop currentRunLoop] runUntilDate: [NSDate distantFuture]];
    
    return 0;
}

static unsigned int processorsStarted = 0;

@implementation OWFWebPounder

+ (void) queueThread: (NSString *) urlString;
{
    while (YES) {
        NSAutoreleasePool *pool;

        pool = [[NSAutoreleasePool alloc] init];
        [startMoreLock lockWhenCondition: YES];
        activeCount++;
        [startMoreLock unlockWithCondition: activeCount < ACTIVE_COUNT];
        [OWFWebPounder findAnchors: urlString];
//        [messageQueue queueSelector: @selector(findAnchors:) forObject: [OWFWebPounder class] withObject: urlString];
        [pool release];
    }
}

+ (void) logStatus;
{
    while (1) {
        NSAutoreleasePool *pool;
        pool = [[NSAutoreleasePool alloc] init];
        NSLog(@"Processors started = %d", processorsStarted);
        sleep(5);
        [pool release];
    }
}

+ (void) findAnchors: (NSString *) urlString;
{
    OWFWebPounder *pounder;

    processorsStarted++;
    pounder = [[self alloc] init];
    [pounder findAnchors: urlString];
    [pounder release];
}

- init;
{
    [super init];
    lock = [[NSConditionLock alloc] initWithCondition: NO];
    return self;
}

- (void) dealloc;
{
#warning WJS: This can't be here any more, because we will never get dealloc'd
    [OWPipeline invalidatePipelinesForTarget:self];
    [lock release];
    [super dealloc];
}

- (void) findAnchors: (NSString *) urlString;
{
    OWURL                *url;
    OWAddress            *address;

    // Work around race condition -- we'll get released in -pipelineTreeDidDeactivate:
    [self retain];

    url = [OWURL urlFromString: urlString];
    address = [OWAddress addressWithURL: url];
    [OWWebPipeline startPipelineWithContent:address target:self];
    [lock lockWhenCondition:YES];
    [lock unlock];
}

//
// OWTarget
//

- (OWContentType *)targetContentType;
{
//    return [OWSourceProcessor sourceContentType];
    return [OWContentType contentTypeForString:@"text/html"];
    return [OWAnchorsProcessor anchorsContentType];
}

- (OWTargetContentDisposition)pipeline:(OWPipeline *)aPipeline hasContent:(id <OWContent
>)someContent;
{
    OWObjectStream       *stream;
    OWSGMLTag            *anchor;
    OWObjectStreamCursor *cursor;

//    NSLog(@"content = %@", someContent);
//    stream = (OWObjectStream *)someContent;
//    cursor = [[[OWObjectStreamCursor alloc] initForObjectStream: stream] autorelease];

//    while ((anchor = [cursor readObject])) {
//       NSLog(@"Anchor = %@", anchor);
//    }

    [startMoreLock lock];
    activeCount--;
    [startMoreLock unlockWithCondition: activeCount < ACTIVE_COUNT];

    [lock lock];
    [lock unlockWithCondition: YES];
    
    return OWTargetContentDisposition_ContentAccepted;
}

- (OWContentInfo *)parentContentInfo;
{
    return [OWContentInfo headerContentInfoWithName: @"Anchor"];
}

- (NSString *)targetTypeFormatString;
{
    return @"Anchor";
}

//
// OWOptionalTarget
//

- (void)pipelineTreeDidDeactivate:(OWPipeline *)aPipeline;
{
    // Work around race condition... this is the last method that the pipeline can potentially call on us
    [self release];
}

@end



#if 0

#import <mach/mach.h>
#import <mach/bootstrap.h>
#import <mach/mach_error.h>

static void OFTieToSingleProcessor()
{
    kern_return_t krc;
    processor_array_t processors;
    processor_set_name_array_t processorSets;
    mach_msg_type_number_t processorCount, processorSetCount;
    host_priv_t host_priv;
    mach_port_t dummy_port_1, dummy_port_2, dummy_port_3, dummy_port_4;
    processor_set_t processorSet;
    processor_set_name_t processorSetName;
    
    host_priv = PORT_NULL;
    
    krc = bootstrap_ports(mach_task_self(), /* BIG HACK */
                          &host_priv,
                          &dummy_port_1, &dummy_port_2,
                          &dummy_port_3, &dummy_port_4);
    if (krc != KERN_SUCCESS) {
        fprintf(stderr, "bootstrap_ports: %s\n", mach_error_string(krc));
        return;
    }

    krc = host_processors(host_priv, &processors, &processorCount);
    if (krc != KERN_SUCCESS) {
        fprintf(stderr, "host_processors: %s\n", mach_error_string(krc));
        return;
    }
    fprintf(stderr, "Processor count = %d\n", processorCount);

    krc = host_processor_sets(host_priv, &processorSets, &processorSetCount);
    if (krc != KERN_SUCCESS) {
        fprintf(stderr, "host_processor_sets: %s\n", mach_error_string(krc));
        return;
    }
    fprintf(stderr, "Processor Set count = %d\n", processorSetCount);
    
    krc = processor_set_create(host_priv, &processorSet, &processorSetName);
    if (krc != KERN_SUCCESS) {
        fprintf(stderr, "processor_set_create: %s\n", mach_error_string(krc));
        return;
    }
}
#endif


#if 0
static void testLocks()
{
    NSConditionLock *lock;
    
    lock = [[NSConditionLock alloc] initWithCondition: 0];
    NSLog(@"Test should wait 5 seconds");
    if ([lock lockWhenCondition: 1 beforeDate: [NSDate dateWithTimeIntervalSinceNow: 5]])
        NSLog(@"Test locked -- shouldn't have");
    else
        NSLog(@"Test didn't lock (correct)");
    exit(0);
}
#endif

