#import "AqFilter.h"
#import "AqFilterController.h"


/* AqFilter */

    @implementation AqFilter
    
    /* Null implementations */
    /* Subclasses provide all implementation */
    
        - (id) filterView; {
            return nil;
        }
    
        - (AqFilterStateChange) changeState: (id) filterView; {
            return kAqFilterNoChange;
        }
        
        - (void) synchronizeViewWithCurrentState; {
        }
          
        - (NSString*) currentStateDescription; {
            return @"";
        }

        - (NSString*) description; {
            return [NSString stringWithFormat: @"%@: %@", [super description], [self currentStateDescription]];
        }
        
        - (BOOL(*)(AqFilter*, AqRemoteFile*)) filterFunction; {
            return 0;
        }
        
        - (BOOL) passesFilter: (AqRemoteFile*) theFile; {
            return YES;
        }
    
    @end


/* AqReliabilityFilter */
    
    @implementation AqReliabilityFilter
        
        /* View */

            - (id) filterView; {
                static id view;
                if (!view) {
                    view = [[NSSlider alloc] init];
                    [[view cell] setControlSize: NSSmallControlSize];
                    [view setNumberOfTickMarks: 5];
                    [view setAllowsTickMarkValuesOnly: YES];
                    [view setMinValue: 0];
                    [view setMaxValue: 4];
                }
                return view;
            }

        
        /* State */

            - (AqFilterStateChange) changeState: (id) filterView; 
            {
                int newState = [filterView intValue];
                
                #if 0
                NSLog(@"AqReliabilityFilter: %i", newState);
                #endif
                
                if (newState < iState) {
                    iState = newState;
                    return kAqFilterRelaxing;
                }
                if (newState > iState) {
                    iState = newState;
                    return kAqFilterTightening;
                }
                return kAqFilterNoChange;
            }
    
            - (void) synchronizeViewWithCurrentState; {
                [[self filterView] setIntValue: iState];
            }

            - (NSString*) currentStateDescription; {
                return [NSString stringWithFormat: @"%i stars", iState];
            }
        
        
        /* Filter */
            
            - (BOOL) passesFilter: (AqRemoteFile*) theFile; {
                return (theFile->rating >= iState);
            }
    
    @end


/* AqBitrateFilter */
    
    @implementation AqBitrateFilter
    
        /* View */
            
            - (id) filterView; {
                static id view;
                if (!view) {
                    view = [[NSSlider alloc] init];
                    [[view cell] setControlSize: NSSmallControlSize];
                    [view setMinValue: 0];
                    [view setMaxValue: 256];
                }
                return view;
            }


        /* State */
        
            - (AqFilterStateChange) changeState: (id) filterView; 
            {
                int newState = [filterView intValue];
                if (newState < iState) {
                    iState = newState;
                    return kAqFilterRelaxing;
                }
                if (newState > iState) {
                    iState = newState;
                    return kAqFilterTightening;
                }
                return kAqFilterNoChange;
            }
            
            - (void) synchronizeViewWithCurrentState; {
                [[self filterView] setIntValue: iState];
            }
            
            - (NSString*) currentStateDescription; {
                return [NSString stringWithFormat: @"%i kbps", iState];
            }


        /* Filter */
        
            - (BOOL) passesFilter: (AqRemoteFile*) theFile; {
                return ((int)theFile->bitrate >= iState);
            }
    
    @end


/* AqSizeFilter */

    @implementation AqSizeFilter

        /* View */
        
            - (id) filterView; {
                static id view;
                if (!view) {
                    view = [[NSSlider alloc] init];
                    [[view cell] setControlSize: NSSmallControlSize];
                    [view setMinValue: 0];
                    [view setMaxValue: 10000000];
                }
                return view;
            }
        
    
        /* State */

            - (AqFilterStateChange) changeState: (id) filterView; 
            {
                int newState = [filterView intValue];
                if (newState < iState) {
                    iState = newState;
                    return kAqFilterRelaxing;
                }
                if (newState > iState) {
                    iState = newState;
                    return kAqFilterTightening;
                }
                return kAqFilterNoChange;
            }
            
            - (void) synchronizeViewWithCurrentState; {
                [[self filterView] setIntValue: iState];
            }
        

        /* Filter */
    
            - (BOOL) passesFilter: (AqRemoteFile*) theFile; {
                return ((int)theFile->size >= iState);
            }
    
    @end


/* AqMediaFilter */
    
    #if 0
    #define ALL NSLocalizedStringFromTable(@"All", @"Filters", @"Media")
    #define MUSIC NSLocalizedStringFromTable(@"Music", @"Filters", @"Media")
    #define VIDEO NSLocalizedStringFromTable(@"Video", @"Filters", @"Media")
    #define IMAGES NSLocalizedStringFromTable(@"Images", @"Filters", @"Media")
    #define FILES NSLocalizedStringFromTable(@"Files", @"Filters", @"Media")

    @implementation AqMediaFilter
    
        /* View */
        
            - (id) filterView; {
                static id view;
                if (!view) {
                    view = [[NSPopUpButton alloc] init];
                    [[view cell] setControlSize: NSSmallControlSize];
                    
                    [view setFont: [NSFont systemFontOfSize: [NSFont smallSystemFontSize]]];
                    
                    NSMenu* theMenu = [[NSMenu alloc] init];
                        [theMenu addItemWithTitle: ALL action: nil keyEquivalent: @""];
                        [theMenu addItem: [NSMenuItem separatorItem]];
                        [theMenu addItemWithTitle: MUSIC action: nil keyEquivalent: @""];
                        [theMenu addItemWithTitle: VIDEO action: nil keyEquivalent: @""];
                        [theMenu addItemWithTitle: IMAGES action: nil keyEquivalent: @""];
                        [theMenu addItemWithTitle: FILES action: nil keyEquivalent: @""];
                    
                    [view setMenu: theMenu];
                }
                return view;
            }


        /* State */
                
            - (AqFilterStateChange) changeState: (id) filterView; 
            {	
                int newState = [filterView indexOfSelectedItem];
                AqFilterStateChange result;

                if (newState == iState)
                    result = kAqFilterNoChange;
                else if (iState == kAqMediaFilterAll)
                    result = kAqFilterTightening;
                else if (newState == kAqMediaFilterAll)
                    result = kAqFilterRelaxing;
                else
                    result = kAqFilterUnknown;

                iState = newState;
                return result;
            }
            
            - (void) synchronizeViewWithCurrentState; {
                [[self filterView] selectItemAtIndex: iState];
            }
        
            
        /* Filter */

            - (BOOL) passesFilter: (AqRemoteFile*) theFile; 
            {
                AqMediaType type = theFile->mediaType;

                switch (iState) 
                {
                    case kAqMediaFilterAll:
                        return YES;
                    
                    case kAqMediaFilterMusic:
                        return (type == kAqMusic);
                        
                    case kAqMediaFilterVideo:
                        return (type == kAqVideo);
                        
                    case kAqMediaFilterImages:
                        return (type == kAqImage);
                        
                    case kAqMediaFilterFiles:
                        return (type == kAqFile);
                }
                
                return NO;
            }

    @end
    #endif


/* AqKeywordFilter */

    @implementation AqKeywordFilter
        
        /* Initialization */

            - (id) init; {
                self = [super init];
                sState = @"";
                positive = [[NSMutableArray alloc] init];
                negative = [[NSMutableArray alloc] init];
                return self;
            }
            
            - (void) dealloc; {
                [positive release];
                [negative release];
                [super dealloc];
            }
    
        
        /* View */

            - (id) filterView; {
                #if 0
                static id view;
                if (!view) {
                    view = [[NSTextField alloc] init];
                    [view setContinuous: YES];
                }
                return view;
                #else
                return [((AqFilterController*)[AqFilterController instance])->keywordField retain];
                #endif
            }
            

        /* State */

            - (AqFilterStateChange) changeState: (id) filterView; 
            {
                id newState = [filterView stringValue];
                AqFilterStateChange result = kAqFilterUnknown;
                
                /*
                if (!sState || [sState isEqual: @""]) {
                    result = kAqFilterTightening;
                }
                else if ([newState hasPrefix: sState]) {
                    result = kAqFilterTightening;
                }
                else if ([sState hasPrefix: newState] || [newState isEqual: @""]) {
                    result = kAqFilterRelaxing;
                }
                */
                
                [sState release];
                sState = [newState retain];
                
                [positive removeAllObjects];
                [negative removeAllObjects];
                
                id frags = [[sState lowercaseString] componentsSeparatedByString: @" "];

                unsigned i;
                for (i=0; i<[frags count]; i++) 
                {
                    id frag = [frags objectAtIndex: i];
                    
                    if (![frag isEqual: @""]) {
                        if ([frag hasPrefix: @"-"]) {
                            if (![frag isEqual: @"-"] && [frag characterAtIndex: 1] != '-') {
                                [negative addObject: [frag substringFromIndex: 1]];
                            }
                        } else {
                            [positive addObject: frag];
                        }
                    }
                }

                //NSLog(@"+ %@", positive);
                //NSLog(@"- %@", negative);
                
                return result;
            }
            
            - (void) synchronizeViewWithCurrentState; {
                [[self filterView] setStringValue: sState];
            }


        /* Filter */

            - (BOOL) passesFilter: (AqRemoteFile*) theFile; 
            {
                int i, count;
                const void* theString = [[theFile nameAsData] bytes];
                                              
                /* - */
                
                    count = [negative count];
                    for (i=0; i<count; i++) {
                        if (NULL != strstr(theString, [[negative objectAtIndex: i] UTF8String]))
                            return NO;
                    }

                /* + */
                
                    count = [positive count];
                    for (i=0; i<count; i++) {
                        if (NULL == strstr(theString, [[positive objectAtIndex: i] UTF8String]))
                            return NO;
                    }
                    
                return YES;
            }

    @end
    

/* AqSpeedFilter */
    
    @implementation AqSpeedFilter
    
        /* View */
        
            - (id) filterView; {
                static id view;
                if (!view) {
                    view = [[NSSlider alloc] init];
                    [[view cell] setControlSize: NSSmallControlSize];
                    [view setMinValue: 0];
                    [view setMaxValue: 10000];
                }
                return view;
            }
        
        
        /* State */

            - (AqFilterStateChange) changeState: (id) filterView; 
            {
                int newState = [filterView intValue];
                if (newState < iState) {
                    iState = newState;
                    return kAqFilterRelaxing;
                }
                if (newState > iState) {
                    iState = newState;
                    return kAqFilterTightening;
                }
                return kAqFilterNoChange;
            }
            
            - (void) synchronizeViewWithCurrentState; {
                [[self filterView] setIntValue: iState];
            }


        /* Filter */

            - (BOOL) passesFilter: (AqRemoteFile*) theFile; {
                return ((int)theFile->speed >= iState);
            }
    
    @end


/* AqHostFilter */
    
    @implementation AqHostFilter

        /* View */
        
            - (id) filterView; {
                static id view;
                if (!view) {
                    view = [[NSSlider alloc] init];
                    [[view cell] setControlSize: NSSmallControlSize];
                    [view setMinValue: 0];
                    [view setMaxValue: 10];
                }
                return view;
            }
            
        
        /* State */

            - (AqFilterStateChange) changeState: (id) filterView; 
            {
                int newState = [filterView intValue];
                if (newState < iState) {
                    iState = newState;
                    return kAqFilterRelaxing;
                }
                if (newState > iState) {
                    iState = newState;
                    return kAqFilterTightening;
                }
                return kAqFilterNoChange;
            }
            
            - (void) synchronizeViewWithCurrentState; {
                [[self filterView] setIntValue: iState];
            }

        
        /* Filter */
        
            - (BOOL) passesFilter: (AqRemoteFile*) theFile; {
                return (theFile->count >= iState);
            }
    
    @end