//
//  VFYCameraWrapper.m
//  Verif-y
//
//  Created by MTN on 09/01/20.
//

#import "VFYCameraWrapper.h"
#import <AVFoundation/AVFoundation.h>
#import "UINavigationController+autoRotate.h"
#import "VFYVerifyApp.h"
#import "VFYSelfieFinalPreviewWrapper.h"

@interface VFYCameraWrapper () <AVCapturePhotoCaptureDelegate>

@property (weak, nonatomic) IBOutlet UIView *overlay;
@property (weak, nonatomic) IBOutlet UIView *VFYCameraView;
@property (weak, nonatomic) IBOutlet UILabel *LbInstruction;
@property (nonatomic) AVCaptureDeviceInput* videoDeviceInput;
@property (nonatomic) AVCaptureSession *captureSession;
@property (nonatomic) AVCapturePhotoOutput *stillImageOutput;
@property (nonatomic) AVCaptureVideoPreviewLayer *videoPreviewLayer;
@property (nonatomic) AVCaptureDeviceDiscoverySession* videoDeviceDiscoverySession;
@property (weak, nonatomic) IBOutlet UIButton *BTNFlashLight;
@property (nonatomic, retain) VFYVerifyApp *sharedInstance;
@property (nonatomic, strong) NSBundle *bundlePath;

@end

@implementation VFYCameraWrapper

@synthesize idSuccess;

- (void) viewDidLoad {
    [super viewDidLoad];
    if (@available(iOS 13.0, *)) {
         self.view.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;
    }
    self.bundlePath = [NSBundle bundleForClass:[VFYVerifyApp class]];
    self.sharedInstance = [VFYVerifyApp sharedInstance];
    [self.BTNFlashLight setImage:[UIImage imageNamed:@"flash-off"] forState:UIControlStateNormal];
    [self.BTNFlashLight setImage:[UIImage imageNamed:@"flash-on"] forState:UIControlStateSelected];
    self.overlay.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.8f];
    [self.LbInstruction setTextColor:[UIColor whiteColor]];
    [self addOverlayShape];
    [self CustomTitle];
}

- (void) addOverlayShape {
    //Uncomment below to get the height and width as per the overlay
    //CGFloat width = self.overlay.frame.size.width; //CGFloat height = self.overlay.frame.size.height;
    CGPoint center = [self view].center;
    /*CGFloat radius = (width/2)-40; CGFloat xOffset = width/2; CGFloat yOffset = height/2;*/
    //CGFloat radius = 200;
    CGFloat xOffset = center.x;
    CGFloat yOffset = center.y;
    CGMutablePathRef path = CGPathCreateMutable();
    //Uncomment to draw the circle instead of oval shape
    //CGPathAddArc(path, NULL, xOffset, yOffset, radius, 0.0, 2.0 * M_PI, false);
    CGPathAddEllipseInRect(path, NULL,CGRectMake(xOffset/4, yOffset/2, 300, 400));
    CGPathAddRect(path, NULL, CGRectMake(0.0, 0.0, self.view.frame.size.width, self.view.frame.size.height));
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.backgroundColor = (__bridge CGColorRef _Nullable)([UIColor blackColor]);
    maskLayer.path = path;
    maskLayer.fillRule = kCAFillRuleEvenOdd;
    self.overlay.layer.mask = maskLayer;
    self.overlay.clipsToBounds = true;
    /*NSLog(@"width:- %f",width); NSLog(@"height:- %f",height);
    NSLog(@"width:- %f",self.view.frame.size.width); NSLog(@"height:- %f",self.view.frame.size.height);*/
}

-(void) CustomTitle
{
    if([self.sharedInstance.headerTitleImage length]>0){
       [Utilities customTitleImage:self.navigationItem Logo:self.sharedInstance.headerTitleImage];
    } else if([self.sharedInstance.headerTitleText length]){
        [Utilities customTitleText:self.navigationItem TitleText:self.sharedInstance.headerTitleText FontColor:self.sharedInstance.headerTextColor];
    }
}

- (void)viewWillAppear:(BOOL)animated {
    [self.navigationController setNavigationBarHidden:YES animated:animated];
    [super viewWillAppear:animated];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    
    /* Force the portrait orientation on view appear*/
    NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
    [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
    
    /* Set up all the supported device in array */
    NSArray<AVCaptureDeviceType>* deviceTypes = @[AVCaptureDeviceTypeBuiltInWideAngleCamera, AVCaptureDeviceTypeBuiltInDualCamera, AVCaptureDeviceTypeBuiltInTrueDepthCamera];
    self.videoDeviceDiscoverySession = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:deviceTypes mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified];
    self.captureSession = [AVCaptureSession new];
    self.captureSession.sessionPreset = AVCaptureSessionPresetMedium;
    AVCaptureDevice *backCamera = [AVCaptureDevice defaultDeviceWithDeviceType:AVCaptureDeviceTypeBuiltInWideAngleCamera mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionFront];
    if (!backCamera) {
        NSLog(@"Unable to access back camera!");
        return;
    }
    NSError *error;
    self.videoDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:backCamera error:&error];
    if (!error) {
        //Step 9
    }
    else {
        NSLog(@"Error Unable to initialize back camera: %@", error.localizedDescription);
    }
    self.stillImageOutput = [AVCapturePhotoOutput new];
    if ([self.captureSession canAddInput:self.videoDeviceInput] && [self.captureSession canAddOutput:self.stillImageOutput]) {
        [self.captureSession addInput:self.videoDeviceInput];
        [self.captureSession addOutput:self.stillImageOutput];
        [self setupLivePreview];
    }
}

/**
  Configure the camera and set up preview
*/
- (void)setupLivePreview {
    self.videoPreviewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];
    if (self.videoPreviewLayer) {
        self.videoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspect;
        self.videoPreviewLayer.connection.videoOrientation = AVCaptureVideoOrientationPortrait;
        [self.VFYCameraView.layer addSublayer:self.videoPreviewLayer];
        self.videoPreviewLayer.frame = self.VFYCameraView.bounds;
    }
    dispatch_queue_t globalQueue =  dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
       dispatch_async(globalQueue, ^{
           [self.captureSession startRunning];
    });
    dispatch_async(dispatch_get_main_queue(), ^{
       // [self.view bringSubviewToFront:self.transparent];
    });
    //double delayInSeconds = 1.0;
    //dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    //dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    [self.VFYCameraView bringSubviewToFront:self.overlay];
    //});
}

- (void) changeCamera {
    AVCaptureDevice* currentVideoDevice = self.videoDeviceInput.device;
    AVCaptureDevicePosition currentPosition = currentVideoDevice.position;
    AVCaptureDevicePosition preferredPosition;
    AVCaptureDeviceType preferredDeviceType;
    switch (currentPosition)
    {
        case AVCaptureDevicePositionUnspecified:
        case AVCaptureDevicePositionFront:
            preferredPosition = AVCaptureDevicePositionBack;
            preferredDeviceType = AVCaptureDeviceTypeBuiltInDualCamera;
            break;
        case AVCaptureDevicePositionBack:
            preferredPosition = AVCaptureDevicePositionFront;
            preferredDeviceType = AVCaptureDeviceTypeBuiltInTrueDepthCamera;
            break;
    }
    NSArray<AVCaptureDevice* >* devices = self.videoDeviceDiscoverySession.devices;
    AVCaptureDevice* newVideoDevice = nil;
    // First, look for a device with both the preferred position and device type.
    for (AVCaptureDevice* device in devices) {
        if (device.position == preferredPosition && [device.deviceType isEqualToString:preferredDeviceType]) {
            newVideoDevice = device;
            break;
        }
    }
    // Otherwise, look for a device with only the preferred position.
    if (!newVideoDevice) {
        for (AVCaptureDevice* device in devices) {
            if (device.position == preferredPosition) {
                newVideoDevice = device;
                break;
            }
        }
    }
    if (newVideoDevice) {
        AVCaptureDeviceInput* videoDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:newVideoDevice error:NULL];
        [self.captureSession beginConfiguration];
        // Remove the existing device input first, since using the front and back camera simultaneously is not supported.
        [self.captureSession removeInput:self.videoDeviceInput];
        if ([self.captureSession canAddInput:videoDeviceInput]) {
            //[[NSNotificationCenter defaultCenter] removeObserver:self name:AVCaptureDeviceSubjectAreaDidChangeNotification object:currentVideoDevice];
            //[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(subjectAreaDidChange:) name:AVCaptureDeviceSubjectAreaDidChangeNotification object:newVideoDevice];
            [self.captureSession addInput:videoDeviceInput];
            self.videoDeviceInput = videoDeviceInput;
        }
        else {
            [self.captureSession addInput:self.videoDeviceInput];
        }
        
        [self.captureSession commitConfiguration];
    }
}

/**
  Get the capture image
*/
- (void)captureOutput:(AVCapturePhotoOutput *)output didFinishProcessingPhoto:(AVCapturePhoto *)photo error:(nullable NSError *)error {
    NSData *imageData = photo.fileDataRepresentation;
    if (imageData) {
        UIImage *image = [UIImage imageWithData:imageData];
        [self pushNextView:image];
    }
}

/**
  Push the view to next viewcontroller
*/
- (void) pushNextView:(UIImage*) captureImage {
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:VFY_MAIN_STORYBOARD bundle:self.bundlePath];
    VFYSelfieFinalPreviewWrapper *newView = [storyboard instantiateViewControllerWithIdentifier:VFY_SELFIE_PREVIEW_STORYBOARD];
    newView.selectedOption = Camera;
    newView.passImage = captureImage;
    newView.idSuccess = self.idSuccess;
    newView.audit_event_Duration = self.audit_event_Duration;
    [self.navigationController pushViewController:newView animated:YES];
}

- (void) viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];
}

/**
   Stop the session on view disappear
*/
- (void)viewWillDisappear:(BOOL)animated {
    [self.navigationController setNavigationBarHidden:NO animated:animated];
    [super viewWillDisappear:animated];
    [self.captureSession stopRunning];
}

/**
  Force the portraite view
*/
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

- (BOOL)shouldAutorotate {
    return NO;
}

-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationPortrait;
}

/**
   Close button
*/
- (IBAction) BTNClose: (UIButton *) sender {
   [self.navigationController popViewControllerAnimated:YES];
}

/**
  Capture the image from camera
*/
- (IBAction)BTNCapture:(id)sender {
    AVCapturePhotoSettings *settings = [AVCapturePhotoSettings photoSettingsWithFormat:@{AVVideoCodecKey: AVVideoCodecTypeJPEG}];
    [self.stillImageOutput capturePhotoWithSettings:settings delegate:self];
    //[self pushNextView:nil];
}

/**
  Flip camera
*/
- (IBAction) BTNChangeCamera: (UIButton *) sender {
   [self changeCamera];
}

/**
  Torch on/off
*/
- (IBAction)BTNTurnTorchOn: (UIButton *) sender {
   sender.selected = !sender.selected;
   BOOL on;
   if (sender.selected) {
       on = true;
       [self.BTNFlashLight setImage:[UIImage imageNamed:@"flash-on"] forState:UIControlStateSelected];
       [self.BTNFlashLight setBackgroundImage:[UIImage imageNamed:@"flash-on"] forState:UIControlStateHighlighted];

   }
   else{
       on = false ;
       [self.BTNFlashLight setImage:[UIImage imageNamed:@"flash-off"] forState:UIControlStateNormal];
       [self.BTNFlashLight setBackgroundImage:[UIImage imageNamed:@"flash-off"] forState:UIControlStateHighlighted];
   }
   // check if flashlight available
   Class captureDeviceClass = NSClassFromString(@"AVCaptureDevice");
   if (captureDeviceClass != nil) {
       AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
       AVCapturePhotoSettings *photosettings = [AVCapturePhotoSettings photoSettings];
       if ([device hasTorch] && [device hasFlash]){
           [device lockForConfiguration:nil];
           if (on) {
               [device setTorchMode:AVCaptureTorchModeOn];
               photosettings.flashMode = AVCaptureFlashModeOn;
               //torchIsOn = YES; //define as a variable/property if you need to know status
           } else {
               [device setTorchMode:AVCaptureTorchModeOff];
                photosettings.flashMode = AVCaptureFlashModeOn;
               //torchIsOn = NO;
           }
           [device unlockForConfiguration];
       }
   }
}

@end
