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

#import "DataView.h"
#import "StatView.h"
#import "NavigationView.h"
#import "DataController.h"
#import "Segment.h"
#import "Tick.h"

@implementation DataView

- (NSPoint)dataPtAtRecord:(GmtShipTrackRecord *)obj
{
	float timeAtCursor = [obj time] - [[[[controller gmtShipTrack] gmtShipTrackRecordList] objectAtIndex:0] time];
	
	return NSMakePoint(timeAtCursor, [obj data:[self dataTypeBeingPlotted]]);
}

- (void)mouseMoved:(NSEvent *)theEvent
{
	tagOfInterest = MEASURED_TAG | PREDICTED_TAG;
	
	distanceToLine = 10.;
	hotSpotIsCenterOfSegment = NO;
	[super mouseMoved:theEvent];
	
	float timeAtCursor = xAtCursor;
	
	if (hotSpotFound) 
	{
		[(NavigationView *)	[[controller navController]  graphView] moveCursorToRecord:objAtCursor];
		[(StatView *)		[[controller statController] graphView] moveCursorToRecord:objAtCursor];
		[tCell setStringValue:[NSString stringWithFormat:@"t: %12.5f", timeAtCursor] ];
	} 
	else
	{
		[(NavigationView *)	[[controller navController]	 graphView] dataMissing];		
		[(StatView *)		[[controller statController] graphView] dataMissing];
		[tCell setStringValue:@"t: no t seg"];
	}
}	

- (void)addDataToDisplayList:(int)dataField
{
	// This where the data read from the file is added to displayList, but not plotted.
	
	GmtShipTrackRecord	*obj = [[[controller gmtShipTrack] gmtShipTrackRecordList] objectAtIndex:0];
	NSEnumerator		*en = [[[controller gmtShipTrack] gmtShipTrackRecordList] objectEnumerator];
	
	double minTime = 0;	
	first = YES;
	
	// avoid silly stuff when appp launches
	
	if ([[[controller gmtShipTrack] gmtShipTrackRecordList] count]) minTime = [obj time];
	
	
	while (obj = [en nextObject]) {
		
		NSPoint dataPt = NSMakePoint([obj time]-minTime, [obj data:dataField]);
		
		if (![[controller gmtShipTrack] isNaN:dataPt.y])
		{
			if (!first)
			{
				Segment *seg = [[[Segment alloc] initFrom:lastPt to:dataPt view:self record:obj] autorelease];
				//Tick *seg = [[[Tick alloc] initFrom:lastPt to:dataPt view:self record:obj] autorelease];
				
				if (([obj flag] & ~1) != 0  && 
					dataField != GS_FIELD &&
					dataField != PT_FIELD && 
					dataField != PM_FIELD
					) 
				{
					[seg  setLineType:SOLID_LINE]; 
					[seg  setTag:FLAG_TAG];
				}
				else					
				{
					switch (dataField) {
						// ship data
						case GF_FIELD : 
						case GT_FIELD : 
						case TC_FIELD : 
						case CC_FIELD : 
						case TT_FIELD : 
						case MA_FIELD : 
							[seg  setTag:MEASURED_TAG]; 
							[seg  setLineType:SOLID_LINE]; 
							break;
						default:
							// other data; i.e. predicted
							[seg  setTag:PREDICTED_TAG];
							[seg  setLineType:SOLID_LINE]; 
					}
				}
				[self addGraphElement:seg];
			}
			
			first = NO;			// No longer first
			lastPt = dataPt;	// Remember this point
		}
	}	
}

- (IBAction)changeDataPlotted:(id)sender
{
	int i = [[dataTypeField selectedItem] tag];
	
	switch (i) {
		case GF_FIELD : 
		case GT_FIELD : 
		case TC_FIELD : 
		case CC_FIELD : 
		case TT_FIELD : 
		case MA_FIELD : 
			dataTypeBeingPlotted = i;

			[self clear];

			float maxData = [[[controller gmtShipTrack] max] data:dataTypeBeingPlotted];
			float minData = [[[controller gmtShipTrack] min] data:dataTypeBeingPlotted];
			
			if ([[controller gmtShipTrack] isNaN:maxData]) {
				[yminCell  setDoubleValue:0];
				[ymaxCell  setDoubleValue:0];
				return;
			}
				
			[self graph:sender];
			[self zoomToFitVertical:self];
			break;
			
		default:
			NSRunAlertPanel(nil,@"DataController.m changedDataPlotted: User selected a unexpected data tag.",nil,nil,nil);
	}
	return;
}

- (void)gotData:(id)sender
{	
	[super gotData:sender];
	
	// Plot ship data selected in the window
	
	[self addDataToDisplayList:[self dataTypeBeingPlotted]];
	
	// Plot the satellite data that matches the selected ship data
	// could use any record in GmtShipTrack, we just want index of predicted...

	int predictedField = [[[controller gmtShipTrack] max] predictedFieldForActualField:[self dataTypeBeingPlotted]];
	
	if (predictedField != [self dataTypeBeingPlotted]) {
		[self addDataToDisplayList:predictedField];
	}
}

- (void)awakeFromNib
{
	[super awakeFromNib];
	dataTypeBeingPlotted = [[dataTypeField selectedItem] tag];
}

- (IBAction)pageToLast:(id)sender
{
	[self getForm];
	float tmp = [[[controller gmtShipTrack] max] time]-[[[controller gmtShipTrack] min] time];
	tmp -= xmax;
	[self pageBy:tmp:0];	
}

- (IBAction)zoomToSelection:(id)sender {
	[self zoomToRect:selectedRect];
}


- (IBAction)zoomToFit:(id)sender {
	[self zoomToDataExtent:[controller gmtShipTrack]];
}

- (IBAction)zoomToFitVertical:(id)sender {
	[self zoomToVerticalExtent:[controller gmtShipTrack]];
}

-(void)mouseDragged:(NSEvent *)theEvent
{
	[super mouseDragged:theEvent];
	weBeFlagging = YES;
	return;				
}

- (void)zoomBy:(double)xScale:(double)yScale
{	
	double xRange = (xmax - xmin) * xScale;
	double yRange = (ymax - ymin) * yScale;
	
	// for convenience avoid scrolling into negative time...
	
	xmin -= xRange; if (xmin < 0) xmin = 0.;
	xmax += xRange;
	ymin -= yRange;
	ymax += yRange;
	
	[xminCell  setDoubleValue:xmin];
	[xmaxCell  setDoubleValue:xmax];
	[yminCell  setDoubleValue:ymin];
	[ymaxCell  setDoubleValue:ymax];
	
	[self getFormAndScaleView];	
}

- (void)pageBy:(double)deltaX:(double)deltaY
{	
	// for convenience avoid scrolling into negative time...
	if (-deltaX > xmin)	deltaX = -xmin;
	xmin += deltaX; if (xmin < 0) xmin = 0.;
	xmax += deltaX;
	ymin += deltaY;
	ymax += deltaY;
	
	[xminCell  setDoubleValue:xmin];
	[xmaxCell  setDoubleValue:xmax];
	[yminCell  setDoubleValue:ymin];
	[ymaxCell  setDoubleValue:ymax];
	
	[self getFormAndScaleView];	
}


- (void)flagRect:(NSRect)rect:(int)op;
{
	NSEnumerator		*en = [[[controller gmtShipTrack] gmtShipTrackRecordList] objectEnumerator];
	GmtShipTrackRecord	*obj =[[[controller gmtShipTrack] gmtShipTrackRecordList] objectAtIndex:0];
	
	double minTime = [obj time];	
	BOOL flaggedAnything = NO;
	
	while (obj = [en nextObject]) {
		
		NSPoint dataPt = NSMakePoint([obj time]-minTime,[obj data:dataTypeBeingPlotted]);
		
		if (NSPointInRect(dataPt, rect))
		{
			flaggedAnything = YES;
			switch (op) {
				case  OR_FIELD:[obj setFlag:([obj flag] |  (1<<dataTypeBeingPlotted))]; break;
				case XOR_FIELD:[obj setFlag:([obj flag] ^  (1<<dataTypeBeingPlotted))]; break;
				case NOT_FIELD:[obj setFlag:([obj flag] & ~(1<<dataTypeBeingPlotted))]; break;
					
				default:
					NSRunAlertPanel(nil,@"DataController.m changedDataPlotted: User selected a unexpected data tag.",nil,nil,nil);
			}
		}
	}
	
	if (flaggedAnything) {
		[[[controller navController ] graphView] graph:self];
		[[[controller dataController] graphView] graph:self];
		[[[controller statController] graphView] graph:self];
	}
}

- (void)flag:(id)sender

{
	[self flagRect:selectedRect:OR_FIELD];
	[[controller gmtShipTrack] calculateSumsForStats];
	[(StatView *)[[controller statController] graphView] updateStatsFields];	
}

- (void)unflag:(id)sender
{
	[self flagRect:selectedRect:NOT_FIELD];
	[[controller gmtShipTrack] calculateSumsForStats];
	[(StatView *)[[controller statController] graphView] updateStatsFields];
}

- (void)toggleFlag:(id)sender
{
	[self flagRect:selectedRect:XOR_FIELD];
}

@end
