#import "BBObjectCell.h"

@implementation BBObjectCell

- (NSCellImagePosition)preferredImagePosition {
    return NSImageAbove;
}

- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {  
  BOOL isFirstResponder = [[controlView window] firstResponder] == controlView && ![controlView isKindOfClass:[NSTableView class]];
  BOOL dropTarget = ([self isHighlighted] && ([self highlightsBy] & NSChangeBackgroundCellMask) && ![self isBezeled]);

	NSColor *fillColor;
	NSColor *strokeColor = [NSColor clearColor];

  if (isFirstResponder) {
    fillColor = [NSColor selectedTextBackgroundColor];
  } else {
    fillColor = [NSColor clearColor];
  }

  if (dropTarget) {
    fillColor = [NSColor controlAccentColor];
  }

  [fillColor setFill];
	[strokeColor setStroke];

  NSBezierPath *roundRect = [NSBezierPath bezierPath];
  [roundRect appendBezierPathWithRoundedRectangle:cellFrame withRadius:NSHeight(cellFrame)/cellRadiusFactor];
  [roundRect fill];

	[self drawInteriorWithFrame:[self drawingRectForBounds:cellFrame] inView:controlView];
}

- (NSRect)titleRectForBounds:(NSRect)theRect
{
  NSRect rect = theRect;
  rect = NSOffsetRect(rect, 0, -4);
  return [super titleRectForBounds: rect];
}

- (void)drawTextForObject:(QSObject *)drawObject withFrame:(NSRect)cellFrame inView:(NSView *)controlView {
  if ([self imagePosition] == NSImageOnly) return;

  NSString *abbrString = nil;
  if ([controlView respondsToSelector:@selector(matchedString)])
    abbrString = [(QSSearchObjectView *)controlView matchedString];

  NSString *nameString = nil;
  NSIndexSet *hitMask = nil;

  id ranker = [drawObject ranker];
  if (ranker && abbrString)
    nameString = [ranker matchedStringForAbbreviation:abbrString hitmask:&hitMask inContext:nil];

  if (!nameString)
    nameString = [drawObject displayName];

  BOOL rankedStringIsName = [nameString isEqualToString:[drawObject displayName]] || nameString == nil;
  if (!nameString) {
    // fall back to the identifier if no reasonable name can be found
    nameString = [drawObject identifier];
  }
  if (!nameString) {
    // Couldn't find anything sensible to use for the name, fallback to avoid a crash
    nameString = @"Unknown";
  }

  BOOL useAlternateColor = [controlView isKindOfClass:[NSTableView class]] && [(NSTableView *)controlView isRowSelected:[(NSTableView *)controlView rowAtPoint:cellFrame.origin]];
  NSColor *mainColor = (textColor ? textColor : (useAlternateColor ? [NSColor alternateSelectedControlTextColor] : [NSColor controlTextColor]));
  NSColor *fadedColor = [mainColor colorWithAlphaComponent:0.50];
  NSRect textDrawRect = [self titleRectForBounds:cellFrame];

  NSMutableAttributedString *titleString = [[[NSMutableAttributedString alloc] initWithString:nameString] autorelease];
  [titleString setAttributes:rankedStringIsName ? nameAttributes : detailsAttributes range:NSMakeRange(0, [titleString length])];

  // Bring out the matched letters
  if (abbrString && ![abbrString hasPrefix:@"QSActionMnemonic"]) {
    [titleString addAttribute:NSForegroundColorAttributeName value:rankedStringIsName ? fadedColor : [fadedColor colorWithAlphaComponent:0.8] range:NSMakeRange(0, [titleString length])];

    NSUInteger i = 0;
    NSUInteger j = 0;
    NSUInteger hits[[titleString length]];
    NSUInteger count = [hitMask getIndexes:(NSUInteger *)&hits maxCount:[titleString length] inIndexRange:nil];
    NSDictionary *attributes = @{
      NSForegroundColorAttributeName:                                 rankedStringIsName ? mainColor : fadedColor
    };
    for(i = 0; i<count; i += j) {
      for (j = 1; i+j<count && hits[i+j-1] +1 == hits[i+j]; j++);
      [titleString addAttributes:attributes range:NSMakeRange(hits[i], j)];
    }
  } else {
    [titleString addAttribute:NSBaselineOffsetAttributeName value:[NSNumber numberWithDouble:-1.0] range:NSMakeRange(0, [titleString length])];
  }
//
//  // Ranked string and nameString aren't the same. Show 'nameString  ⟷ rankedString' in the UI
//  if (!rankedStringIsName && [drawObject displayName].length) {
//    [titleString addAttribute:NSFontAttributeName value:detailsFont range:NSMakeRange(0,[titleString length])];
//    NSMutableAttributedString *attributedNameString = [[NSMutableAttributedString alloc] initWithString:[drawObject displayName]];
//    [attributedNameString setAttributes:nameAttributes range:NSMakeRange(0, [[drawObject displayName] length])];
//
//    [attributedNameString appendAttributedString:[[[NSAttributedString alloc] initWithString:@" ⟷ " attributes:rankedNameAttributes] autorelease]];
//    // the replaceCharacters... method inserts the new string into the receiver at the start of the work (range.location and range.length are 0)
//    [titleString replaceCharactersInRange:NSMakeRange(0,0) withAttributedString:attributedNameString];
//    [attributedNameString release];
//  }

  if (showDetails) {
    NSString *detailsString = [drawObject details];
    
    NSRange returnRange = [detailsString rangeOfString:@"\n"];
    if (returnRange.location != NSNotFound) {
      detailsString = [detailsString substringToIndex:returnRange.location];
    }

    detailsAttributes = [detailsAttributes mutableCopy];
    [detailsAttributes setValue:[NSColor grayColor] forKey:NSForegroundColorAttributeName];
    
    if (detailsString && detailsString.length && ![detailsString isEqualToString:nameString]) {
      [titleString appendAttributedString:[[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"\n%@",detailsString] attributes:detailsAttributes] autorelease]];
    }
  }

  NSRect centerRect = rectFromSize([titleString size]);
  centerRect.size.width = NSWidth(textDrawRect);
  centerRect.size.height = MIN(NSHeight(textDrawRect), centerRect.size.height);
  [titleString drawInRect:centerRectInRect(centerRect, textDrawRect)];
}

- (void)drawSearchPlaceholderWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
  NSString *defaultText = NSLocalizedStringWithDefaultValue(@"Type to search", nil, [NSBundle mainBundle], @"Type to search", @"Hint that appears in the first pane of the QS interface when it's empty.");
  NSSize textSize = [defaultText sizeWithAttributes:nameAttributes];
  NSRect textRect = centerRectInRect(rectFromSize(textSize), cellFrame);
  BOOL isFirstResponder = [[controlView window] firstResponder] == controlView && ![controlView isKindOfClass:[NSTableView class]];
  
  if (isFirstResponder && [controlView isKindOfClass:[QSSearchObjectView class]]) {
    NSImage *find = [NSImage imageWithSystemSymbolName:@"magnifyingglass.circle.fill" accessibilityDescription:nil];
    
    
    [find setSize:QSSize16];
    NSRect findImageRect = expelRectFromRectOnEdge(centerRectInRect(rectFromSize([find size]), cellFrame), textRect, NSRectEdgeMinX, -2);
    
  
    NSGraphicsContext *graphicsContext = [NSGraphicsContext currentContext];
    [graphicsContext saveGraphicsState];
    CGContextRef context = [graphicsContext CGContext];
    CGContextBeginTransparencyLayerWithRect(context, findImageRect, nil);
    CGContextSetBlendMode(context, kCGBlendModeNormal);
    [find drawInRect:findImageRect fromRect:rectFromSize([find size]) operation:NSCompositingOperationSourceOver fraction:1];
    CGContextSetBlendMode(context, kCGBlendModeSourceIn);
    CGContextSetFillColorWithColor(context, [[NSColor textColor] CGColor]);
    CGContextFillRect(context, findImageRect);
    CGContextEndTransparencyLayer(context);

    [defaultText drawInRect:textRect withAttributes:nameAttributes];
  }
}

- (void)drawIconForObject:(QSObject *)object withFrame:(NSRect)cellFrame inView:(NSView *)controlView {
  NSImage *image = [object icon];
  NSString *iconName = nil;
  NSImageSymbolConfiguration *iconConfig = nil;
  if ([[image name] isEqualToString: @"defaultAction"]) {
    iconName = @"gearshape.circle";
  }
  else if ([[image name] isEqualToString: @"Find"]) {
    iconName = @"magnifyingglass";
  }
  else if ([[image name] isEqualToString: @"Object"]) {
    iconName = @"cube.transparent";
    iconConfig = [NSImageSymbolConfiguration configurationWithHierarchicalColor:[NSColor controlAccentColor]];
  }
  else if ([[image name] isEqualToString: @"ContactAddress"]) {
    iconName = @"mappin.circle";
  }
  else if ([[image name] isEqualToString: @"ContactEmail"]) {
    iconName = @"envelope.circle";
  }
  else if ([[image name] isEqualToString: @"ContactPhone"]) {
    iconName = @"phone.circle";
  }
  else if ([[image name] isEqualToString: @"DefaultBookmarkIcon"]) {
    iconName = @"link.circle";
  }
  else if ([[image name] isEqualToString: @"Catalog"]) {
    iconName = @"sparkles.rectangle.stack";
  }
  else if ([[image name] isEqualToString: @"Triggers"]) {
    iconName = @"bolt.fill";
  }

  
  if (iconName != nil) {
    NSImage *newIcon = [NSImage imageWithSystemSymbolName:iconName accessibilityDescription:[image name]];
    
    if (iconConfig == nil) {
      NSArray *colors = [NSArray arrayWithObjects:[NSColor textColor], [NSColor controlAccentColor], nil];
      iconConfig = [NSImageSymbolConfiguration configurationWithPaletteColors:colors];
    }

    QSObject *newObject = [QSObject objectWithName:[object name]];
    [newObject setIcon:[newIcon imageWithSymbolConfiguration:iconConfig]];
    [newObject setIconLoaded:[object iconLoaded]];
    return [super drawIconForObject: newObject withFrame:cellFrame inView:controlView];
  }
  
  [super drawIconForObject: object withFrame:cellFrame inView:controlView];
}

@end
