#import <Foundation/Foundation.h>
#import <CoreMedia/CoreMedia.h>
#import <AVFoundation/AVFoundation.h>
#import <AVFoundation/AVFCapture.h>
#import <AVKit/AVKit.h>
#import <AVFoundation/AVFoundation.h>

@interface MyDelegate : NSObject <AVCaptureVideoDataOutputSampleBufferDelegate>

- (void) captureOutput:(AVCaptureOutput *)captureOutput
         didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
         fromConnection:(AVCaptureConnection *)connection;

@end

@implementation MyDelegate

- (void)captureOutput:(AVCaptureOutput *)captureOutput
         didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
         fromConnection:(AVCaptureConnection *)connection
{
    NSLog(@"Got a frame!");
}

@end


void run(bool useSnapCamera)
{
    NSString* cameraID = nil;

    {
        NSLog(useSnapCamera ? @"Looking for snap camera" : @"Looking for not snap camera");
        
        NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];

        for (AVCaptureDevice *device in videoDevices) {
            NSLog(@"----------");
            
            if ([[device uniqueID] hasPrefix:@"SnapCamera"] == useSnapCamera) {
                NSLog(@"Camera found");
                cameraID = [device uniqueID];
            }
            
            NSLog(@"  id: %@", [device uniqueID]);
            NSLog(@"  description: %@", [device localizedName]);
            NSLog(@"  formats:");

            for (AVCaptureDeviceFormat *format in device.formats) {
                if (![format.mediaType isEqualToString:AVMediaTypeVideo])
                    continue;

                CMVideoDimensions size = CMVideoFormatDescriptionGetDimensions(format.formatDescription);
                NSLog(@"    format: %u; resulution: {%u; %u}",
                      CMVideoFormatDescriptionGetCodecType(format.formatDescription),
                      size.width,
                      size.height);
            }
        }
    }
    
    if (cameraID == nil)
    {
        NSLog(@"No camera found");
        return;
    }
    
    AVCaptureSession* session = [[AVCaptureSession alloc] init];

    AVCaptureDevice *videoDevice = [AVCaptureDevice deviceWithUniqueID: cameraID];
    AVCaptureDeviceInput* input = [AVCaptureDeviceInput
                    deviceInputWithDevice:videoDevice
                    error:nil];
    
    [session addInput:input];

    AVCaptureVideoDataOutput* output = [[AVCaptureVideoDataOutput alloc] init];
    
    MyDelegate* delegate = [[MyDelegate alloc] init];

    // Configure video output
    dispatch_queue_t queue = dispatch_queue_create("vf_queue", nil);
    [output setSampleBufferDelegate:delegate queue:queue];
    [session addOutput:output];

    [session startRunning];
    
    NSLog(@"Print char!");
    getchar();
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        run(true);
    }
    
    return 0;
}
