<commit_before>//
//  CliqzSearchViewController.swift
//  BlurredTemptation
//
//  Created by <NAME> on 20/11/14.
//  Copyright (c) 2014 Cliqz. All rights reserved.
//

import UIKit
import WebKit
import Shared
import Storage

protocol SearchViewDelegate: class {
	
	func searchView(SearchViewController: CliqzSearchViewController, didSelectUrl url: NSURL)
	
}

class CliqzSearchViewController : UIViewController, LoaderListener, WKNavigationDelegate, WKScriptMessageHandler, KeyboardHelperDelegate  {
	
	private var searchLoader: SearchLoader!
    var webView: WKWebView?
	weak var delegate: SearchViewDelegate?

	private var historyResults: Array<Dictionary<String, String>> = Array<Dictionary<String, String>>()
	
	var searchQuery: String? {
		didSet {
			self.loadData(searchQuery!)
		}
	}

	override func viewDidLoad() {
        super.viewDidLoad()
		let config = WKWebViewConfiguration()
		let controller = WKUserContentController()
		config.userContentController = controller
		controller.addScriptMessageHandler(self, name: "jsBridge")
        self.webView = WKWebView(frame: self.view.bounds, configuration: config)
		self.webView?.navigationDelegate = self;
        self.view.addSubview(self.webView!)
		let url = NSURL(string: "http://localhost:3005/extension/index.html")
		self.webView!.loadRequest(NSURLRequest(URL: url!))

		KeyboardHelper.defaultHelper.addDelegate(self)
		layoutSearchEngineScrollView()
	}

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
    }

    override func viewWillDisappear(animated: Bool) {
		super.viewWillDisappear(animated)
    }

	func loader(dataLoaded data: Cursor<Site>) {
		self.historyResults.removeAll(keepCapacity: true)
		for site in data {
			var d = Dictionary<String, String>()
			d["url"] = site!.url
			d["title"] = site!.title
			self.historyResults.append(d)
		}
	}

	func loadData(query: String) {
		var JSString: String!
		let q = query.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
//		if q == "" {
//			JSString = "_cliqzNoResults()"
//		} else {
			JSString = "search_mobile('\(q)')"
//		}
		self.webView!.evaluateJavaScript(JSString, completionHandler: nil)
	}

	func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {
		if !navigationAction.request.URL!.absoluteString.hasPrefix("http://localhost:3005/") {
			delegate?.searchView(self, didSelectUrl: navigationAction.request.URL!)
			decisionHandler(.Cancel)
		}
		decisionHandler(.Allow)
	}

	func webView(webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
	}

	func userContentController(userContentController:  WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) {
		switch message.name {
			case "jsBridge":
				if let input = message.body as? NSDictionary {
					if let action = input["action"] as? String {
						let data = input["data"] as? NSDictionary {
						let callback = input["callBack"] as? String {
						handleJSMessage(action, data: data, callback: callback)
					}
				}
		default:
			print("Unhandled JS message: \(message.name)!!!")
			
		}
		/*
		== "interOp" {
			print("Received event \(message.body) --- \(message.name)")
			let input = message.body as! NSDictionary
			let callbakcID = input.objectForKey("callbackId")
			let query = input.objectForKey("query") as? String
			var jsonStr: NSString = ""
			do {
				let json = try NSJSONSerialization.dataWithJSONObject(self.historyResults, options: NSJSONWritingOptions(rawValue: 0))
					jsonStr = NSString(data:json, encoding: NSUTF8StringEncoding)!
			} catch let error as NSError {
				print("Json conversion is failed with error: \(error)")
			}
			let exec = "CLIQZEnvironment.historySearchDone(\(callbakcID!), '\(query!)', '\(jsonStr)');"
			self.webView!.evaluateJavaScript(exec, completionHandler: nil)
		} else if message.name == "linkSelected" {
			let url = message.body as! String
			print("LINK SEL: ---- \(url)")
			delegate?.searchView(self, didSelectUrl: NSURL(string: url)!)
		} else if message.name == "changeUrlVal" {
			let url = message.body as! String
				// TODO: Naira
		}
*/
	}

	private func layoutSearchEngineScrollView() {
		let keyboardHeight = KeyboardHelper.defaultHelper.currentState?.intersectionHeightForView(self.view) ?? 0
		self.webView!.snp_remakeConstraints { make in
			make.top.equalTo(0)
			make.left.right.equalTo(self.view)
			make.bottom.equalTo(self.view).offset(-keyboardHeight)
		}
	}

	private func animateSearchEnginesWithKeyboard(keyboardState: KeyboardState) {
		layoutSearchEngineScrollView()
		
		UIView.animateWithDuration(keyboardState.animationDuration, animations: {
			UIView.setAnimationCurve(keyboardState.animationCurve)
			self.view.layoutIfNeeded()
		})
	}

	func keyboardHelper(keyboardHelper: KeyboardHelper, keyboardWillShowWithState state: KeyboardState) {
		animateSearchEnginesWithKeyboard(state)
	}
	
	func keyboardHelper(keyboardHelper: KeyboardHelper, keyboardDidShowWithState state: KeyboardState) {
	}
	
	func keyboardHelper(keyboardHelper: KeyboardHelper, keyboardWillHideWithState state: KeyboardState) {
		animateSearchEnginesWithKeyboard(state)
	}

	private func handleJSMessage(action: String, data: NSDictionary?, callback: String?) {
		switch action {
			case "searchHistory":
				var jsonStr: NSString = ""
				do {
					let json = try NSJSONSerialization.dataWithJSONObject(self.historyResults, options: NSJSONWritingOptions(rawValue: 0))
					jsonStr = NSString(data:json, encoding: NSUTF8StringEncoding)!
				} catch let error as NSError {
					print("Json conversion is failed with error: \(error)")
				}
				if let c = callback {
					let exec = "\(callback)(\(jsonStr))"
				self.webView!.evaluateJavaScript(exec, completionHandler: nil)
			}
			case "openLink":
				if let url = data["url"] as? String {
					delegate?.searchView(self, didSelectUrl: NSURL(string: url)!)
				}
			case "":
			default
				print("Unhandles JS action: \(action)")
		}
	}
}<commit_msg>Partial changes for JS bridge<commit_after>//
//  CliqzSearchViewController.swift
//  BlurredTemptation
//
//  Created by <NAME> on 20/11/14.
//  Copyright (c) 2014 Cliqz. All rights reserved.
//

import UIKit
import WebKit
import Shared
import Storage

protocol SearchViewDelegate: class {
	
	func searchView(SearchViewController: CliqzSearchViewController, didSelectUrl url: NSURL)
	
}

class CliqzSearchViewController : UIViewController, LoaderListener, WKNavigationDelegate, WKScriptMessageHandler, KeyboardHelperDelegate  {
	
	private var searchLoader: SearchLoader!
    var webView: WKWebView?
	weak var delegate: SearchViewDelegate?

	private var historyResults: Array<Dictionary<String, String>> = Array<Dictionary<String, String>>()
	
	var searchQuery: String? {
		didSet {
			self.loadData(searchQuery!)
		}
	}

	override func viewDidLoad() {
        super.viewDidLoad()
		let config = WKWebViewConfiguration()
		let controller = WKUserContentController()
		config.userContentController = controller
		controller.addScriptMessageHandler(self, name: "jsBridge")
        self.webView = WKWebView(frame: self.view.bounds, configuration: config)
		self.webView?.navigationDelegate = self;
        self.view.addSubview(self.webView!)
		let url = NSURL(string: "http://localhost:3005/extension/index.html")
		self.webView!.loadRequest(NSURLRequest(URL: url!))

		KeyboardHelper.defaultHelper.addDelegate(self)
		layoutSearchEngineScrollView()
	}

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
    }

    override func viewWillDisappear(animated: Bool) {
		super.viewWillDisappear(animated)
    }

	func loader(dataLoaded data: Cursor<Site>) {
		self.historyResults.removeAll(keepCapacity: true)
		for site in data {
			var d = Dictionary<String, String>()
			d["url"] = site!.url
			d["title"] = site!.title
			self.historyResults.append(d)
		}
	}

	func loadData(query: String) {
		var JSString: String!
		let q = query.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
//		if q == "" {
//			JSString = "_cliqzNoResults()"
//		} else {
			JSString = "search_mobile('\(q)')"
//		}
		self.webView!.evaluateJavaScript(JSString, completionHandler: nil)
	}

	func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {
		if !navigationAction.request.URL!.absoluteString.hasPrefix("http://localhost:3005/") {
			delegate?.searchView(self, didSelectUrl: navigationAction.request.URL!)
			decisionHandler(.Cancel)
		}
		decisionHandler(.Allow)
	}

	func webView(webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
	}

	func userContentController(userContentController:  WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) {
		switch message.name {
			case "jsBridge":
				if let input = message.body as? NSDictionary {
					if let action = input["action"] as? String {
						handleJSMessage(action, data: input["data"], callback: input["callBack"] as? String)
					}
				}
		default:
			print("Unhandled JS message: \(message.name)!!!")
			
		}
		/*
		== "interOp" {
			print("Received event \(message.body) --- \(message.name)")
			let input = message.body as! NSDictionary
			let callbakcID = input.objectForKey("callbackId")
			let query = input.objectForKey("query") as? String
			var jsonStr: NSString = ""
			do {
				let json = try NSJSONSerialization.dataWithJSONObject(self.historyResults, options: NSJSONWritingOptions(rawValue: 0))
					jsonStr = NSString(data:json, encoding: NSUTF8StringEncoding)!
			} catch let error as NSError {
				print("Json conversion is failed with error: \(error)")
			}
			let exec = "CLIQZEnvironment.historySearchDone(\(callbakcID!), '\(query!)', '\(jsonStr)');"
			self.webView!.evaluateJavaScript(exec, completionHandler: nil)
		} else if message.name == "linkSelected" {
			let url = message.body as! String
			print("LINK SEL: ---- \(url)")
			delegate?.searchView(self, didSelectUrl: NSURL(string: url)!)
		} else if message.name == "changeUrlVal" {
			let url = message.body as! String
				// TODO: Naira
		}
*/
	}

	private func layoutSearchEngineScrollView() {
		let keyboardHeight = KeyboardHelper.defaultHelper.currentState?.intersectionHeightForView(self.view) ?? 0
		self.webView!.snp_remakeConstraints { make in
			make.top.equalTo(0)
			make.left.right.equalTo(self.view)
			make.bottom.equalTo(self.view).offset(-keyboardHeight)
		}
	}

	private func animateSearchEnginesWithKeyboard(keyboardState: KeyboardState) {
		layoutSearchEngineScrollView()
		
		UIView.animateWithDuration(keyboardState.animationDuration, animations: {
			UIView.setAnimationCurve(keyboardState.animationCurve)
			self.view.layoutIfNeeded()
		})
	}

	func keyboardHelper(keyboardHelper: KeyboardHelper, keyboardWillShowWithState state: KeyboardState) {
		animateSearchEnginesWithKeyboard(state)
	}
	
	func keyboardHelper(keyboardHelper: KeyboardHelper, keyboardDidShowWithState state: KeyboardState) {
	}
	
	func keyboardHelper(keyboardHelper: KeyboardHelper, keyboardWillHideWithState state: KeyboardState) {
		animateSearchEnginesWithKeyboard(state)
	}

	private func handleJSMessage(action: String, data: AnyObject?, callback: String?) {
		switch action {
			case "searchHistory":
				var jsonStr: NSString = ""
				do {
					let json = try NSJSONSerialization.dataWithJSONObject(self.historyResults, options: NSJSONWritingOptions(rawValue: 0))
					jsonStr = NSString(data:json, encoding: NSUTF8StringEncoding)!
				} catch let error as NSError {
					print("Json conversion is failed with error: \(error)")
				}
				if let c = callback {
					let exec = "\(c)(\(jsonStr))"
				self.webView!.evaluateJavaScript(exec, completionHandler: nil)
			}
			case "openLink":
				if let url = data as? String {
					delegate?.searchView(self, didSelectUrl: NSURL(string: url)!)
				}
//			case "":
		default:
				print("Unhandles JS action: \(action)")
		}
	}
}
{'fraction_non_alphanumeric': 0.11514247846255798, 'fraction_numerical': 0.003976143141153081, 'mean_word_length': 4.558471454880294, 'pattern_counts': {'":': 8, '<': 17, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6812163', 'n_tokens_mistral': 4220, 'n_tokens_neox': 3648, 'n_words': 784}