#import <Foundation/Foundation.h>
#import <WebKit/WebKit.h>
#include "ClientAuth.h"

extern "C" UIViewController* UnityGetGLViewController();

@interface ClientAuth : NSObject<WKNavigationDelegate> {
	WKWebView* webView;
	NSString* scheme;
	NSString* responseUri;
}
- (void)dispose;
@end

@implementation ClientAuth

- (id)initWithTransparent:(BOOL)transparent {
	self= [super init];
	UIView* view= UnityGetGLViewController().view;
	webView= [[WKWebView alloc] initWithFrame:view.frame];
	webView.navigationDelegate= self;
	if(transparent) {
		webView.opaque= NO;
		webView.backgroundColor= [UIColor clearColor];
	}
	webView.autoresizingMask= UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
	webView.hidden= YES;
	[view addSubview:webView];
	return self;
}

- (void)dispose {
	WKWebView* webView_= webView;
	webView= nil;
	webView_.navigationDelegate= nil;
	[webView_ stopLoading];
	[webView_ removeFromSuperview];
	scheme= nil;
	responseUri= nil;
}

- (void)webView:(WKWebView*)webView didFailProvisionalNavigation:(WKNavigation*)navigation withError:(NSError*)error {
	NSLog(@"Provisional navigation failed: %@", error.description);
}

- (void)webView:(WKWebView*)webView didFailNavigation:(WKNavigation*)navigation withError:(NSError*)error {
	NSLog(@"Navigation failed: %@", error.description);
}

- (void)webView:(WKWebView*)wkWebView
		decidePolicyForNavigationAction:(WKNavigationAction*)navigationAction
		decisionHandler:(void(^)(WKNavigationActionPolicy))decisionHandler {
	if(webView == nil) {
		decisionHandler(WKNavigationActionPolicyCancel);
	} else {
		NSString* url= [[navigationAction.request URL] absoluteString];
		if([url hasPrefix:scheme]) {
			responseUri= url;
			decisionHandler(WKNavigationActionPolicyCancel);
		} else {
			decisionHandler(WKNavigationActionPolicyAllow);
		}
	}
}

- (void)setMargins:(int)left top:(int)top right:(int)right bottom:(int)bottom {
	if(webView != nil) {
		UIView* view= UnityGetGLViewController().view;
		CGRect frame= webView.frame;
		CGRect screen= view.bounds;
		CGFloat scale= 1.0 / [self getScale:view];
		frame.size.width= screen.size.width - scale * (left + right);
		frame.size.height= screen.size.height - scale * (top + bottom);
		frame.origin.x= scale * left;
		frame.origin.y= scale * top;
		webView.frame= frame;
	}
}

- (CGFloat)getScale:(UIView*)view {
	if([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
		return view.window.screen.nativeScale;
	}
	return view.contentScaleFactor;
}

- (void)setVisibility:(BOOL)visibility {
	if(webView != nil) {
		webView.hidden= visibility ? NO : YES;
	}
}

- (void)loadURL:(char const*)url_ withScheme:(char const*)scheme_ {
	if(webView != nil) {
		NSURL* url= [NSURL URLWithString:[NSString stringWithUTF8String:url_]];
		NSURLRequest* request= [NSURLRequest requestWithURL:url];
		scheme= [NSString stringWithUTF8String:scheme_];
		[webView loadRequest:request];
	}
}

- (char*)getResponseUri {
	return responseUri == nil ? nullptr : strdup([responseUri UTF8String]);
}

- (void)cancel {
	responseUri= @"";
}

@end

void* ClientAuth_Init(bool transparent) {
	id instance= [[ClientAuth alloc] initWithTransparent:transparent];
	return (__bridge_retained void*)instance;
}

void ClientAuth_Destroy(void* instance) {
	auto* clientAuth= (__bridge_transfer ClientAuth*)instance;
	[clientAuth dispose];
	clientAuth= nil;
}

void ClientAuth_SetMargins(void* instance, int left, int top, int right, int bottom) {
	auto* clientAuth= (__bridge ClientAuth*)instance;
	[clientAuth setMargins:left top:top right:right bottom:bottom];
}

void ClientAuth_SetVisibility(void* instance, bool visibility) {
	auto* clientAuth= (__bridge ClientAuth*)instance;
	[clientAuth setVisibility:visibility];
}

void ClientAuth_LoadURL(void* instance, char const* url, char const* scheme) {
	auto* clientAuth= (__bridge ClientAuth*)instance;
	[clientAuth loadURL:url withScheme:scheme];
}

char* ClientAuth_GetResponseUri(void* instance) {
	auto* clientAuth= (__bridge ClientAuth*)instance;
	return [clientAuth getResponseUri];
}

void ClientAuth_Cancel(void* instance) {
	auto* clientAuth= (__bridge ClientAuth*)instance;
	[clientAuth cancel];
}

void ClientAuth_ClearCookies() {
	auto* cookieStorage= [NSHTTPCookieStorage sharedHTTPCookieStorage];
	[[cookieStorage cookies] enumerateObjectsUsingBlock:^(NSHTTPCookie* cookie, NSUInteger, BOOL*) {
		[cookieStorage deleteCookie:cookie];
	}];
}
