#import "AqQueryCell.h"
#import "DWCachedString.h"
#import "NSImageExtensions.h"
#import "NSStringExtensions.h"


@implementation AqQueryCell

/* Layout Parameters */

    #define kAqQueryCellLeftMargin  24.0f
    #define kAqQueryCellRightMargin 8.0f
    #define kAqQueryCellFindRatio   0.75f

#pragma mark -
/* Text Attributes */

    + (id) primaryAttributes; {
        static id attributes = nil;
        if (!attributes)
            attributes = [[NSDictionary alloc] initWithObjectsAndKeys: [NSFont boldSystemFontOfSize: 12], NSFontAttributeName, [NSColor blackColor], NSForegroundColorAttributeName, nil];
        return attributes;
    }
    
    + (id) secondaryAttributes; {
        static id attributes = nil;
        if (!attributes)
            attributes = [[NSDictionary alloc] initWithObjectsAndKeys: [NSFont systemFontOfSize: 11], NSFontAttributeName, [NSColor grayColor], NSForegroundColorAttributeName, nil];
        return attributes;
    }

    + (id) secondaryBlueAttributes; {
        static id attributes = nil;
        if (!attributes)
            attributes = [[NSDictionary alloc] initWithObjectsAndKeys: [NSFont boldSystemFontOfSize: 11], NSFontAttributeName, [NSColor colorWithCalibratedRed: 0.313726 green: 0.654902 blue: 0.988235 alpha: 1.0], NSForegroundColorAttributeName, nil];
        return attributes;
    }


#pragma mark -
/* Initialization */

    static id BH = nil;
    static id WHITE = nil;
    static id GRAY = nil;
    static id BLACK = nil;
    
    - (id) init; {
        self = [super init];
        controlOpacity = 1;
        controlOpacityTarget = 1;
        if (!BH) {
            BH = [[NSImage imageNamed: @"imacsmall"] retain];
            [BH setFlipped: YES];
            WHITE = [DWColor whiteColor];
            GRAY = [DWColor grayColor30];
            BLACK = [DWColor blackColor];
        }
        return self;
    }


#pragma mark -
/* Draw Individual Elements */
        
    - (void) drawFindInRect: (NSRect) rect;
    {
        static id oval = nil;
        if (!oval) 
        {
            oval = [[NSBezierPath bezierPathWithOvalInRect: (NSRect){
                {0,0}, 
                {kAqQueryCellFindRatio*rect.size.width, kAqQueryCellFindRatio*rect.size.height}
            }] retain];
            [oval setLineWidth: 2.2];
        }
        
        static id line = nil;
        if (!line) 
        {
            line = [[NSBezierPath bezierPath] retain];
            
            [line moveToPoint: (NSPoint){rect.size.width, rect.size.height}];
            [line lineToPoint: (NSPoint){(0.85*rect.size.width*kAqQueryCellFindRatio), (0.85*rect.size.height*kAqQueryCellFindRatio)}];
            [line setLineWidth: 2.2];
        }
        
        [[NSGraphicsContext currentContext] saveGraphicsState];
        
            id t2 = [NSAffineTransform transform];
            [t2 translateXBy: 7 yBy: rect.origin.y - 1.5];
            [t2 concat];
            
            if (mouseOver || (dwColorIndex == kDWColorAlternateIndex)) {
                [[WHITE colorWithAlphaComponent: controlOpacity] set];
            } else {
                [[GRAY colorWithAlphaComponent: controlOpacity/2] set];
            }
            
            [oval stroke];
            [line stroke];
    
        [[NSGraphicsContext currentContext] restoreGraphicsState];
    }
    
    - (void) drawArrowInRect: (NSRect) rect;
    {
        id path, t2;
        
        /* arc */
        
            static id arc = nil;
            if (!arc)
            {
                path = [NSBezierPath bezierPath];
                        
                #define v 3
                [path setLineWidth: 2];
                
                [path moveToPoint: (NSPoint){-5,0}];
        
                [path curveToPoint: (NSPoint){0, -5}
                    controlPoint1:  (NSPoint){-5,-v}
                    controlPoint2:  (NSPoint){-v,-5}];
        
                [path curveToPoint: (NSPoint){5, 0}
                    controlPoint1:  (NSPoint){v,-5}
                    controlPoint2:  (NSPoint){5,-v}];
                
                [path curveToPoint: (NSPoint){0,5}
                    controlPoint1:  (NSPoint){5,v}
                    controlPoint2:  (NSPoint){v,5}];
                #undef v
    
                arc = [path retain];
            }
            
        /* head */ 
        
            static id head = nil;
            if (!head)
            {
                path = [NSBezierPath bezierPath];
                
                [path moveToPoint: (NSPoint){0,9}];
                [path lineToPoint: (NSPoint){0,1}];
                [path lineToPoint: (NSPoint){-5,5}];
                [path lineToPoint: (NSPoint){0,9}];
    
                head = [path retain];
            }

        /* rotate */
        
            #define scale    0.8
    
            [[NSGraphicsContext currentContext] saveGraphicsState];
        
                t2 = [NSAffineTransform transform];
                [t2 translateXBy: rect.origin.x + rect.size.width/2 yBy: rect.origin.y + rect.size.height/2];
                [t2 scaleXBy: scale yBy: scale];
                [t2 rotateByDegrees: rotation];
                [t2 concat];
                
                if (mouseOver || (dwColorIndex == kDWColorAlternateIndex)) {
                    [[WHITE colorWithAlphaComponent: controlOpacity] set];
                } else {
                    [[GRAY colorWithAlphaComponent: controlOpacity] set];
                }
        
                [arc stroke];
                [head fill];
    
            [[NSGraphicsContext currentContext] restoreGraphicsState];
    }
    
    - (void) drawControlInRect: (NSRect) rect;
    {
        /* do some correction */
        
            if (controlOpacity < 0.0f)
                controlOpacity = 0.0f;
            
            if (controlOpacity > 1.0f)
                controlOpacity = 1.0f;
                
            if (bgOpacity < 0.0f)
                bgOpacity = 0.0f;
            
            if (bgOpacity > 1.0f)
                bgOpacity = 1.0f;

        /* background circle */
        
            if (bgOpacity > 0.0f)
            {
                NSBezierPath* circle = [NSBezierPath bezierPathWithOvalInRect: AqQueryCellTrackingRectInFrame(rect)];
                
                [[BLACK colorWithAlphaComponent: bgOpacity * .6f] set];
                [circle fill];
            }
    
        /* control */

            if (isBrowseHostCell) 
            {
                NSPoint bhPoint = rect.origin;
                bhPoint.x += 4.0f;
                bhPoint.y += 4.0f;
                float fraction = 1.0f;
                
                if (!secondary) {
                    fraction = 0.40f;
                }
                
                if (isActive && !secondary) {
                    //fraction = 0.75 + (sin((rotation/360)*6.283*2)) / 4;	/* between 0.5 and 1 */
                    //fraction = 0.65 + (sin((rotation/360)*6.283*2)) / 2.85;	/* between 0.3 and 1 */
                    fraction = 0.70f + (sin((rotation/360)*6.283*2)) / 3.333f;	/* between 0.4 and 1 */
                }
                                
                [BH drawAtPoint: bhPoint fromRect: NSZeroRect operation: NSCompositeSourceOver fraction: fraction];
            }
        
            if (isActive && !isBrowseHostCell) {
                [self drawArrowInRect: (NSRect){
                    {rect.origin.x + 8.5, rect.origin.y + 8.5}, 
                    {7, 7}
                }];
            }
            
            if (!isActive && !isBrowseHostCell) {

                static id find = nil;
                if (!find) {
                    find = [[NSImage imageNamed: @"AcqFindSmall"] copy];
                    [find setFlipped: YES];
                }

                if ((dwColorIndex == kDWColorWhiteIndex) && (!mouseOver) && (bgOpacity == 0) && (controlOpacity == 1)) {
                    [find drawAtPoint: (NSPoint){rect.origin.x+6, rect.origin.y+6} fromRect: NSZeroRect operation: NSCompositeSourceOver fraction: 1.0];
                } else {
                    [self drawFindInRect: (NSRect){
                        {rect.origin.x + 7, rect.origin.y + 8.5}, 
                        {10, 10}
                    }];
                }
            }
    }

    
#pragma mark -
/* Draw */

    NSRect AqQueryCellTrackingRectInFrame(NSRect frame) {
        return (NSRect){
            {frame.origin.x + 3.0f, frame.origin.y + 3.0f}, 
            {18.0f, 18.0f}
        };
    }

    - (void) drawWithFrame: (NSRect) frame inView: (id) view;
    {
        NSRect theRect;
        id theString;
    
        /* text - setup points */

            float sWidth = 0;
            if (secondary) sWidth = [secondary totalWidth] + 2.0f * kAqQueryCellRightMargin;
                        
            NSPoint primaryPoint = (NSPoint){
                frame.origin.x + kAqQueryCellLeftMargin,
                frame.origin.y + 4
            };
            NSPoint secondaryPoint = (NSPoint){
                frame.origin.x + frame.size.width - [secondary totalWidth] - kAqQueryCellRightMargin,
                frame.origin.y + 5
            };

        /* text - draw */
           
            if (NSPointInRect(primaryPoint, frame)) 
            {
                /* secondary */
                
                    theString = secondary;
                    theRect = frame;
                    theRect.origin = secondaryPoint;

                    if (dwColorIndex == kDWColorAlternateIndex) {
                        [theString setAlternateColor: WHITE];
                        theString = [theString alternateString];
                    }
        
                    [theString drawInRect: theRect centered: NO];
                

                /* primary */
                    
                    theRect = frame;
                    theRect.origin = primaryPoint;
                    theRect.size.width -= (primaryPoint.x + sWidth);
                    theString = primary;
        
                    if (dwColorIndex == kDWColorAlternateIndex) {
                        [theString setAlternateColor: WHITE];
                        theString = [theString alternateString];
                    }
        
                    [theString drawInRect: theRect centered: NO];
            }
                
        /* control */

            NSRect controlRect = {
                frame.origin,
                {30,30}
            };
            
            [self drawControlInRect: controlRect];
    }
    

#pragma mark -
/* set... */

    - (void) setPrimary: (DWTableString*) theString; {
        [primary release];
        primary = [theString retain];
        [primary setStyle: DWCollapseRight];
    }
    
    - (void) setSecondary: (DWTableString*) theString; {
        [secondary release];
        secondary = [theString retain];
        [secondary setStyle: DWCollapseNone];
    }

@end