//  Created by Joe Becker on 3/7/05.
//  Copyright 2005 __MyCompanyName__. All rights reserved.

#import "GraphView.h"
#import "TrackingGraphView.h"
#import "Segment.h"
#import "Label.h"
#import "Controller.h"
#import "defaults.h"

#import "GmtShipTrack.h"
#import "GmtShipTrackRecord.h"

@implementation GraphView


+(void)initialize
{
    NSUserDefaults *defs         = [NSUserDefaults standardUserDefaults];
    NSMutableDictionary *appDefs = [NSMutableDictionary dictionary];
	
	// Defaults
    [appDefs setObject:@"0.50"  forKey:GP_xstep];
    [appDefs setObject:@"0"     forKey:GP_xmin];
    [appDefs setObject:@"360."  forKey:GP_xmax];
    [appDefs setObject:@"-8000" forKey:GP_ymin];
    [appDefs setObject:@"+0"    forKey:GP_ymax];
    [appDefs setObject:@"Use File/Open" forKey:GP_Formula];
	
    [defs registerDefaults:appDefs];
}

- (void)awakeFromNib
{
    NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
	
    [xminCell  setObjectValue:[defs objectForKey:GP_xmin]];
    [xmaxCell  setObjectValue:[defs objectForKey:GP_xmax]];
    [xstepCell setObjectValue:[defs objectForKey:GP_xstep]];
    [yminCell  setObjectValue:[defs objectForKey:GP_ymin]];
    [ymaxCell  setObjectValue:[defs objectForKey:GP_ymax]];
	
    [formulaField setObjectValue:[defs objectForKey:GP_Formula]];
}

- (void)dealloc
{
    [displayList release];
    [super dealloc];
}

- (void)gotData:(id)sender
{
	// stub for dataView, navView etc to use.
}

- (IBAction)graph:(id)sender
{	
	// set instance variables from the form
	[self getFormAndScaleView];
	
	// Check the parameters of the graph
	if (xmax < xmin || ymax < ymin){
        NSRunAlertPanel( nil, @"Invalid min/max combination", @"OK", nil, nil);
		return;
    }
	
    if ( xstep <= 0 ) {
        NSRunAlertPanel(0, @"The step size must be positive", @"OK", nil, nil);
        return;
    }
	
	// Delete everything in the old display list and make a new one...
    [self clear];
	
    // Display the axes
    [self addAxesFrom:NSMakePoint(-1000*1000,0.0)
                   to:NSMakePoint(+1000*1000,0.0) ];
    [self addAxesFrom:NSMakePoint(0.0,-1000*1000)
                   to:NSMakePoint(0.0,+1000*1000) ];
	
    first = YES;
	[self gotData:sender];
}

- initWithFrame:(NSRect)frame
{
    [super initWithFrame:frame];
	displayList = [[NSMutableArray alloc] init];

	// The notification below causes the getFormAndScaleView
    // method to be invoked whenever this view is resized.
    [ [NSNotificationCenter defaultCenter]
                    addObserver:self
                       selector:@selector(getFormAndScaleView)
                           name:NSViewFrameDidChangeNotification
                         object:self];

	return self;
}

- (void)clear
{
    [displayList removeAllObjects];
    [self setNeedsDisplay:YES];
}

- (void)addGraphElement:(id)element
{
    [displayList addObject:element];
	[self setNeedsDisplayInRect:[element bounds]];
}

- (void)getForm
{
    xstep = [xstepCell doubleValue];
	xmin  = [xminCell doubleValue];
	xmax  = [xmaxCell doubleValue];
    ymin  = [yminCell doubleValue];
    ymax  = [ymaxCell doubleValue];	
	
	[[controller gmtShipTrack] setCarterCount:[carterCountCell doubleValue]];	
}

- (void)getFormAndScaleView
{
	[self getForm];
    [self setBounds:(NSMakeRect(xmin, ymin, xmax-xmin, ymax-ymin) ) ];
    [self setNeedsDisplay:YES];
}


-(BOOL)isOpaque { return NO; }   // Because DataView, and StatView are opaque

-(void)drawRect:(NSRect )rect
{
    id obj=nil;
    NSEnumerator *en;
	
    [[NSColor whiteColor] set];
    NSRectFill(rect);
	
	//NSSize sz = [self convertSize:NSMakeSize(1,1) fromView:nil];
	//[NSBezierPath setDefaultLineWidth:MIN(sz.width,sz.height)];
	[NSBezierPath setDefaultLineWidth:0.];
	
    en = [displayList objectEnumerator];
    while (obj = [en nextObject]) {
		if (NSIntersectsRect(rect,[obj bounds])) {
			[obj stroke];
		}
    }
}

- (void)addAxesFrom:(NSPoint)pt1 to:(NSPoint)pt2
{
    Segment *seg = [[Segment alloc] initFrom:pt1 to:pt2 view:self record:nil];
    [seg  setTag:AXES_TAG];
    [seg  autorelease];
    [self addGraphElement:seg];
}

- (void)setFormula:(NSString *)aString
{
    [formulaField setStringValue:aString];
}

- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
{
    return NO;
}

- (id)zoomToDataExtent:(GmtShipTrack *)gmtShipTrack :(int)field
{
	NSRect extent = [gmtShipTrack extent:field];
	
	// could use any record in GmtShipTrack, we just want index of predicted...
	int predictedField = [[gmtShipTrack max] predictedFieldForActualField:field];
	
	NSRect predictedExtent = [gmtShipTrack extent:predictedField];
	
	[(TrackingGraphView *)self zoomToRect: NSUnionRect(extent, predictedExtent) ];
	
	return self;
}

- (id)zoomToDataExtent:(GmtShipTrack *)gmtShipTrack
{
	return [self zoomToDataExtent:gmtShipTrack:[[dataTypeField selectedItem] tag]];
}

- (id)zoomToVerticalExtent:(GmtShipTrack *)gmtShipTrack :(int)field
{
	NSRect extent;
	NSRect combinedExtent;
	// could use any record in GmtShipTrack, we just want index of predicted...
	int predictedField = [[gmtShipTrack max] predictedFieldForActualField:field];
	
	float minTime = [xminCell  doubleValue];
	float maxTime = [xmaxCell  doubleValue];
	
	float minData = [[gmtShipTrack min] data:field];
	float maxData = [[gmtShipTrack max] data:field];
	
	// need to be careful; predicted time, and lat and so on is just 0, so you get zero size predictedExtent.
	
	if (maxData > minData) {
		extent = NSMakeRect(minTime, minData, maxTime-minTime, maxData-minData);
		combinedExtent = extent;
	} else {
		[yminCell  setDoubleValue:0];
		[ymaxCell  setDoubleValue:0];
		return self;
	}
	
	minData = [[gmtShipTrack min] data:predictedField];
	maxData = [[gmtShipTrack max] data:predictedField];
		
	if (maxData > minData) {
		NSRect predictedExtent = NSMakeRect(minTime, minData, maxTime-minTime, maxData-minData);
		combinedExtent = NSUnionRect(extent, predictedExtent);
	}
	
	[(TrackingGraphView *)self zoomToRect:combinedExtent];

	return self;
}

- (id)zoomToVerticalExtent:(GmtShipTrack *)gmtShipTrack
{
	return [self zoomToVerticalExtent:gmtShipTrack:[[dataTypeField selectedItem] tag]];
}

- (id) carterCountCell {
	return carterCountCell;
}

// Services

- (void)setRunningAsService:(BOOL)aFlag
{
    runningAsService = aFlag;
}

// Drag-and-Drop

- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)flag
{
    if (flag==YES) return NSDragOperationNone;
    return NSDragOperationCopy;
}

@end
