//
//  BackgroundHelper.m
//  CyTV Client
//
//  Created by Andreas Junghans on Wed Oct 22 2003.
//  Copyright (c) 2003-2004 Andreas Junghans. All rights reserved.
//

#import "BackgroundHelper.h"

@implementation BackgroundHelper


/**
 * Forms an NSConnection from the background helper side.
 */

+ (void) connectWithParams: (NSArray*) paramsArray {
    NSAutoreleasePool* pool;
    NSConnection* serverConnection;
    BackgroundHelper* serverObject;
    
    // make sure we have an autorelease pool
    pool = [[NSAutoreleasePool alloc] init];

    // create a connection to the main thread
    serverConnection = [NSConnection
                        connectionWithReceivePort: [paramsArray
                                                    objectAtIndex: 0]
                        sendPort: [paramsArray objectAtIndex: 1]];
    
    // create an instance of ourselves and tell the
    // main thread about it
    serverObject = [[self alloc] init];
    serverObject->_urlFetcher = [[URLFetcher alloc] init];
    serverObject->_baseURL = [[[paramsArray objectAtIndex: 2] retain] autorelease];
    serverObject->_clientId = [[[paramsArray objectAtIndex: 3] retain] autorelease];
    serverObject->_cacheURL = [[[paramsArray objectAtIndex: 4] retain] autorelease];
    serverObject->_applicationController = (id <ApplicationControllerProtocol>) [[[serverConnection rootProxy] retain] autorelease];
    [serverObject->_applicationController setServer: serverObject];
    [serverObject release];
    
    // enter the run loop
    [[NSRunLoop currentRunLoop] run];
    [pool release];
}


/**
 * Start collecting information about EyeTV streams.
 */

- (void) startInfoCollector {
    _collectStreamInfo = TRUE;
    if (_infoCollectorTimer == nil) {
        _infoCollectorTimer = [NSTimer scheduledTimerWithTimeInterval: 2.0
                                       target: self
                                       selector: @selector(getStreamInfo:)
                                       userInfo: nil
                                       repeats: YES];
    }
}


/**
 * Stop collecting information about EyeTV streams.
 */

- (void) stopInfoCollector {
    /*if (_infoCollectorTimer != nil) {
        [_infoCollectorTimer invalidate];   // releases the timer
        _infoCollectorTimer = nil;
    }*/
    _collectStreamInfo = FALSE;
}


/**
 * Start scanning channels.
 */

- (void) startChannelScanner {
    if (_channelScannerTimer == nil) {
        _channelScannerTimer = [NSTimer scheduledTimerWithTimeInterval: 5.0
                                        target: self
                                        selector: @selector(nextChannel:)
                                        userInfo: nil
                                        repeats: YES];
    }
}


/**
 * Stop scanning channels.
 */

- (void) stopChannelScanner {
    if (_channelScannerTimer != nil) {
        [_channelScannerTimer invalidate];  // releases the timer
        _channelScannerTimer = nil;
    }
}


/**
 * Get information about CyTV streams.
 */

- (void) getStreamInfo: (NSTimer*) timer {
    NSString* cacheStateString = [_urlFetcher fetchURL:[_cacheURL stringByAppendingString:@"status"]];
    //printf("Cache state: %s\n", [cacheStateString cString]);
    double cacheState = 0.0;
    NSRange range = [cacheStateString rangeOfString:@"fill state: "];
    if (range.location != NSNotFound) {
        int index = [cacheStateString rangeOfString:@";" options:0
            range:NSMakeRange(range.location,
                              [cacheStateString length] - range.location)
            ].location;
        if (index != NSNotFound) {
            NSString *temp = [cacheStateString substringWithRange:
                NSMakeRange(range.location + range.length,
                            index - range.location - range.length)];
            cacheState = [temp doubleValue];
        }
        /*if (!_cacheFilled) {
            range = [cacheStateString rangeOfString:@"initialized: "];
            if (range.location != NSNotFound) {
                int index = [cacheStateString rangeOfString:@";" options:0
                    range:NSMakeRange(range.location,
                                      [cacheStateString length] - range.location)
                    ].location;
                if (index != NSNotFound) {
                    NSString *temp = [cacheStateString substringWithRange:
                        NSMakeRange(range.location + range.length,
                                    index - range.location - range.length)];
                    int initState = [temp intValue];
                    if (initState != 0) {
                        _cacheFilled = TRUE;
                        temp = [[_baseURL stringByAppendingString: @"?cacheFilled&clientId="] stringByAppendingString: _clientId];
                        temp = [_urlFetcher fetchURL:temp];
                    }
                }
            }
        }*/
    }
    
    if (_collectStreamInfo) {
        NSString* url = [[_baseURL stringByAppendingString: @"?getInfo&clientId="] stringByAppendingString: _clientId];
        //if (_firstVariableStreamId != nil) {
        //    url = [[url stringByAppendingString:@"&"] stringByAppendingString:_firstVariableStreamId];
        //}
        NSString* info = [_urlFetcher fetchURL:url];
        if ([info length] > 0) {
            // just to be safe in case something
            // goes wrong
            //NSString* firstVariableStreamId =
            //    [[_applicationController updateStreamInfo:info cacheState:cacheState] retain];
            [_applicationController updateStreamInfo:info cacheState:cacheState];
            //if (firstVariableStreamId != nil) {
            //    [_firstVariableStreamId autorelease];
            //    _firstVariableStreamId = [firstVariableStreamId retain];
            //}
        }
    } else {
        [_applicationController updateStreamInfo:nil cacheState:cacheState];
    }
}


/**
 * Skips forward or backward inside the stream.
 */

- (oneway void)skip:(int)skipTime {
    [_urlFetcher fetchURL: [_baseURL stringByAppendingString:
        [NSString stringWithFormat:@"?skip&%i&clientId=%@", skipTime, _clientId]]];
}


/**
 * Switch to the next channel.
 */

- (oneway void)channelUp {
    NSString* info = [_urlFetcher fetchURL: [_baseURL stringByAppendingString: @"?channelUp"]];
    // Sometimes, the connection fails with a
    // "zero byte resource" error. On the server
    // side, everything looks just fine in these
    // cases, so I'm assuming it's a Cocoa/WebKit bug.
    // Just ignore this here.
    if ([info length] > 0) {
        [_applicationController updateSelectedChannel: [info intValue]];
    }
}


/**
 * Switch to the previous channel.
 */

- (oneway void)channelDown {
    NSString* info = [_urlFetcher fetchURL: [_baseURL stringByAppendingString: @"?channelDown"]];
    // Sometimes, the connection fails with a
    // "zero byte resource" error. On the server
    // side, everything looks just fine in these
    // cases, so I'm assuming it's a Cocoa/WebKit bug.
    // Just ignore this here.
    if ([info length] > 0) {
        [_applicationController updateSelectedChannel: [info intValue]];
    }
}


/**
 * Switch to the next channel.
 */

- (void)nextChannel:(NSTimer*)timer {
    [self channelUp];
}

@end
