//
//  MBIMFetchAttachmentOperation.m
//  kordophoned
//
//  Created by James Magahern on 11/20/18.
//  Copyright © 2018 James Magahern. All rights reserved.
//

#import "MBIMFetchAttachmentOperation.h"
#import "MBIMDataResponse.h"
#import "MBIMImageUtils.h"

#import "IMCore_ClassDump.h"
#import "IMSharedUtilities_ClassDump.h"
#import <CoreGraphics/CoreGraphics.h>

@implementation MBIMFetchAttachmentOperation

+ (void)load { [super load]; }

+ (NSString *)endpointName
{
    return @"attachment";
}

- (void)main
{
    NSObject<HTTPResponse> *response = nil;
    do {
        BOOL preview = [[self valueForQueryItemWithName:@"preview"] boolValue];
        NSString *guid = [self valueForQueryItemWithName:@"guid"];
        if (!guid) {
            MBIMLogInfo(@"No query item provided");
            response = [[HTTPErrorResponse alloc] initWithErrorCode:500];
            break;
        }
        
        IMFileTransfer *transfer = [[IMFileTransferCenter sharedInstance] transferForGUID:guid];
        if (!transfer) {
            MBIMLogInfo(@"No transfer found for guid: %@", guid);
            response = [[HTTPErrorResponse alloc] initWithErrorCode:404];
            break;
        }
        
        if (![transfer existsAtLocalPath]) {
            MBIMLogInfo(@"We don't have the file for this yet (still downloading to server?)");
            response = [[HTTPErrorResponse alloc] initWithErrorCode:404];
            break;
        }
        
        NSData *responseData = nil;
        NSURL *localURL = [transfer localURL];
        NSString *extension = [[localURL pathExtension] lowercaseString];
        if (preview) {
            IMPreviewConstraints constraints = IMPreviewConstraintsZero();

            // Fetch preview constraints from transfer
            NSDictionary *previewConstraintsDict = [[transfer attributionInfo] objectForKey:@"pgenszc"];
            if (previewConstraintsDict) {
                constraints = IMPreviewConstraintsFromDictionary(previewConstraintsDict);
            } else {
                // Or, make a guess. 
                constraints.maxPxWidth = 500.0;
                constraints.scale = 1.0;
            }

            NSURL *previewURL = IMAttachmentPreviewFileURL(localURL, extension, YES);
            if (!previewURL) {
                // I'm not sure why this sometimes returns nil... 
                MBIMLogInfo(@"Unable to generate attachment preview cache URL for %@, making one up.", localURL);

                NSURL *temporaryAttachmentCache = [[[NSFileManager defaultManager] temporaryDirectory] URLByAppendingPathComponent:@"kordophone_attachment_cache"];
                temporaryAttachmentCache = [temporaryAttachmentCache URLByAppendingPathComponent:guid];

                [[NSFileManager defaultManager] createDirectoryAtURL:temporaryAttachmentCache withIntermediateDirectories:YES attributes:nil error:nil];

                previewURL = [temporaryAttachmentCache URLByAppendingPathComponent:[localURL lastPathComponent]];
            }

            if (![[NSFileManager defaultManager] fileExistsAtPath:[previewURL path]]) {
                MBIMLogInfo(@"Generating preview image for guid: %@ at %@", guid, [previewURL path]);
                
                // Generate preview using preview generator manager
                NSError *error = nil;
                IMPreviewGeneratorManager *generator = [IMPreviewGeneratorManager sharedInstance];
                CGImageRef previewImage = [generator newPreviewFromSourceURL:localURL withPreviewConstraints:constraints error:&error];
                if (error) {
                    MBIMLogInfo(@"Unable to generate preview for attachment guid: %@", guid);
                    response = [[HTTPErrorResponse alloc] initWithErrorCode:500];
                    break;
                }
                
                // Convert to JPEG.
                responseData = MBIMCGImageJPEGRepresentation(previewImage);
                
                // Persist JPEG preview to disk
                if (previewURL) {
                    [responseData writeToURL:previewURL atomically:YES];
                }
            } else {
                // File exists
                MBIMLogInfo(@"Using cached preview image for guid: %@ at %@", guid, [previewURL path]);
                responseData = [NSData dataWithContentsOfURL:previewURL];
            }
        } else {
            responseData = [NSData dataWithContentsOfURL:localURL];
        }
         
        if (!responseData) {
            MBIMLogInfo(@"Wasn't able to load data for guid: %@", guid);
            response = [[HTTPErrorResponse alloc] initWithErrorCode:404];
            break;
        }
        
        NSString *mimeType = [transfer mimeType];
        if ([mimeType isEqualToString:@"image/heic"]) {
            // TODO: We should convert this to JPEG here. I don't want clients to have to deal with HEIC.
            MBIMLogInfo(@"WARNING: Returning HEIC data for attachment %@", guid);
        }
        
        // It's unusual, but if this is nil, try to guess the MIME type based on the filename
        if (!mimeType) {
            // XXX: REALLY hacky
            mimeType = [NSString stringWithFormat:@"image/%@", extension];
        }
        
        MBIMDataResponse *dataResponse = [[MBIMDataResponse alloc] initWithData:responseData contentType:mimeType];
        dataResponse.httpHeaders[@"Cache-Control"] = @"public, immutable, max-age=31536000";
        response = dataResponse;
    } while (0);
    
    self.serverCompletionBlock(response);
}

@end
