#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
#import "FileManager.h"
#import <QuickLook/QuickLook.h>
#import <React/RCTUtils.h>
#import <React/RCTConvert.h>
#import <MobileCoreServices/MobileCoreServices.h>

static NSString *const E_DOCUMENT_PICKER_CANCELED = @"DOCUMENT_PICKER_CANCELED";
static NSString *const E_INVALID_DATA_RETURNED = @"INVALID_DATA_RETURNED";

static NSString *const OPTION_TYPE = @"type";
static NSString *const OPTION_MULTIPLE = @"allowMultiSelection";

static NSString *const FIELD_URI = @"uri";
static NSString *const FIELD_FILE_COPY_URI = @"fileCopyUri";
static NSString *const FIELD_COPY_ERR = @"copyError";
static NSString *const FIELD_NAME = @"name";
static NSString *const FIELD_TYPE = @"type";
static NSString *const FIELD_SIZE = @"size";

@interface CometChatFileManager () <UIDocumentPickerDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate>
@end

@implementation CometChatFileManager {
    NSString *_url;
    RCTResponseSenderBlock callback;
    bool hasListeners;
}

- (void)startObserving {
    hasListeners = YES;
}

- (void)stopObserving {
    hasListeners = NO;
}

- (NSArray<NSString *> *)supportedEvents {
    return @[@"opening", @"downloading"];
}

RCT_EXPORT_MODULE(FileManager)

RCT_EXPORT_METHOD(checkAndDownload:(NSString *) urlToDownload name:(NSString *) name callback:(RCTResponseSenderBlock) callback) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            NSURL  *url = [NSURL URLWithString:urlToDownload];
            NSData *urlData = [NSData dataWithContentsOfURL:url];
            if (urlData)
            {
                NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
                NSString *documentsDirectory = [paths objectAtIndex:0];

                NSString *filePath = [NSString stringWithFormat:@"file://%@/%@", documentsDirectory,name];
                NSURL *destinationFileURL = [NSURL URLWithString:filePath];

                NSURL *url = [NSURL URLWithString:urlToDownload];
                [[[NSURLSession sharedSession] downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
                    if (error == nil) {
                        NSLog(@"down moving %@ to %@", location, destinationFileURL);
                        [[NSFileManager defaultManager] moveItemAtURL:location toURL:destinationFileURL error:nil];
                        NSLog(@"downloaded to %@", filePath);
                        self->_url = filePath;
                        callback(@[filePath]);
                        return;
                    }
                    callback(@[@""]);
                }] resume];
            }
        });
}

- (void) openMedia:(NSString *) path {
            dispatch_async(dispatch_get_main_queue(), ^{
                QLPreviewController* previewCtrl = [[QLPreviewController alloc] init];
                [previewCtrl setDataSource: self];
                [[previewCtrl navigationController] setTitle:@""];
                [previewCtrl setModalPresentationStyle:UIModalPresentationPopover];
                UIViewController *presentedViewController = RCTPresentedViewController();
                [presentedViewController presentViewController:previewCtrl animated:YES completion:nil];
            });
}

RCT_EXPORT_METHOD(openFile:(NSString *) url name:(NSString *) fileName myCallback:(RCTResponseSenderBlock)callback) {
    //new way
    @try {
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDownloadsDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0];
        NSString *filepath = [NSString stringWithFormat:@"%@/%@", documentsDirectory, fileName];
        if ([[NSFileManager defaultManager] fileExistsAtPath: filepath isDirectory:false]) {
            self->_url = [NSString stringWithFormat:@"file://%@",filepath];
            if (hasListeners)
                [self sendEventWithName:@"opening" body:@{@"url": url}];
            [self openMedia:self->_url];
            callback(@[@"{\"success\": true}"]);
        } else {
            if (hasListeners)
                [self sendEventWithName:@"downloading" body:@{@"url": url}];
            [self checkAndDownload:url name:fileName callback:^(NSArray *response) {
                self->_url = [NSString stringWithFormat:@"%@",response[0]];
                NSLog(@"down url : %@", self->_url);
                [self openMedia:self->_url];
                callback(@[@"{\"success\": true}"]);
            }];
        }
    } @catch (NSException *exception) {
        NSLog(@"down got exception %@", [exception description]);
        callback(@[@"{\"error\": true}"]);
    }
}

- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller {
    return 1;
}

- (id <QLPreviewItem>)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index {
    return [NSURL URLWithString:_url];
}

- (BOOL)previewController:(QLPreviewController *)controller shouldOpenURL:(NSURL *)url forPreviewItem:(id <QLPreviewItem>)item {
    return YES;
}

RCT_EXPORT_METHOD(openCamera: (NSString *) type callback:(RCTResponseSenderBlock) call) {
    callback = call;
    UIViewController *presentedViewController = RCTPresentedViewController();
    dispatch_async(dispatch_get_main_queue(), ^{
        UIImagePickerController *imageController = [[UIImagePickerController alloc] init];
        imageController.delegate = self;
        imageController.title = @"Select an image";
        imageController.sourceType = UIImagePickerControllerSourceTypeCamera;
        [presentedViewController presentViewController:imageController animated:YES completion:nil];
    });
}

RCT_EXPORT_METHOD(openFileChooser:(NSString *) type callback:(RCTResponseSenderBlock) call) {
    callback = call;
    UIViewController *presentedViewController = RCTPresentedViewController();
    if ([@"image" isEqualToString:type]) {
        dispatch_async(dispatch_get_main_queue(), ^{
            UIImagePickerController *imageController = [[UIImagePickerController alloc] init];
            imageController.delegate = self;
            imageController.title = @"Select an image";
            imageController.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
            [presentedViewController presentViewController:imageController animated:YES completion:nil];
        });
    } else {
        dispatch_async(dispatch_get_main_queue(), ^{
            UIDocumentPickerViewController *documentController = [[UIDocumentPickerViewController alloc] initWithDocumentTypes: @[@"public.data",@"public.content",@"public.audiovisual-content",@"public.movie",@"public.audiovisual-content",@"public.video",@"public.audio",@"public.data",@"public.zip-archive",@"com.pkware.zip-archive",@"public.composite-content",@"public.text"] inMode: UIDocumentPickerModeImport];
            documentController.delegate = self;
            documentController.title = @"Select a file";
            [presentedViewController presentViewController:documentController animated:YES completion:nil];
        });
    }
}

- (NSURL *) saveImage:(NSString *) imageName image:(UIImage *) image {
    NSFileManager *defaultManager = [NSFileManager defaultManager];
    NSURL *documentUrl = [defaultManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask].firstObject;
    if (!documentUrl) {
        return [NSURL alloc];
    }
    NSURL *fileURL = [documentUrl URLByAppendingPathComponent:imageName];

    if ([defaultManager fileExistsAtPath:fileURL.path]) {
        [defaultManager removeItemAtPath:fileURL.path error:nil];
    }
    [UIImageJPEGRepresentation(image, 1.0) writeToURL:fileURL atomically:TRUE];
    return fileURL;
}

- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey, id> *)info {
    switch (picker.sourceType) {
        case UIImagePickerControllerSourceTypeCamera: {
            UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage];
            if (image) {
                NSTimeInterval interval = [[NSDate date] timeIntervalSince1970];
                NSString *subPart = [NSString stringWithFormat:@"%f", interval];
                NSString *filename = [NSString stringWithFormat:@"Image_%@.png", [subPart stringByReplacingOccurrencesOfString:@"." withString:@""]];
                NSURL *new_image_url = [self saveImage: filename image:image];
                NSString *type = [self getMimeType:new_image_url];
                NSString *name = [new_image_url lastPathComponent];
                NSString *uri = [NSString stringWithFormat:@"%@", new_image_url];
                callback(@[@{@"name": name, @"type": type, @"uri": uri}]);
            } else {
                NSLog(@"failed to get image");
                callback(@[@{@"error": @"unable to get image"}]);
            }
            break;
        }
        case UIImagePickerControllerSourceTypePhotoLibrary: {
            NSLog(@"image from photo library");
            NSURL *url = (NSURL *) [info valueForKey:UIImagePickerControllerImageURL];
            if (url) {
                NSLog(@"image path in url format : %@", url);
                NSString *name = [url lastPathComponent];
                NSString *extention = [url pathExtension];
                NSString *imageUrl = [[NSString alloc] initWithFormat:@"%@", url];
                NSString *videoUrl = [[NSString alloc] initWithFormat:@"%@", [info valueForKey:UIImagePickerControllerMediaURL]];
                NSString *fileurl;
                if (imageUrl)
                    fileurl = imageUrl;
                if (videoUrl)
                    fileurl = videoUrl;
//                NSString *type = [[NSString alloc] initWithFormat:@"%@", [info valueForKey:UIImagePickerControllerMediaType]];
                NSString *type = [self getMimeType:url];
                callback(@[@{@"name": name, @"uri": fileurl, @"type": type}]);
            } else {
                callback(@[@{@"error": @"invalid"}]);
            }
            break;
        }
        case UIImagePickerControllerSourceTypeSavedPhotosAlbum: {
            NSLog(@"image from saved photo library");
            NSString *imageUrl = [[NSString alloc] initWithFormat:@"%@", [info valueForKey:UIImagePickerControllerImageURL]];
            NSString *videoUrl = [[NSString alloc] initWithFormat:@"%@", [info valueForKey:UIImagePickerControllerMediaURL]];
            NSString *type = [[NSString alloc] initWithFormat:@"%@", [info valueForKey:UIImagePickerControllerMediaType]];
            NSURL *imgUrl = [[NSURL alloc] initWithString:imageUrl];
            NSString *name = [imgUrl lastPathComponent];
            callback(@[@{@"name": name, @"uri": imageUrl, @"type":type}]);
            break;
        }
    }
    [picker dismissViewControllerAnimated:TRUE completion:nil];
}

- (NSString *) getMimeType:(NSURL *) url {
    CFStringRef extension = (__bridge CFStringRef) url.pathExtension;
    CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(UTTagClassFilenameExtension, extension, NULL);
    CFStringRef mimeType = UTTypeCopyPreferredTagWithClass(uti, UTTagClassMIMEType);
    if (uti) {
        CFRelease(uti);
    }
    NSString *mimeTypeString = (__bridge_transfer NSString *)mimeType;
    return mimeTypeString;
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    NSLog(@"image selection cancelled");
    [picker dismissViewControllerAnimated:TRUE completion:nil];
}

- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls {
    NSLog(@"document selected %@", urls[0]);
    NSString *uri = [NSString stringWithFormat:@"%@", urls[0]];
    NSString *type = [self getMimeType:urls[0]];
    NSString *name = [urls[0] lastPathComponent];
    callback(@[@{@"name": name, @"type": type, @"uri": uri}]);
}

- (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller {
    NSLog(@"document pick cancelled");
    [controller dismissViewControllerAnimated:TRUE completion:nil];
}

@end
