//
//  GPSTrack.m
//  DrivoMeter
//
//  Created by Mobi on 2/7/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#import "GPSTrack.h"
#import <CoreLocation/CoreLocation.h>
#import "Constants.h"

#define kUpdateErrorGPSOff      0

@interface GPSTrack (Private)

- (BOOL)isValidLocation:(CLLocation *)newLocation withOldLocation:(CLLocation *)oldLocation;

@end
@implementation GPSTrack

@synthesize locationManager = locationManager_;
@synthesize delegate = delegate_;
@synthesize currentDistance = currentDistance_;
@synthesize locationManagerStart_ = locationManagerStart_;


- (void)startUpdatingDistance {
  
  CLLocationManager *newManager = [[CLLocationManager alloc] init];
  [self setLocationManager:newManager];
  [locationManager_ setDelegate:self];  
  [locationManager_ setDistanceFilter:10];
  [locationManager_ setDesiredAccuracy:kCLLocationAccuracyBestForNavigation];
  [locationManager_ startUpdatingLocation];
  
  [self setLocationManagerStart_:[NSDate date]];
}

- (void)stopUpdatingDistance {
  [locationManager_ stopUpdatingLocation];
  [self setCurrentDistance:0.0f];
  [self.delegate updateDistance:currentDistance_];
}

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
  
  MSLog(@"newLocation %@", newLocation);
  
  if (![self isValidLocation:newLocation withOldLocation:oldLocation]) {
    return;
  }
  
  double distanceBetween = [newLocation distanceFromLocation:oldLocation];
  currentDistance_ += distanceBetween;
  [self.delegate updateDistance:(currentDistance_/1000.0)];
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
  MSLog(@"location manager failed with error %@", error);
  if (error.code == kUpdateErrorGPSOff) {
    [self.delegate updatingDistanceFailed];
    [self stopUpdatingDistance];
  }  
}

- (BOOL)isValidLocation:(CLLocation *)newLocation withOldLocation:(CLLocation *)oldLocation 
{
  // filter out nil locations
  if (!newLocation){
    return NO;
  }
  // filter out points by invalid accuracy
  if (newLocation.horizontalAccuracy < 0 || newLocation.horizontalAccuracy > 20.0f){
    return NO;
  }
  // filter out points that are out of order
  NSTimeInterval secondsSinceLastPoint = [newLocation.timestamp 
                                          timeIntervalSinceDate:oldLocation.timestamp];
  if (secondsSinceLastPoint < 0){
    return NO;
  }
  // filter out points created before the manager was initialized
  
  NSTimeInterval secondsSinceManagerStarted = [newLocation.timestamp 
                                               timeIntervalSinceDate:locationManagerStart_];
  if (secondsSinceManagerStarted < 0){
    return NO;
  }
  
  if ([newLocation distanceFromLocation:oldLocation] < 0) { 
    return NO; 
  }
  // newLocation is good to use
  return YES;
} 

@end
