//
//  ContainerViewController.m
//  PhotoShareExtension
//
//  Created by Russell on 27/5/15.
//
//

#import "ContainerViewController.h"
#import "ImageCaptionViewController.h"
#import <ImageIO/ImageIO.h>

@interface ContainerViewController ()
@property (assign) ImageCaptionViewController *svc;
- (BOOL)tokenExists;
- (void)handleUploadError:(NSError *)error;
@end

@implementation ContainerViewController

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

  [self performSegueWithIdentifier:@"InitialSegue" sender:nil];

  self.api = [[NixAPI alloc] init];
  self.uploadHandler = [[NixUpload alloc] initWithAPI:self.api];
  self.uploadHandler.delegate = self;
  self.uploadHandler.uploadSessionIdentifier = @"com.creedon.Nixplay.uploadsession.appext";
  [self.uploadHandler createSession]; // rejoin the session
  [self.uploadHandler loadUploadState];
}

- (void)didReceiveMemoryWarning {
  [super didReceiveMemoryWarning];
  // Dispose of any resources that can be recreated.
}

#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
  // Get the new view controller using [segue destinationViewController].
  // Pass the selected object to the new view controller.
  self.svc = ((UINavigationController *)segue.destinationViewController)
  .childViewControllers[0];
  self.svc.containerViewController = self;
}

#pragma mark - Actions
- (void)verifyServiceAvailable {
  [self verifyServiceAvailableWithCompletionHandler:nil];
}

- (void)verifyServiceAvailableWithCompletionHandler:(void (^)(BOOL))completionHandler {

  [self.uploadHandler getCurrentTasks:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
    NSLog(@"uploadTasks: %@", uploadTasks);
  }];


  if (!self.api.apiURL.length) {

    [self showAlertViewWithTitle:NSLocalizedString(@"app_never_launched_title", nil)
                         message:NSLocalizedString(@"app_never_launched_message", nil)
                 actionWithTitle:NSLocalizedString(@"close", nil)
                         handler:^(UIAlertAction *action) {
                           [self cancel];
                         }];
    completionHandler(NO);
    return;
  }

  if (![self tokenExists]) {
    [self showAlertViewWithTitle:NSLocalizedString(@"no_account_title", nil)
                         message:NSLocalizedString(@"no_account_message", nil)
                 actionWithTitle:NSLocalizedString(@"close", nil)
                         handler:^(UIAlertAction *action) {
                           [self cancel];
                         }];
    completionHandler(NO);
  } else {
    [self pingWithCompletionHandler:^(NSError *error) {
      if (error) {
        if (error.code == 401) {

          [self showAlertViewWithTitle:NSLocalizedString(@"signin_again_title", nil)
                               message:NSLocalizedString(@"signin_again_message", nil)
                       actionWithTitle:NSLocalizedString(@"close", nil)
                               handler:^(UIAlertAction *action) {
                                 [self cancel];
                               }];
        } else {
          [self showAlertViewWithTitle:NSLocalizedString(@"server_connection_error_title", nil)
                               message:NSLocalizedString(@"server_connection_error_message", nil)
                       actionWithTitle:NSLocalizedString(@"close", nil)
                               handler:^(UIAlertAction *action) {
                                 [self cancel];
                               }];
        }
        completionHandler(NO);
      } else {
        completionHandler(YES);
      }
    }];
  }
}

- (void)pingWithCompletionHandler:(void (^)(NSError *))completionHandler {
  [self.api ping:^(id data, NSURLResponse *response, NSError *error) {
    NSLog(@"pingError: %@", error);
    completionHandler(error);
  }];
}

- (void)send {

  NSMutableIndexSet *imageErrorIndexes = [NSMutableIndexSet indexSet];
  for (NSUInteger i = 0; i < self.imageErrors.count; i++) {
    NSError *error = self.imageErrors[i];
    if ([error isKindOfClass:[NSError class]]) {
      [imageErrorIndexes addIndex:i];
    }
  }

  NSMutableArray *mutableImageUrls = [NSMutableArray arrayWithArray:self.imageUrls];
  NSMutableArray *mutableCaptions = [NSMutableArray arrayWithArray:self.captions];
  [mutableImageUrls removeObjectsAtIndexes:imageErrorIndexes];
  [mutableCaptions removeObjectsAtIndexes:imageErrorIndexes];

  if (mutableImageUrls.count == 0) {
    NSError *error = [NSError errorWithDomain:[[NSBundle mainBundle] bundleIdentifier]
                                         code:0
                                     userInfo:@{
                                                NSLocalizedDescriptionKey: NSLocalizedString(@"upload_error_no_files_selected", nil)
                                                }];
    [self handleUploadError:error];
    return;
  }


  //process image before upload
  //if user choose optimize photo size
  if( [self isOptimizeResolution ]){
    //optimize photo size

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
      SDImageCache *imageCache = [SDImageCache sharedImageCache];
      //store images to /tmp
      NSString *defaultCachePath = NSTemporaryDirectory();

      //nix opt. size
      float optimizedDimension = 1820.0f;
      NSNumber *maxWidth = [NSNumber numberWithFloat:optimizedDimension];


      for (NSUInteger i = 0; i < mutableImageUrls.count; i++) {
        @autoreleasepool {
          NSURL *imageUrl = mutableImageUrls[i];
          CGImageSourceRef imageSource = CGImageSourceCreateWithURL((CFURLRef)imageUrl, nil);

          // load the image at the desired size
          NSDictionary* options = @{
                                    (id)kCGImageSourceShouldAllowFloat: (id)kCFBooleanTrue,
                                    (id)kCGImageSourceCreateThumbnailWithTransform: (id)kCFBooleanTrue,
                                    (id)kCGImageSourceCreateThumbnailFromImageAlways: (id)kCFBooleanTrue,
                                    (id)kCGImageSourceThumbnailMaxPixelSize: maxWidth
                                    };

          CGImageRef imageRef = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, (__bridge CFDictionaryRef)options);

          //80% jpg quality
          NSData * data = UIImageJPEGRepresentation([UIImage imageWithCGImage:imageRef], 0.8f);

          //retrieve cache path from Table view SDImageCache
          NSURL* cachePathURL = [[NSURL alloc] initWithString:[imageCache cachePathForKey:[imageUrl absoluteString]]] ;
          NSURL* newPathURL = [[NSURL alloc] initWithString:
                               [NSString stringWithFormat:@"%@/%@.JPG",defaultCachePath, [cachePathURL lastPathComponent]]];

          NSDictionary *metaoptions = @{(NSString *)kCGImageSourceShouldCache : [NSNumber numberWithBool:NO]};
          CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, (__bridge CFDictionaryRef)metaoptions);
          if (imageProperties) {
            NSDictionary *metadata = (__bridge NSDictionary *)imageProperties;
            NSMutableDictionary *mutableMetadata = [NSMutableDictionary dictionaryWithDictionary:metadata];
            [mutableMetadata setValue:[NSNumber numberWithInt:1] forKey:@"Orientation"];
            [self writeData: [self writeMetadataIntoImageData:data metadata:mutableMetadata ] toPath: [newPathURL absoluteString]];

          }
          else{
            //wirte to file
            [self writeData: data toPath: [newPathURL absoluteString]];
          }
          //replace imageURLs object
          [mutableImageUrls replaceObjectAtIndex:i withObject:[newPathURL absoluteString] ];
        }
      }

      [self.uploadHandler uploadWithImageUrls:[mutableImageUrls copy]
                                     captions:[mutableCaptions copy]
                                    playlists:self.playlistIds
                                      friends:self.friendUsernames
                                       camera:NO];
    });

  }

  else{
    [mutableImageUrls enumerateObjectsUsingBlock:^(NSURL* url, NSUInteger idx, BOOL * _Nonnull stop) {
      [mutableImageUrls replaceObjectAtIndex:idx withObject:[url absoluteString]];
    }];
    [self.uploadHandler uploadWithImageUrls:[mutableImageUrls copy]
                                   captions:[mutableCaptions copy]
                                  playlists:self.playlistIds
                                    friends:self.friendUsernames
                                     camera:NO];
  }
}


- (void)cancel {
  dispatch_async(dispatch_get_main_queue(), ^{
    [self dismissViewControllerAnimated:YES completion:^{
      NSDictionary *userInfo = @{
                                 NSLocalizedDescriptionKey: NSLocalizedString(@"Operation was cancelled.", nil),
                                 NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"Operation was cancelled.", nil),
                                 NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"Operation was cancelled.", nil)
                                 };
      NSError *error = [NSError errorWithDomain:NSURLErrorDomain
                                           code:-57
                                       userInfo:userInfo];
      [self.extensionContext cancelRequestWithError:error];
    }];
  });
}

#pragma mark - Private
- (BOOL)tokenExists {
  return [[self.api getAccessToken] length];
}

- (void)handleUploadError:(NSError *)error {
  if (error) {
    UINavigationController *navigationController = (UINavigationController *)self.presentedViewController;
    ReceiverTableViewController *receiverTableVC = (ReceiverTableViewController *)navigationController.topViewController;
    if ([receiverTableVC isKindOfClass:[ReceiverTableViewController class]]) {
      [receiverTableVC hideActivityIndicator];
      receiverTableVC.navigationItem.rightBarButtonItem.enabled = YES;
    }

    NSString *errorMessage = [error localizedDescription];
    switch (error.code) {
      case kNixIoFileTooLargeError:
        errorMessage = NSLocalizedString(@"upload_error_file_too_large", nil);
        break;
    }
    [self showAlertViewWithTitle:NSLocalizedString(@"upload_error_title", nil)
                         message:errorMessage
                 actionWithTitle:NSLocalizedString(@"close", nil)
                         handler:^(UIAlertAction *action) {
                           [self cancel];
                         }];
  }

  //delete cache image
  [self deleteCache];

}

-(BOOL) isOptimizeResolution {
  NSUserDefaults *preferences = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.creedon.Nixplay"] ;

  NSString *optimizeResolutionKey = @"nixSettings.settings.resolution";

  if ([preferences objectForKey:optimizeResolutionKey] == nil)
  {
    NSLog(@"%@ not exist",optimizeResolutionKey);
    return false;
  }
  else
  {
    //  Get current level
    const Boolean optimizeResolution = [preferences boolForKey:optimizeResolutionKey];

    NSLog(@"currentLevel %i",optimizeResolution);
    return optimizeResolution;

  }
  return false;
}

- (BOOL)writeData:(NSData*) data toPath:(NSString *)path
{
  NSError* errorWrite = nil;

  BOOL write = [data writeToFile:path atomically:YES];
  if(errorWrite != NULL){
    NSLog(@"Failed to write to '%@': %@", path , [errorWrite localizedDescription]);
  }
  return write;
}

-(void)deleteCache{
  NSArray* tmpDirectory = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:NSTemporaryDirectory() error:NULL];
  for (NSString *file in tmpDirectory) {
    [[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:@"%@%@", NSTemporaryDirectory(), file] error:NULL];
  }
}


//http://stackoverflow.com/questions/9006759/how-to-write-exif-metadata-to-an-image-not-the-camera-roll-just-a-uiimage-or-j
-(NSData *)writeMetadataIntoImageData:(NSData *)imageData metadata:(NSMutableDictionary *)metadata {
  // create an imagesourceref
  CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef) imageData, NULL);

  // this is the type of image (e.g., public.jpeg)
  CFStringRef UTI = CGImageSourceGetType(source);

  // create a new data object and write the new image into it
  NSMutableData *dest_data = [NSMutableData data];
  CGImageDestinationRef destination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)dest_data, UTI, 1, NULL);
  if (!destination) {
    NSLog(@"Error: Could not create image destination");
  }
  // add the image contained in the image source to the destination, overidding the old metadata with our modified metadata
  CGImageDestinationAddImageFromSource(destination, source, 0, (__bridge CFDictionaryRef) metadata);
  BOOL success = NO;
  success = CGImageDestinationFinalize(destination);
  if (!success) {
    NSLog(@"Error: Could not create data from image destination");
  }
  CFRelease(destination);
  CFRelease(source);
  return dest_data;
}

#pragma mark - NixUploadDelegate
- (void)didStartUploadWithTasks:(NSArray *)tasks {
  [self dismissViewControllerAnimated:YES completion:^{
    [self.extensionContext completeRequestReturningItems:@[]
                                       completionHandler:nil];
  }];
}

- (void)didUploadImageAtIndex:(NSUInteger)index error:(NSError *)error {
  [self handleUploadError:error];
}

- (void)didFinishUploadingWithError:(NSError *)error {
  [self handleUploadError:error];

}

-(void) showAlertViewWithTitle:(NSString*)title message:(NSString*)message actionWithTitle:actiontitle handler:(void (^ __nullable)(UIAlertAction *action))handler{
  UIAlertController* alert = [UIAlertController alertControllerWithTitle:title
                                                                 message:message
                                                          preferredStyle:UIAlertControllerStyleAlert];

  UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"close", nil) style:UIAlertActionStyleDefault
                                                        handler:^(UIAlertAction * action) {
                                                          [self cancel];
                                                        }];
  [alert addAction:defaultAction];

  [self.svc presentViewController:alert animated:YES completion:nil];

}

@end
