//
//  MPT_Speedometer.m
//  Enjoyment
//
//  Created by Andrew Salamon on 4/26/09.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//

#import "MPT_Speedometer.h"

#import <math.h>

@interface MPT_Speedometer(PrivateMethods)
- (void)drawArrowFrom:(NSPoint)arrowOrigin length:(float)arrowLength angle:(float)arrowAngle;
- (void)fillGoodArcFrom:(NSPoint)arrowOrigin length:(float)arrowLength angle:(float)arrowAngle;
@end

@implementation MPT_Speedometer

- (id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self setMin:-8.0];
        [self setMax:2.0];
        [self setCenter:-3.0];
        [self setCurValue:[self center]];
        [self setNoValue:YES];
    }
    return self;
}

- (void)drawRect:(NSRect)rect
{
//    [super drawRect:rect];
    
    // Draw an arc from bottom left to bottom right.
    float buffer = 2.0;
    NSRect myFrame = [self frame];
    float mySize = myFrame.size.height - (buffer*2.0);
//    float halfWidth = myFrame.size.width / 2.0;
//    NSPoint arcCenter = NSMakePoint( halfWidth, 0.0 );
    
    NSBezierPath *path = [NSBezierPath bezierPath];
    NSRect halfRect = NSMakeRect( buffer, -mySize, mySize*2.0, mySize*2.0);
    [path appendBezierPathWithOvalInRect:halfRect];
    [path moveToPoint:NSMakePoint( buffer, buffer/2.0 )];
    [path lineToPoint:NSMakePoint( (mySize*2.0)+buffer, buffer/2.0 )];
//    [[NSColor greenColor] set];
    [path stroke];

    float range = [self max] - [self min];
    float angle = (([self max] - [self center]) / range) * 180.0;
    if( (angle > 180.0) || (angle < 0) )
        NSLog( @"Wonky data (2)." );
    [[NSColor greenColor] set];
    [self fillGoodArcFrom:NSMakePoint( mySize, 0.0 ) length:mySize angle:angle];
    
    if( [self noValue] )
        return;
    
    angle = (([self max] - [self curValue]) / range) * 180.0;
    if( (angle > 180.0) || (angle < 0) )
        NSLog( @"Wonky data." );
    
    [[NSColor blackColor] set];
    [self drawArrowFrom:NSMakePoint( mySize, 0.0 ) length:mySize angle:angle];
}

- (void)fillGoodArcFrom:(NSPoint)arrowOrigin length:(float)arrowLength angle:(float)arrowAngle
{
    static float mLineWidth = 1.0;
    //    static float L_PI = 3.14159265358979323846264338327;
    static float DEGREES_TO_RADIANS = 3.14159265358979323846264338327 / 180.0;
    
    NSPoint arrowTip;
    float deltaX = 0.0;
    float deltaY = 0.0;
    
	arrowOrigin.x += 2.0;
	arrowOrigin.y += 2.0;
	arrowLength -= 2.0;
    NSPoint bottomRight = arrowOrigin;
    bottomRight.x += arrowLength;
    
    
    // Set the arrow colour
    //[[NSColor blackColor] set];
    
    // Create the path that will contain the arrow drawing instructions
    // and begin drawing.
    NSBezierPath* arrowPath = [NSBezierPath bezierPath];
    [arrowPath setLineWidth: mLineWidth];
    [arrowPath moveToPoint: arrowOrigin];
    
    [arrowPath lineToPoint: bottomRight];

    // Calculate the arrow tip location from the polar coordinates
    deltaX = arrowLength*cos(arrowAngle*DEGREES_TO_RADIANS);  // Radians
    deltaY = arrowLength*sin(arrowAngle*DEGREES_TO_RADIANS);
    arrowTip.x = arrowOrigin.x + deltaX;
    arrowTip.y = arrowOrigin.y + deltaY;
    
//    [arrowPath appendBezierPathWithArcFromPoint:bottomRight toPoint:arrowTip radius:arrowLength];
    [arrowPath appendBezierPathWithArcWithCenter:arrowOrigin radius:arrowLength startAngle:0.0 endAngle:arrowAngle];
    //[arrowPath lineToPoint: bottomRight];
    //[arrowPath lineToPoint: arrowTip];
    
    [arrowPath closePath];
    
    // Draw the arrow
    [arrowPath stroke];
    [arrowPath fill];
}

- (void)drawArrowFrom:(NSPoint)arrowOrigin length:(float)arrowLength angle:(float)arrowAngle
{
    static float mLineWidth = 2.0;
//    static float L_PI = 3.14159265358979323846264338327;
    static float DEGREES_TO_RADIANS = 3.14159265358979323846264338327 / 180.0;
    static float mArrowHeadAspectRatio = 0.4;

    float mArrowHeadLength = floor(arrowLength / 10.0);
    NSPoint arrowTip;
    NSPoint arrowHeadBase;
    NSPoint arrowHeadWing1;
    NSPoint arrowHeadWing2;
    float deltaX = 0.0;
    float deltaY = 0.0;
    
    float deltaXBase = 0.0;
    float deltaYBase = 0.0;
    
    float headToShaftRatio = 0.0;
    float deltaXWing = 0.0;
    float deltaYWing = 0.0;
        
    // Set the arrow colour
    //[[NSColor blackColor] set];
        
    // Create the path that will contain the arrow drawing instructions
    // and begin drawing.
    NSBezierPath* arrowPath = [NSBezierPath bezierPath];
    [arrowPath setLineWidth: mLineWidth];
    [arrowPath moveToPoint: arrowOrigin];
    
    // Calculate the arrow tip location from the polar coordinates
    deltaX = arrowLength*cos(arrowAngle*DEGREES_TO_RADIANS);  // Radians
    deltaY = arrowLength*sin(arrowAngle*DEGREES_TO_RADIANS);
    arrowTip.x = arrowOrigin.x + deltaX;
    arrowTip.y = arrowOrigin.y + deltaY;
    
    // Define the arrow shaft
    [arrowPath lineToPoint: arrowTip];
    
    // Calculate the location of the base of the arrow head
    headToShaftRatio = mArrowHeadLength/arrowLength;
    deltaXBase = headToShaftRatio*deltaX;
    deltaYBase = headToShaftRatio*deltaY;
    arrowHeadBase.x = arrowTip.x - deltaXBase;  
    arrowHeadBase.y = arrowTip.y - deltaYBase;  
    
    // Calculate the wing tips of the arrow head
    deltaXWing = mArrowHeadAspectRatio*deltaXBase;
    deltaYWing = mArrowHeadAspectRatio*deltaYBase;
    arrowHeadWing1.x = arrowHeadBase.x - deltaYWing ;   
    arrowHeadWing1.y = arrowHeadBase.y + deltaXWing ;   
    arrowHeadWing2.x = arrowHeadBase.x + deltaYWing ;   
    arrowHeadWing2.y = arrowHeadBase.y - deltaXWing ;   
    
    // Define the arrow head wings
    [arrowPath moveToPoint: arrowTip];
    [arrowPath lineToPoint: arrowHeadWing1];
//    [arrowPath moveToPoint: arrowTip];
    [arrowPath lineToPoint: arrowHeadWing2];
    
    // Draw the arrow
    [arrowPath stroke];
    [arrowPath fill];
}
      
- (float)min {
    return min;
}
- (void)setMin:(float)value {
    if (min != value) {
        min = value;
        [self setNeedsDisplay:YES];
    }
}

- (float)center {
    return center;
}
- (void)setCenter:(float)value {
    if (center != value) {
        center = value;
        [self setNeedsDisplay:YES];
    }
}

- (float)max {
    return max;
}
- (void)setMax:(float)value {
    if (max != value) {
        max = value;
        [self setNeedsDisplay:YES];
    }
}

- (float)curValue {
    return curValue;
}
- (void)setCurValue:(float)value
{
    if (curValue != value)
    {
        if( value > [self max] )
        {
            NSLog( @"Value above max in Enjoyment plugin." );
            value = [self max];
        }
        if( value < [self min] )
        {
            NSLog( @"Value below min in Enjoyment plugin." );
            value = [self min];
        }
        curValue = value;
        [self setNoValue:NO];
        [self setNeedsDisplay:YES];
    }
}

- (BOOL)noValue {
    return noValue;
}

- (void)setNoValue:(BOOL)value {
    if (noValue != value) {
        noValue = value;
        [self setNeedsDisplay:YES];
    }
}
@end
