/* Copyright (c) 2011 Artjom Popov */

#import "UTScannerController.h"
#import "UTScannerControllerDelegate.h"
#import "UTScannerIndicatorView.h"
#import "UTScannerResult.h"

#define UTScannerControllerIndicatorViewTag 2000

@implementation UTScannerController

@synthesize delegate = m_delegate;

- (UTScannerIndicatorView *)indicatorView
{
	return (UTScannerIndicatorView *)[self.view viewWithTag:UTScannerControllerIndicatorViewTag];
}

- (IBAction)cancel:(id)sender
{
	[self->m_session stopRunning];
	[self dismissModalViewControllerAnimated:YES];
}

- (void)dismiss
{
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(captureSessionDidStopRunning:) name:AVCaptureSessionDidStopRunningNotification object:nil];
	[self->m_session stopRunning];
}

- (void)captureSessionDidStopRunning:(NSNotification *)notification
{
	dispatch_after(
				   dispatch_time(0, 500000000),
				   dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
				   ^{
					   [self->m_session release];
					   self->m_session = nil;
					   
					   [self->m_previewLayer release];
					   self->m_previewLayer = nil;
					   
					   [self dismissModalViewControllerAnimated:YES];
				   });
}

#pragma mark AVCaptureVideoDataOutputSampleBufferDelegate

// Delegate routine that is called when a sample buffer was written
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
	[self->m_scanner scanSampleBuffer:sampleBuffer];
}

#pragma mark UTScannerDelegate

- (void)scanner:(UTScanner *)scanner didReadWithResult:(NSString *)result
{
	if(self->m_session.isRunning) {
		if([self->m_delegate respondsToSelector:@selector(scannerController:didFinishPickingResult:)]) {
			//[self->m_session stopRunning];
			[self->m_delegate scannerController:self didFinishPickingResult:result];
		}
	}
}

- (void)scanner:(UTScanner *)scanner didFailWithErrorCode:(UTScannerReaderError)error
{
	switch (error) {
		default:
			self.indicatorView.state = UTScannerIndicatorViewStatePartialMatch;
			break;
			
		case UTScannerReaderFinderPatternsError:
			self.indicatorView.state = UTScannerIndicatorViewStateNoMatch;
			break;
	}
}

#pragma mark UIViewController

- (void)loadView
{
	UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0.0F, 0.0F, 320.0F, 480.0F)];
	view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
	//view.backgroundColor = [UIColor themeBackgroundColor];

	self.view = view;
	[view release];
}

- (void)viewDidLoad
{
	[super viewDidLoad];
	
	NSError *error = nil;
	
	AVCaptureSession *session = [[[AVCaptureSession alloc] init] autorelease];
	session.sessionPreset = AVCaptureSessionPresetHigh;

	AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
	[device lockForConfiguration:nil];
	
	// Enable auto-focus
	if ([device isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) {
		device.focusMode = AVCaptureFocusModeContinuousAutoFocus;
	}
	
	[device unlockForConfiguration];
	
	AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
	[session addInput:input];
	
	NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
								   [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA], (NSString *)kCVPixelBufferPixelFormatTypeKey, nil];
	
	AVCaptureVideoDataOutput *output = [[[AVCaptureVideoDataOutput alloc] init] autorelease];
	output.minFrameDuration = CMTimeMake(1, 10);
	output.videoSettings = videoSettings;
	[session addOutput:output];
	
	dispatch_queue_t queue = dispatch_queue_create("myQueue", NULL);
	[output setSampleBufferDelegate:self queue:queue];
	dispatch_release(queue);
	
	[self->m_session release];
	self->m_session = [session retain];
	
	[self->m_previewLayer release];
	self->m_previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self->m_session];
	self->m_previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
	
	CGRect layerRect = self.view.layer.bounds;
	self->m_previewLayer.bounds = layerRect;
	self->m_previewLayer.position = CGPointMake(CGRectGetMidX(layerRect), CGRectGetMidY(layerRect));
	[self.view.layer addSublayer:self->m_previewLayer];
	
	UTScannerIndicatorView *indicatorView = [[UTScannerIndicatorView alloc] initWithFrame:CGRectMake((self.view.frame.size.width / 2.0F) - 125.0F, (self.view.frame.size.height / 2.0F) - 150.0F, 250.0F, 250.0F)];
	indicatorView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
	indicatorView.backgroundColor = [UIColor clearColor];
	indicatorView.tag = UTScannerControllerIndicatorViewTag;
	[self.view addSubview:indicatorView];
	[indicatorView release];
	
	[self->m_session startRunning];
}

- (void)viewWillAppear:(BOOL)animated
{
	[super viewWillAppear:animated];
}

- (void)startRunnning
{
	[self->m_session startRunning];
}

#pragma mark NSObject

- (id)init
{
	self = [super init];
	
	if(self) {
		
		self->m_scanner = [[UTScanner alloc] init];
		self->m_scanner.delegate = self;
	}
	
	return self;
}

- (void)dealloc 
{
	[[NSNotificationCenter defaultCenter] removeObserver:self];
	 
	self->m_scanner.delegate = nil;
	[self->m_scanner release];
	
    [super dealloc];
}

@end
