/* Copyright (c) 2004, Noah Sorscher
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 	¥ 	Redistributions of source code must retain the above copyright
 * 	notice, this list of conditions and the following disclaimer.
 * 	¥ 	Redistributions in binary form must reproduce the above copyright
 * 	notice, this list of conditions and the following disclaimer in the
 * 	documentation and/or other materials provided with the distribution.
 * 	¥ 	Neither the name of the Noah Sorscher nor the names of its
 * 	contributors may be used to endorse or promote products derived from
 * 	this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */
#import "tWWW.h"


//BOOL isChoices(NSString *input);
char getEscChar(char *input);
BOOL hasPrefix(char *input, char *prefix);
//int expon(int a, int b);

NSMutableArray *theList, *epgSeries, *epgEps;

@interface NSObject (additions)
- (NSDictionary *)guessOneMovie:(NSString *)name;
@end

@implementation tWWW

- (IBAction) mhWeb:(id)sender
{
    //NSLog(@"tWWW mhWeb");
    int index = [mainTable selectedRow];
    MHMovie *movie = [[mainTable dataSource] movieForIndex:index];
    [MHWeb go];
    [MHWeb setSearchText:[movie stringValue]];
    //[MHEPGTVT setRegulars:[[NSUserDefaults standardUserDefaults] objectForKey:@"webRegs"]];
    [self movieDidChangeTo:movie];
}

- (void)webSelectionMade:(id)metadata
{
    //NSLog(@"tWWW webSelectionMade");
    if (nil == metadata) return;
    tPlaylist *model = [mainTable dataSource];
    int selection = [mainTable selectedRow];
    MHMovie *aMovie = [model movieForIndex:selection];
    if (nil == aMovie) {
        NSBeep();
        return;
    }
    if ([metadata isKindOfClass:[MHWeb class]]) {
        MHChapters *ch;
        if ([scaleChapters state])
            ch = [metadata chaptersScaledToMovie:aMovie];
        else
            ch = [metadata chapters];
        [(tChapters *)chapters setChapters:ch];
    } else if ([metadata isKindOfClass:[NSDictionary class]]) {
        [self insertMetadata:metadata intoMovie:aMovie];
        [model tableViewSelectionDidChange:nil];
        [mainTable reloadData];
    }
}

- (void)insertMetadata:(NSDictionary *)metadata intoMovie:(MHMovie *)aMovie
{
    //int num = [metadata count];
    NSArray *keys = [metadata allKeys];
    NSString *key, *value;
    int i, j, m, n = [keys count];
    NSString *fn = nil;
    for (i=0;i<n;i++) {
        key = [keys objectAtIndex:i];
        if ([self keyIsGood:key]) {
            value = [[metadata objectForKey:key] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
            if ([optReduce state])
                value = [self reduce:value];
            if ([key isEqualToString:@"Performers"]) {
                NSScanner *scan = [NSScanner scannerWithString:value];
                m = [numPerformers intValue];
                for (j=0;j<m;j++)
                    [scan scanPastString:@", "];
                if (![scan isAtEnd])
                    value = [value substringToIndex:[scan scanLocation]-2];
            }
	    else if ([key isEqualToString:@"Full Name"]) {
		fn = value;
		value = [self uninvert:value];
	    }
            else if ([key isEqualToString:@"Cover Image"])
                [aMovie setImageFile:value];
            else if ([optMerge state]) {
                NSString *oldValue = [aMovie objectForKey:key];
                value = [self mergeThis:value that:oldValue];
            }
            [aMovie setObject:value forKey:key language:@"English"];
        }
    }
    if ([optComment state])
        [aMovie setObject:[commentText stringValue] forKey:@"Comment" language:@"English"];
    if ([updateFilename state] && fn) {
        fn = [fn stringByAppendingString:@".mov"];
        NSString *buffer = [aMovie objectForKey:@"Product"];
        if (buffer != nil) {
            if (![fn hasPrefix:@" "] && ![buffer hasSuffix:@" "])
                buffer = [buffer stringByAppendingString:@" "];
            fn = [NSString stringWithFormat:@"%@%@", buffer, fn];
        }
        [aMovie setObject:fn forKey:@"File Name"];
    }
}

- (void)webOptionsButtonPressed
{
    [prefsTab selectTabViewItemWithIdentifier:@"Web Lookup"];
    [prefs makeKeyAndOrderFront:nil];
}

- (void)guessWholeSeries:(id)sender
{
    if ([sender respondsToSelector:@selector(guessOneMovie:)]) {
        int i, n = [mainTable numberOfRows];
        for (i=0;i<n;i++) {
            MHMovie *movie = [[mainTable dataSource] movieForIndex:i];
            NSDictionary *guess = [sender guessOneMovie:[movie objectForKey:@"File Name"]];
            if (guess)
                [self insertMetadata:guess intoMovie:movie];
        }
        [mainTable reloadData];
    }
}

- (void)awakeFromNib
{
    //NSLog(@"tWWW");
    [MHWeb addWebSelectionListener:self];
    [MHWeb addOptionsButtonListener:self];
}

- (void)movieDidChangeTo:(MHMovie *)aMovie
{
    if (aMovie)
        [MHWeb setTitle:[aMovie stringValue]];
    else
        [MHWeb setTitle:nil];
}

- (BOOL)pictures
{
    return [optIcon state];
}

- (BOOL)keyIsGood:(NSString *) key
{
    //NSLog(@"tWWW keyIsGood");
    NSArray *bad = [NSArray arrayWithObjects:@"title", @"code", @"dl", @"address", nil];
    NSArray *good = [NSArray arrayWithObjects:@"Album", @"Author", @"Copyright", @"Creation Date", @"Full Name", @"Description", @"Director", @"Information", @"Performers", @"Product", @"Writer", @"Genre", @"Website", @"Cover Image", @"Rating", nil];
    NSArray *preferences = [NSArray arrayWithObjects:optAlbum, optAuthor, optCopy, optCreDate, optFName, optDesc, optDir, optInfo, optPerf, optProd, optWrit, optGenre, optWebsite, optIcon, optRating, optIcon, nil];
    int i, n = [bad count];
    if (key == nil) return NO;
    for (i=0;i<n;i++) {
        if ([key isEqualToString:[bad objectAtIndex:i]]) return NO;
    }
    n = [good count];
    for (i=0;i<n;i++) {
        if ([key isEqualToString:[good objectAtIndex:i]])
            return [[preferences objectAtIndex:i] state];
    }
    return YES;
}


- (NSString *)mergeThis:(NSString *)this that:(NSString *)that
{
    //NSLog(@"tWWW mergeThis:that");
    BOOL trueThis, trueThat;
    trueThis = [self checkString:this];
    trueThat = [self checkString:that];
    if (!trueThis && !trueThat) return @"";
    if (!trueThis) return [that copy];
    if (!trueThat) return [this copy];
    
    if ([this isEqualToString:that]) return [this copy];
    NSRange aRange;
    NSArray *a = [that componentsSeparatedByString:@", "];
    NSString *buffer;
    NSMutableString *output = [NSMutableString stringWithCapacity:[this length] + [that length]];
    [output appendString:this];
    int i, n = [a count];
    for (i=0;i<n;i++) {
        buffer = [a objectAtIndex:i];
        aRange = [this rangeOfString:buffer options:NSCaseInsensitiveSearch];
        if (aRange.length == 0) {
            [output appendString:@", "];
            [output appendString:buffer];
        }
    }
    return output;
}

- (BOOL)checkString:(NSString *)s
{
    return (nil != s && [s isKindOfClass:[NSString class]] && ![s isEqualToString:@""]);
}

- (BOOL)stringEquiv:(NSString *)s1 toString:(NSString *)s2
{
    NSArray *strings = [NSArray arrayWithObjects:s1, s2, nil];
    NSArray *mStrings = [NSArray arrayWithObjects:[NSMutableString string], [NSMutableString string], nil];
    int i;
    NSCharacterSet *punct = [NSCharacterSet punctuationCharacterSet];
    for (i=0;i<[strings count];i++) {
        NSScanner *scan = [NSScanner scannerWithString:[strings objectAtIndex:i]];
        [scan setCaseSensitive:NO];
        while (![scan isAtEnd]) {
            NSString *buffer;
            [scan scanUpToCharactersFromSet:[NSCharacterSet whitespaceCharacterSet] intoString:&buffer];
            [scan setScanLocation:[scan scanLocation]+1];
            buffer = [buffer stringByTrimmingCharactersInSet:punct];
            if ([self isWord:buffer]) {
                if ([(NSString *)[mStrings objectAtIndex:i] length])
                    [[mStrings objectAtIndex:i] appendString:@" "];
                [[mStrings objectAtIndex:i] appendString:buffer];
            }
        }
    }
    return ([[mStrings objectAtIndex:0] compare:[mStrings objectAtIndex:1] options:NSCaseInsensitiveSearch] == NSOrderedSame);
}

- (NSString *)uninvert:(NSString *)input
{
    NSArray *sufs = [NSArray arrayWithObjects:@", the", @", a", @", an", nil];
    int i, n = [sufs count];
    for (i=0;i<n;i++) {
	if ([[input lowercaseString] hasSuffix:[sufs objectAtIndex:i]]) {
	    int length = [input length], elength = [(NSString *)[sufs objectAtIndex:i] length];
	    NSString *end = [input substringFromIndex:length - elength + 2];
	    input = [input substringToIndex:length - elength];
	    return [NSString stringWithFormat:@"%@ %@", end, input];
	}
    }
    return input;
}

- (NSString *)reduce:(NSString *)input
{
    NSArray *names = [input componentsSeparatedByString:@","];
    NSMutableArray *uNames = [NSMutableArray array];
    int i, n = [names count];
    for (i=0;i<n;i++) {
	NSString *aName = [names objectAtIndex:i];
	NSRange aRange = [aName rangeOfString:@"("];
	NSRange bRange = [aName rangeOfString:@")"];
	if (aRange.length && bRange.length && bRange.location > aRange.location) {
	    NSMutableString *mName = [NSMutableString stringWithString:aName];
	    aRange.length = bRange.location - aRange.location + 1;
	    [mName deleteCharactersInRange:aRange];
            [mName replaceOccurrencesOfString:@"  " withString:@" " options:NSLiteralSearch range:NSMakeRange(0, [mName length]-1)];
	    aName = [mName whitespaceTrimmed];
            if ([aName hasSuffix:@" &"]) aName = [aName substringToIndex:[aName length]-2];
            else if ([aName hasSuffix:@" and"]) aName = [aName substringToIndex:[aName length]-4];
	}
	if (![uNames containsObject:aName])
	    [uNames addObject:[aName whitespaceTrimmed]];
    }
    return [uNames componentsJoinedByString:@", "];
}

- (BOOL) isWord:(NSString *)aWord
{
    if (!aWord) return NO;
    NSArray *nonWords = [NSArray arrayWithObjects:@"", @"a", @"an", @"the", nil];
    int i, n = [nonWords count];
    for (i=0;i<n;i++) {
        if ([aWord compare:[nonWords objectAtIndex:i] options:NSCaseInsensitiveSearch] == NSOrderedSame)
            return NO;
    }
    return YES;
}



- (IBAction)editRegulars:(id)sender
{
    [regsWin makeKeyAndOrderFront:nil];
}

- (IBAction)add:(id)sender
{
    NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
    NSMutableDictionary *regs = [NSMutableDictionary dictionaryWithDictionary:[defs objectForKey:@"webRegs"]];
    [regs setObject:@"New Regulars" forKey:@"New Series"];
    [defs setObject:regs forKey:@"webRegs"];
    [defs synchronize];
    [regsTable reloadData];
}

- (IBAction)remove:(id)sender
{
    int index = [regsTable selectedRow];
    if (index == -1) return;
    NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
    NSMutableDictionary *regs = [NSMutableDictionary dictionaryWithDictionary:[defs objectForKey:@"webRegs"]];
    NSString *key = [[regs allKeys] objectAtIndex:index];
    [regs removeObjectForKey:key];
    [defs setObject:regs forKey:@"webRegs"];
    [defs synchronize];
    [regsTable reloadData];
}


- (int)numberOfRowsInTableView:(NSTableView *)tview
{
    NSDictionary *regs = [[NSUserDefaults standardUserDefaults] objectForKey:@"webRegs"];
    return [regs count];
}

- (id)tableView:(NSTableView *)tview objectValueForTableColumn:(NSTableColumn *)col row:(int)row
{
    NSDictionary *regs = [[NSUserDefaults standardUserDefaults] objectForKey:@"webRegs"];
    NSString *key = [[regs allKeys] objectAtIndex:row];
    if ([[col identifier] isEqualToString:@"Series"]) return key;
    return [regs objectForKey:key];
}

- (void)tableView:(NSTableView *)tview setObjectValue:(id)object forTableColumn:(NSTableColumn *)col row:(int)row
{
    NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
    NSMutableDictionary *regs = [NSMutableDictionary dictionaryWithDictionary:[defs objectForKey:@"webRegs"]];
    NSString *key = [[regs allKeys] objectAtIndex:row];
    NSString *value = [regs objectForKey:key];
    if ([[col identifier] isEqualToString:@"Series"]) {
        // changing series name
        [regs removeObjectForKey:key];
        if (object)
            [regs setObject:value forKey:object];
    } else {
        if (object) [regs setObject:object forKey:key];
        else [regs removeObjectForKey:key];
    }
    [defs setObject:regs forKey:@"webRegs"];
    [defs synchronize];
}


// EPGuides
/*
- (void)epgSearch:(NSString *)input
{
    [epg epgSearch:input];
}

- (void)displayEPGresults:(NSString *)input
{
    //NSLog(@"tWWW displayEPGresults");
    BOOL success;
    if (input == nil) {
        NSBeep();
        return;
    }
    NSString *buffer, *address;
    tSeriesObject *aResult;
    NSScanner *scan = [[NSScanner alloc] initWithString:input];
    [scan setCaseSensitive:NO];
    while (![scan isAtEnd]) {
        buffer = address = nil;
        [scan scanUpToString:@"/?u=" intoString:nil];
        [scan scanUpToString:@"http%3A//" intoString:nil];
        [scan scanString:@"http%3A//" intoString:nil];
        [scan scanUpToString:@"\"" intoString:&address];
        if (address != nil) {
            address = [NSString stringWithFormat:@"http://%@",address];
            [scan scanUpToString:@"STRONG>" intoString:nil];
            [scan scanString:@"STRONG>" intoString:nil];
            [scan scanUpToString:@"</STRONG>" intoString:&buffer];
            if (buffer != nil) {
                buffer = [self cleanHTML:buffer];
                if (![buffer hasPrefix:@"epguides"]) {
                    aResult = [[tSeriesObject alloc] initWithTitle:buffer address:address];
                    success = [[tSeriesObject rootNode] addSeries:aResult];
                }
            }
        }
    }
    [theOutline expandItem:[tSeriesObject rootNode]];
    [theOutline reloadData];
}

- (NSMutableDictionary *)parseEPGEpisodes:(NSString *)htmlString
{
    //NSLog(@"tWWW parseEPGEpisodes:");
    if (htmlString == nil || ![htmlString isKindOfClass:[NSString class]]) return nil;
    NSScanner *shortScanner, *scan = [[NSScanner alloc] initWithString:htmlString];
    [scan setCaseSensitive:NO];
    NSString *shortString;
    NSString *buffer, *name, *tag, *date, *date1, *date2, *date3, *address;
    int season, ep, count;
    NSMutableDictionary *entry, *theResult = [[NSMutableDictionary alloc] initWithCapacity:10];
    NSCharacterSet *end = [NSCharacterSet characterSetWithCharactersInString:@"\n\r<"];
    NSMutableArray *episodes = [[NSMutableArray alloc] init];
    [theResult setObject:episodes forKey:@"episodes"];
    NSMutableString *regulars = [[NSMutableString alloc] initWithCapacity:128];
    [theResult setObject:regulars forKey:@"regulars"];
    
    // Regulars
    shortString = nil;
    [scan scanUpToString:@"<ul>" intoString:nil];
    [scan scanUpToString:@"<p>" intoString:&shortString];
    if (shortString != nil) {
        shortScanner = [[NSScanner alloc] initWithString:shortString];
        [shortScanner setCaseSensitive:NO];
        [shortScanner scanUpToString:@"<li>" intoString:nil];
    	while (![shortScanner isAtEnd]) {
            buffer = nil;
            [shortScanner scanUpToString:@"<strong>" intoString:nil];
            [shortScanner scanString:@"<strong>" intoString:nil];
            [shortScanner scanUpToString:@"</strong>" intoString:&buffer];
            if (buffer != nil) {
                if ([regulars length] > 0)
                    [regulars appendString:@", "];
                [regulars appendString:buffer];
            }
        }
    }
    //[shortScanner release];
    
    // Episodes
    count = 1;
    while (![scan isAtEnd]) {
        buffer = name = tag = date = date1 = date2 = date3 = address = nil;
        season = ep = -1;
        [scan scanUpToString:[NSString stringWithFormat:@"%d. ", count] intoString:nil];
        [scan scanString:[NSString stringWithFormat:@"%d. ", count++] intoString:nil];
        [scan scanInt:&season];
        [scan scanString:@"-" intoString:nil];
        [scan scanInt:&ep];
        [scan scanUpToString:@" " intoString:nil];
        [scan scanUpToString:@" " intoString:&date1];
        [scan scanUpToString:@" " intoString:&date2];
        [scan scanUpToString:@" " intoString:&date3];
        if (date1 != nil && date2 != nil && date3 != nil)
            date = [NSString stringWithFormat:@"%@ %@ %@", date1, date2, date3];
        if ([scan scanString:@"<" intoString:nil]) {
            [scan scanUpToString:@"href=\"" intoString:nil];
            [scan scanString:@"href=\"" intoString:nil];
            [scan scanUpToString:@"\"" intoString:&address];
            [scan scanUpToString:@">" intoString:nil];
            [scan scanString:@">" intoString:nil];
        }
        [scan scanUpToCharactersFromSet:end intoString:&name];
        if (name != nil && address != nil) {
            if (date != nil)
                name = [NSString stringWithFormat:@"%@ %@", date, name];
            if (season != -1 && ep != -1)
                if (season == 5 && ep == 17)
                    season = 5;
                name = [NSString stringWithFormat:@"%d-%d %@", season, ep, name];
            entry = [[NSMutableDictionary alloc] initWithCapacity:10];
            [entry setObject:name forKey:@"title"];
            [entry setObject:address forKey:@"address"];
            [entry setObject:[NSNumber numberWithBool:NO] forKey:@"dl"];
            [episodes addObject:entry];
        }
    }
    return theResult;
}

- (void)tvtSearch:(NSString *)input
{
    [epg tvtSearch:input];
}

- (void)displayTVTresults:(NSString *)htmlString
{
    tSeriesObject *aResult;
    BOOL success;
    NSRange aRange = [htmlString rangeOfString:@"Didn't find what you were looking for?" options:NSCaseInsensitiveSearch];
    if (aRange.location != NSNotFound)
        htmlString = [htmlString substringToIndex:aRange.location];
    NSScanner *scan = [NSScanner scannerWithString:htmlString];
    NSString *buffer, *address;
    [scan scanUpToString:@"Show search for:" intoString:nil];
    [scan setCaseSensitive:NO];
    while (![scan isAtEnd]) {
        buffer = address = nil;
        [scan scanUpToString:@"<a href=\"" intoString:nil];
        [scan scanString:@"<a href=\"" intoString:nil];
        [scan scanUpToString:@"\"" intoString:&address];
        [scan scanUpToString:@">" intoString:nil];
        [scan scanString:@">" intoString:nil];
        [scan scanUpToString:@"</a>" intoString:&buffer];
        if (buffer != nil && address != nil) {
            address = [NSString stringWithFormat:@"http://www.tvtome.com%@eplist.html", address];
            aResult = [[tSeriesObject alloc] initWithTitle:buffer address:address];
            success = [[tSeriesObject rootNode] addSeries:aResult];
        }
    }
    [theOutline expandItem:[tSeriesObject rootNode]];
    [theOutline reloadData];
}

- (NSDictionary *)readTVTURL:(NSString *)address
{
    NSString *htmlString = nil;
    htmlString = [NSString stringWithContentsOfURL:[NSURL URLWithString:address]];
    if (htmlString == nil) return nil;
    //NSString *suffix;
    NSArray *theComponents = [address componentsSeparatedByString:@"#"];
    return [self readTVThtml:htmlString suffix:[theComponents objectAtIndex:1]];
}

- (NSDictionary *)readTVThtml:(NSString *)htmlString suffix:(NSString *)suffix
{
    //NSLog(@"tWWW readTVTURL:");
    //NSString *htmlString = nil;
    //htmlString = [NSString stringWithContentsOfURL:[NSURL URLWithString:address]];
    //[htmlString writeToFile:@"text.txt" atomically:YES];
    //if (htmlString == nil) return nil;
    // shortString: starts at beginning of this episode
    // substring: shorter
    NSString *shortString, *substring, *name, *buffer, *desc, *date, *pc, *tag;
    NSMutableDictionary *theResult = [[NSMutableDictionary alloc] initWithCapacity:10];
    //NSArray *theComponents = [address componentsSeparatedByString:@"#"];
    //if ([theComponents count] != 2) return theResult;
    NSRange aRange;
    
    aRange = [htmlString rangeOfString:suffix];
    if (aRange.location == NSNotFound) return theResult;
    shortString =[htmlString substringFromIndex:aRange.location];
    NSScanner *scanSmall, *scan = [[NSScanner alloc] initWithString:shortString];
    [scan setCaseSensitive:NO];
    
    // name
  if ([optFName state]) {
    name = nil;
    [scan scanUpToString:@">" intoString:nil];
    [scan scanString:@">" intoString:nil];
    [scan scanUpToString:@"<" intoString:&name];
    if (name != nil) [theResult setObject:name forKey:@"Full Name"];
    
    // guest stars
    NSMutableString *gs = [[NSMutableString alloc] init];
    aRange = [shortString rangeOfString:@"<i>gs</i>" options:NSCaseInsensitiveSearch];
    if (aRange.location != NSNotFound) {
        substring = [shortString substringFromIndex:aRange.location];
        aRange = [substring rangeOfString:@"</tr>" options:NSCaseInsensitiveSearch];
        if (aRange.location != NSNotFound) {
            substring = [substring substringToIndex:aRange.location];
            scanSmall = [[NSScanner alloc] initWithString:substring];
            [scanSmall setCaseSensitive:NO];
            while (![scanSmall isAtEnd]) {
                buffer = nil;
                [scanSmall scanUpToString:@"/tvtome/servlet/PersonDetail/personid" intoString:nil];
                [scanSmall scanUpToString:@">" intoString:nil];
                [scanSmall scanString:@">" intoString:nil];
                [scanSmall scanUpToString:@"<" intoString:&buffer];
                if (buffer != nil) {
                    if ([gs length] > 0) [gs appendString:@", "];
                    [gs appendString:buffer];
                }
            }
        }
    }
    if ([gs length] > 0)
        [theResult setObject:gs forKey:@"Guest Stars"];
  }
    
    
    aRange = [shortString rangeOfString:@"name=" options:NSCaseInsensitiveSearch];
    if (aRange.location != NSNotFound)
        substring = [shortString substringToIndex:aRange.location];
    else
        substring = shortString;
    scanSmall = [[NSScanner alloc] initWithString:substring];
    // Description
  if ([optDesc state]) {
    [scanSmall setScanLocation:0];
    desc = nil;
    [scanSmall scanUpToString:@"</tr>" intoString:nil];
    [scanSmall scanString:@"</tr>" intoString:nil];
    [scanSmall scanUpToString:@"</tr>" intoString:nil];
    [scanSmall scanUpToString:@"<br>" intoString:nil];
    [scanSmall scanString:@"<br>" intoString:nil];
    [scanSmall scanUpToString:@"</td>" intoString:&desc];
    if (desc != nil)
        [theResult setObject:[self fixIMDB:[self cleanHTML:desc]] forKey:@"Description"];
  }
    
    // Air Date
  if ([optCreDate state]) {
    [scanSmall setScanLocation:0];
    date = nil;
    [scanSmall scanUpToString:@"<i>b</i>:" intoString:nil];
    [scanSmall scanString:@"<i>b</i>:" intoString:nil];
    [scanSmall scanUpToString:@"<" intoString:&date];
    if (date != nil)
        [theResult setObject:[self fixIMDB:date] forKey:@"Creation Date"];
  }
    
    // Production Code
  if ([optProd state]) {
    [scanSmall setScanLocation:0];
    pc = nil;
    [scanSmall scanUpToString:@"<i>pc</i>:" intoString:nil];
    [scanSmall scanString:@"<i>pc</i>:" intoString:nil];
    [scanSmall scanUpToString:@"<" intoString:&pc];
    if (pc != nil)
        [theResult setObject:[self fixIMDB:pc] forKey:@"Product"];
  }
    
    // Writer
  if ([optWrit state]) {
    NSMutableString *writer = [[NSMutableString alloc] init];
    [scanSmall setScanLocation:0];
    [scanSmall scanUpToString:@"<i>w</i>:" intoString:nil];
    [scanSmall scanString:@"<i>w</i>:" intoString:nil];
    while (![scanSmall isAtEnd]) {
        buffer = tag = nil;
        [scanSmall scanUpToString:@"<" intoString:&buffer];
        [scanSmall scanString:@"<" intoString:nil];
        if (buffer != nil) {
            if ([writer length] > 0 && ![writer hasSuffix:@" "]) [writer appendString:@" "];
            [writer appendString:buffer];
        }
        [scanSmall scanString:@"/" intoString:nil];
        [scanSmall scanUpToString:@">" intoString:&tag];
        [scanSmall scanString:@">" intoString:nil];
        if (tag != nil) {
            if (![tag hasPrefix:@"a"] && ![tag hasPrefix:@"A"])
                break;
        }
    }
    if ([writer length] > 0)
        [theResult setObject:[self fixIMDB:writer] forKey:@"Writer"];
  }
    
    // Director
  if ([optDir state]) {
    NSMutableString *director = [[NSMutableString alloc] init];
    [scanSmall setScanLocation:0];
    [scanSmall scanUpToString:@"<i>d</i>:" intoString:nil];
    [scanSmall scanString:@"<i>d</i>:" intoString:nil];
    while (![scanSmall isAtEnd]) {
        buffer = tag = nil;
        [scanSmall scanUpToString:@"<" intoString:&buffer];
        [scanSmall scanString:@"<" intoString:nil];
        if (buffer != nil) {
            if ([director length] > 0 && ![director hasSuffix:@" "]) [director appendString:@" "];
            [director appendString:buffer];
        }
        [scanSmall scanString:@"/" intoString:nil];
        [scanSmall scanUpToString:@">" intoString:&tag];
        [scanSmall scanString:@">" intoString:nil];
        if (tag != nil) {
            if (![tag hasPrefix:@"a"] && ![tag hasPrefix:@"A"])
                break;
        }
    }
    if ([director length] > 0)
        [theResult setObject:[self fixIMDB:director] forKey:@"Director"];
  }
    
    return theResult;
}

- (IBAction)flush:(id)sender
{
    //NSLog(@"tWWW flush");
    NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
    [defs removeObjectForKey:@"Cache"];
    [[tSeriesObject rootNode] removeChildren];
    [theOutline reloadData];
}

- (NSTextField *)getEPGText
{
    return epgText;
}

- (void)epgDisplay:(NSString *)input
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    [epgText setStringValue:input];
    [pool release];
}

// Blockbuster

- (void)bbSearch:(NSString *)input
{
    if (nil == bb) {
        bb = [[MHBB alloc] init];
        [bb setTextField:bbText];
        [bb setTextFieldForImage:picField];
    }
    [bb search:input];
}

- (IBAction)bbSearchAgain:(id)sender
{
    if (nil == bb) return;
    [bb bbSearchAgain:nil];
}
*/
@end
