//
//  TripViewController.m
//  DrivoMeter
//
//  Created by Triin Uudam on 1/3/12.
//

#import "TripViewController.h"
#import "AddTripViewController.h"
#import "Constants.h"
#import "Database+Trips.h"
#import "Database+Odometer.h"
#import "CustomSegmentControl.h"
#import "MBProgressHUD.h"
#import "Trip.h"
#import "Database+Settings.h"
#import "Setting.h"

#define kUpdateErrorGPSOff      0

@interface TripViewController (Private) 

- (void)addTrip;
- (void)updateActionButton;
- (BOOL)isValidLocation:(CLLocation *)newLocation withOldLocation:(CLLocation *)oldLocation;
- (void)updateDistance;
- (void)stopUpdatingDistance;
- (void)updatingDistanceFailed;
- (void)clearTripValues;
- (void)endTripIsBusiness:(BOOL)isBusiness;
- (void)timerFireMethod:(NSTimer*)theTimer;
- (BOOL)isFirstTime;
- (void)showFirstTimeWarning;
- (BOOL)canShowUserLocation;
  
@end

@implementation TripViewController

@synthesize distanceTitleLabel = distanceTitleLabel_;
@synthesize distanceStateLabel = distanceStateLabel_;
@synthesize actionButton = actionButton_;
@synthesize database = database_;
@synthesize locationManager = locationManager_;
@synthesize isActive = isActive_;
@synthesize currentTrip = currentTrip_;
@synthesize currentDistance = currentDistance_;
@synthesize mapView = mapView_;
@synthesize locationManagerStart = locationManagerStart_;
@synthesize futureAlert = futureAlert_;
@synthesize distanceInBackground = distanceInBackground_;
@synthesize backgroundTimer = backgroundTimer_;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
  self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
  if (self) {
    // Custom initialization
  }
  return self;
}

- (void)didReceiveMemoryWarning
{
  // Releases the view if it doesn't have a superview.
  [super didReceiveMemoryWarning];
  
  // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
  [super viewDidLoad];
  // Do any additional setup after loading the view from its nib.
}

- (void)viewDidUnload
{
  [super viewDidUnload];
  // Release any retained subviews of the main view.
  // e.g. self.myOutlet = nil;
}

- (void)viewWillAppear:(BOOL)animated {
  [super viewWillAppear:animated];
  [[UIApplication sharedApplication] setDelegate:self];
  
  [distanceTitleLabel_ setText:NSLocalizedString(@"trip.view.distance.title.label", nil)];
  
  [self updateActionButton];
  
  //UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"trip.view.add.trip.button.title", nil) style:UIBarButtonItemStylePlain target:self action:@selector(addTrip)];
  UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addTrip)];
  [addButton setTintColor:[UIColor orangeColor]];
  [self.navigationItem setRightBarButtonItem:addButton];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
  // Return YES for supported orientations
  return (interfaceOrientation == UIInterfaceOrientationPortrait);
}



#pragma mark - all kinds of action button update thingies :S

- (void)addTrip {
  AddTripViewController *controller = [[AddTripViewController alloc] init];
  [controller setDatabase:database_];
  UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller];
  [self.navigationController presentModalViewController:navController animated:TRUE];
}

- (void)clearTripValues {
  [mapView_ removeOverlays:[mapView_ overlays]];
  [self setCurrentDistance:0.0f];
  [self updateDistance];
}

- (void)endTripWithPurpose:(NSString *)purpose {
  [database_ endTrip:currentTrip_ withDistance:[distanceStateLabel_.text doubleValue] purpose:purpose];
  [self stopUpdatingDistance];
}

- (IBAction)actionButtonPressed:(id)sender {
  if ([self isFirstTime]) {
    [self showFirstTimeWarning];
  }
  if (!isActive_) {
    [self clearTripValues];
    
    CLLocationManager *newManager = [[CLLocationManager alloc] init];
    [self setLocationManager:newManager];
    [locationManager_ setDelegate:self];  
    [locationManager_ setDistanceFilter:10];
    [locationManager_ setDesiredAccuracy:kCLLocationAccuracyBestForNavigation];
    [locationManager_ startUpdatingLocation];
    if ([self canShowUserLocation]) {
      [MBProgressHUD showHUDAddedTo:mapView_ animated:YES];
      mapView_.showsUserLocation = YES;  
      [mapView_ setUserTrackingMode:MKUserTrackingModeFollow animated:NO];
    }    
    [self setLocationManagerStart:[NSDate date]];
    [self setIsActive:TRUE];
    [self setCurrentTrip:[database_ startCurrentTrip]];
    [[UIApplication sharedApplication] setIdleTimerDisabled:YES];
  }
  else {    
    
    UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil 
                                                             delegate:self 
                                                    cancelButtonTitle:NSLocalizedString(@"trip.view.action.sheet.continue.button.title", nil) 
                                               destructiveButtonTitle:nil 
                                                    otherButtonTitles:NSLocalizedString(@"trip.view.action.sheet.save.business.title", nil), 
                                  NSLocalizedString(@"trip.view.action.sheet.save.private.title", nil), 
                                  NSLocalizedString(@"trip.view.action.sheet.cancel.button.title", nil),
                                   nil];
    [actionSheet showFromTabBar:self.tabBarController.tabBar];    
  } 
  [self updateActionButton];
}

- (void)updateActionButton {
  if (isActive_) {
    [actionButton_ setTitle:NSLocalizedString(@"trip.view.action.button.finish", nil) forState:UIControlStateNormal];
    [actionButton_ setBackgroundImage:[UIImage imageNamed:@"redButton1"] forState:UIControlStateNormal];
  }
  else {
    [actionButton_ setTitle:NSLocalizedString(@"trip.view.action.button.start", nil) forState:UIControlStateNormal];
    [actionButton_ setBackgroundImage:[UIImage imageNamed:@"greenButton1"] forState:UIControlStateNormal];
  }
}

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {

  UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:NSLocalizedString(@"trip.view.purpose.alert.title", nil) delegate:self cancelButtonTitle:NSLocalizedString(@"trip.view.alert.later.button.title", nil) otherButtonTitles:NSLocalizedString(@"button.title.OK", nil), nil];
  alert.alertViewStyle = UIAlertViewStylePlainTextInput;
  switch (buttonIndex) {
    case 0:      
      [alert show];
      [currentTrip_ setIsBusinessValue:YES];
      break;
    case 1:
      [alert show];
      [currentTrip_ setIsBusinessValue:NO];
      break;
    case 2:
      [database_ cancelTrip:currentTrip_];
      [self stopUpdatingDistance];
      [self clearTripValues];
      break;
    default:
      break;
  }
  [self updateActionButton];
}

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
  [self endTripWithPurpose:[[alertView textFieldAtIndex:0] text]];
}

- (void)updateDistance {
  MSLog(@"update distance %.2f", currentDistance_);
  [distanceStateLabel_ setText:[NSString stringWithFormat:NSLocalizedString(@"trip.view.distance.state.label.text", nil), currentDistance_]];
}

- (void)stopUpdatingDistance {

  [locationManager_ stopUpdatingLocation];
  [self setLocationManager:nil];
  mapView_.showsUserLocation = NO;
  [mapView_ setUserTrackingMode:MKUserTrackingModeNone];
  crumbs_ = nil;
  crumbView_ = nil;
  
  [[UIApplication sharedApplication] setIdleTimerDisabled:NO];
  [self setIsActive:FALSE];
  [self updateActionButton];
}

- (void)updatingDistanceFailed {
  UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:NSLocalizedString(@"trip.view.distance.failed.alert.message", nil) delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
  [alert show];
  [self actionButtonPressed:nil];
}

#pragma mark - Map View and Location Manager Delegate Methods

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
  
  [MBProgressHUD hideHUDForView:mapView_ animated:YES];
  if (![self isValidLocation:newLocation withOldLocation:oldLocation]) {
    MSLog(@"is not valid");
    return;
  }
  
  double distanceBetween = [newLocation distanceFromLocation:oldLocation];
  currentDistance_ += distanceBetween/1000.0;
  [self updateDistance];
  if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateBackground) {
    distanceInBackground_ += distanceBetween;
  }

  if ([self canShowUserLocation]) {
    if (!crumbs_) {
      crumbs_ = [[CrumbPath alloc] initWithCenterCoordinate:newLocation.coordinate];
      [mapView_ addOverlay:crumbs_];
      
    }
    else {
      MKMapRect updateRect = [crumbs_ addCoordinate:newLocation.coordinate];
      
      if (!MKMapRectIsNull(updateRect))
      {
        // There is a non null update rect.
        // Compute the currently visible map zoom scale
        MKZoomScale currentZoomScale = (CGFloat)(mapView_.bounds.size.width / mapView_.visibleMapRect.size.width);
        // Find out the line width at this zoom scale and outset the updateRect by that amount
        CGFloat lineWidth = MKRoadWidthAtZoomScale(currentZoomScale);
        updateRect = MKMapRectInset(updateRect, -lineWidth, -lineWidth);
        // Ask the overlay view to update just the changed area.
        [crumbView_ setNeedsDisplayInMapRect:updateRect];
      }
    }
  }  
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
  MSLog(@"location manager failed with error %@", error);
 //TODO triin: this fails sometimes
}

- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
  if (!crumbView_)
  {
    crumbView_ = [[CrumbPathView alloc] initWithOverlay:overlay];
  }
  return crumbView_;
}

- (void)mapViewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error {
  MSLog(@"map loading failed with error %@", error);
}

- (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;
} 

#pragma mark - Application Delegate Methods

- (void)applicationWillResignActive:(UIApplication *)application {
  MSLog(@"application enters background");
  [mapView_ setDelegate:nil];
  if (isActive_) {
//    futureAlert_ = [[UILocalNotification alloc] init];
//    futureAlert_.fireDate = [NSDate dateWithTimeIntervalSinceNow:10];
//    futureAlert_.timeZone = [NSTimeZone defaultTimeZone];
//    futureAlert_.repeatInterval = NSHourCalendarUnit;
//    futureAlert_.alertBody = @"Sõit on endiselt aktiivne";
//    [[UIApplication sharedApplication] scheduleLocalNotification:futureAlert_];
    backgroundTimer_ = [NSTimer scheduledTimerWithTimeInterval:7200 target:self selector:@selector(timerFireMethod:) userInfo:nil repeats:NO];

       
  }    
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
  [mapView_ setDelegate:self];
  [backgroundTimer_ invalidate];
  distanceInBackground_ = 0.0f;
}

- (void)applicationWillTerminate:(UIApplication *)application {
  if (currentTrip_) {
    [database_ cancelTrip:currentTrip_];
    [self setCurrentTrip:nil];
  }
}

- (void)findMeButtonPressed {
  if ([self canShowUserLocation]) {
    [TestFlight passCheckpoint:@"find me button pressed"];
    [mapView_ setUserTrackingMode:MKUserTrackingModeFollow animated:YES];
  }
}

- (void)timerFireMethod:(NSTimer *)theTimer {
  if (distanceInBackground_ < 5000) {
    [TestFlight passCheckpoint:@"forgot the location updating to work"];
    [database_ endTrip:currentTrip_ withDistance:currentDistance_ purpose:nil];
    [self stopUpdatingDistance];
  }
}

- (BOOL)isFirstTime {
  Setting *firstSetting = [database_ findOrCreateSettingWithTitle:kSettingFirstUse];
  return firstSetting.valueValue;
}

- (void)showFirstTimeWarning {
  UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:NSLocalizedString(@"trip.view.first.use.alert.text", nil) delegate:nil cancelButtonTitle:NSLocalizedString(@"button.title.OK", nil) destructiveButtonTitle:nil otherButtonTitles:nil, nil];
  [actionSheet showFromTabBar:self.tabBarController.tabBar];
  [database_ updateSetting:[database_ findOrCreateSettingWithTitle:kSettingFirstUse] withValue:NO];
}

- (BOOL)canShowUserLocation {
  Setting *setting = [database_ findOrCreateSettingWithTitle:kSettingShowMap];
  return [setting valueValue];
}
@end
