//
//  ColorPlotWindowController.m
//  SnoopX
//

#import "ColorPlotWindowController.h"

static const CGFloat kAdjacencyGap = 8.0;

@implementation ColorPlotWindowController

@synthesize plotDelegate;
@synthesize plotMode;

- (instancetype) initWithMode:(ColorPlotMode)mode
{
	// Initial content rect is a placeholder; -repositionRelativeToWindow: sets the real size.
	NSRect contentRect = NSMakeRect(0, 0, 480, 240);

	NSUInteger styleMask = NSWindowStyleMaskTitled
	                     | NSWindowStyleMaskClosable
	                     | NSWindowStyleMaskResizable
	                     | NSWindowStyleMaskMiniaturizable;

	NSWindow *win = [[NSWindow alloc] initWithContentRect:contentRect
	                                            styleMask:styleMask
	                                              backing:NSBackingStoreBuffered
	                                                defer:NO];
	[win setReleasedWhenClosed:NO];
	[win setBackgroundColor:[NSColor blackColor]];
	[win setOpaque:YES];

	self = [super initWithWindow:win];
	[win release];
	if (self) {
		plotMode = mode;
		closingProgrammatically = NO;
		plotDelegate = nil;

		plotView = [[ColorPlotView alloc] initWithFrame:[[win contentView] bounds]];
		[plotView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
		[plotView setPlotMode:mode];
		[[win contentView] addSubview:plotView];

		// Allow free user resizing — no aspect-ratio lock. The drawing code
		// adapts to whatever bounds the user gives it. A move or resize of the
		// snoop window resets size + position via -repositionRelativeToWindow:.
		// Set a minimum content size so the window can't be squeezed to nothing.
		[[self window] setContentMinSize:NSMakeSize(200.0, 80.0)];

		[win setDelegate:self];
		[self updateTitle];
	}
	return self;
}

- (void) dealloc
{
	// Make sure AppKit doesn't keep a dangling reference to us as the window's delegate.
	NSWindow *win = [self window];
	if ([win delegate] == self) {
		[win setDelegate:nil];
	}
	[plotView release];
	[super dealloc];
}

- (void) updateTitle
{
	NSString *title;
	switch (plotMode) {
		case ColorPlotModeWaveform:   title = @"SnoopX — Color Waveform";   break;
		case ColorPlotModeHistogram:  title = @"SnoopX — Color Histogram";  break;
		default:                      title = @"SnoopX — Color Vectorscope"; break;
	}
	[[self window] setTitle:title];
}

- (void) setMode:(ColorPlotMode)mode
{
	if (plotMode == mode) return;
	plotMode = mode;
	[plotView setPlotMode:mode];
	[self updateTitle];
}

- (void) updateSnapshot:(SnoopxFrameSnapshot)newSnap
{
	[plotView setSnapshot:newSnap];
}

- (void) updateCursorR:(float)r G:(float)g B:(float)b
{
	[plotView setCursorR:r G:g B:b];
}

- (void) repositionRelativeToWindow:(NSWindow*)mainWindow
{
	if (!mainWindow) return;

	NSRect mainFrame = [mainWindow frame];
	NSScreen *screen = [mainWindow screen];
	if (!screen) screen = [NSScreen mainScreen];
	NSRect screenVisible = [screen visibleFrame];

	// All plots: window width = snoop window width.
	// Vectorscope:  square.
	// Waveform:     chart-area height = 2 × h-plot canvas (snoop content × 2/3).
	// Histogram:    chart-area height = 1 × h-plot canvas (snoop content × 1/3).
	NSRect target;
	target.size.width = mainFrame.size.width;
	if (plotMode == ColorPlotModeVectorscope) {
		target.size.height = mainFrame.size.width;
	} else {
		CGFloat snoopContentH = [[mainWindow contentView] frame].size.height;
		CGFloat chartH;
		if (plotMode == ColorPlotModeHistogram) {
			chartH = snoopContentH / 3.0;
			if (chartH > 256.0) chartH = 256.0;
			if (chartH < 60.0)  chartH = 60.0;
		} else {
			chartH = snoopContentH * 2.0 / 3.0;
			if (chartH > 512.0) chartH = 512.0;
			if (chartH < 120.0) chartH = 120.0;
		}
		target.size.height = chartH + ColorPlotWaveformTopMargin + ColorPlotWaveformBottomMargin;
	}
	target.origin.x = mainFrame.origin.x;

	// Place above the snoop window, with a small gap; if no room, below; else centered on-screen.
	CGFloat above = mainFrame.origin.y + mainFrame.size.height + kAdjacencyGap;
	CGFloat below = mainFrame.origin.y - kAdjacencyGap - target.size.height;
	CGFloat screenTop = screenVisible.origin.y + screenVisible.size.height;

	if (above + target.size.height <= screenTop) {
		target.origin.y = above;
	} else if (below >= screenVisible.origin.y) {
		target.origin.y = below;
	} else {
		target.origin.y = screenTop - target.size.height;
		if (target.origin.y < screenVisible.origin.y) target.origin.y = screenVisible.origin.y;
	}

	// Clamp horizontally so the window stays on the visible screen.
	CGFloat screenRight = screenVisible.origin.x + screenVisible.size.width;
	if (target.origin.x + target.size.width > screenRight) {
		target.origin.x = screenRight - target.size.width;
	}
	if (target.origin.x < screenVisible.origin.x) target.origin.x = screenVisible.origin.x;

	[[self window] setFrame:target display:YES animate:NO];
}

- (void) closeProgrammatically
{
	closingProgrammatically = YES;
	[[self window] close];
	closingProgrammatically = NO;
}

#pragma mark - NSWindowDelegate

- (void) windowWillClose:(NSNotification*)note
{
	if (closingProgrammatically) return;
	id<ColorPlotWindowControllerDelegate> d = plotDelegate;
	if (d && [d respondsToSelector:@selector(colorPlotWindowDidUserClose:)]) {
		[d colorPlotWindowDidUserClose:self];
	}
}

@end
