<commit_before>/**
 * Defines the main service of Ionicitude.
 * This is the service that you will inject into your controllers in order to use the Wikitude cordova plugin functions and the service functions.
 */
angular
	.module('ionicitude-module')
	.factory('Ionicitude', Ionicitude);

/* @ngInject */
function Ionicitude($q) {
	/**
	 * Defines the service object that will be publicly accessible when injecting the Ionicitude service.
	 * @type {Object}
	 */
	var service = {
		checkDevice: checkDevice,
		deviceSupportsFeatures: false,
		init: init,
		launchAR: launchAR,
		addAction: addAction,
		listLibActions: listLibActions,
		captureScreen: captureScreen,
		ready: ready,
		// Wikitude API wrapper. Will be set by init()
		close: null,
		hide: null,
		show: null,
		callJavaScript: null,
		setLocation: null
	};

	/**
	 * This is a simple flag to prevent calling the init() public method twice.
	 * @type {boolean}
	 */
	var initialized = false;

	/**
	 * Defines the value of the url protocol used by Wikitude to call the app from within the AR View.
	 * This value MUST NOT be altered in any way since it's an internal Wikitude mechanism.
	 * @type {String}
	 */
	var protocol = 'architectsdk://';

	/**
	 * This will store the WikitudePlugin for subsequent uses, after a call to getPlugin().
	 */
	var plugin;

	/**
	 * This is where all the custom Actions that can be called from within an AR View will be stored at runtime, using the addAction() method.
	 * @type {Object}
	 */
	var lib = {};

	/**
	 * This is where any request made with the ready() function while Ionicitude is not fully initialized will be stored, waiting to be executed.
	 * @type {Array}
	 */
	var requestsQueue = [];

	/**
	 * Defines the default settings of the Wikitude service.
	 * Each of these settings can be defined when calling the init() method.
	 * @type {Object}
	 */
	var settings = {
		/**
		 * Additionnals world load config.
		 * For now, there's only one such setting available for the Wikitude plugin : camera_position.
		 */
		worldLoadConfig: {camera_position: 'back'},
		/**
		 * Defines which features your AR app needs the device to support.
		 * For now, only two features are available in the cordova WikitudePlugin.
		 * The first one is 'geo' and is used for any ARchitect World that wants to rely on the user's location.
		 * The second is '2d_tracking' and is used for any ARchitect World that wants to use image recognition and image tracking.
		 * More information : http://www.wikitude.com/developer/documentation/phonegap.
		 * @type {Array}
		 */
		reqFeatures: ['geo', '2d_tracking'],
		/**
		 * Defines where in your app are stored all your ARchitect World folders.
		 * This folder should contain sub-folders, one for each of your AR World.
		 * @type {String}
		 */
		worldsRootFolder: 'wikitude-worlds'
	};

	return service;

	//////////////////// PUBLIC SERVICE METHODS ////////////////////

	/**
	 * Should be used when wanting to call any sensitive Ionicitude's method - like launchAR() - while not being sure if the plugin will be fully initialized
	 * by the time its method is called.
	 * Since Ionicitude.init() is asynchronous when performing the device check, your AR World could be launch before the initialization process is fully resolved,
	 * causing an UnsupportedFeatureError to be falsly raised.
	 * The parameter must be a function that should encapsulate the code you want to execute. Much like $ionicPlatform.ready() function.
	 * @param {Function} request An anonymous function encapsulating the code to execute when Ionicitude's plugin is completely initialized.
	 */
	function ready(request) {
		if (initialized && angular.isFunction(request)) request();
		else requestsQueue.push(request);
	}

	/**
	 * Debug method that returns a list of the current Actions that you added using the addAction() method.
	 */
	function listLibActions() {
		console.log(Object.getOwnPropertyNames(lib));
		return Object.getOwnPropertyNames(lib);
	}

	/**
	 * Allows the user to take a screenshot with the app, while being in an AR view.
	 * This is just a wrapper aroune the Wikitude Plugin method, that uses promises instead of callback.
	 * See Wikitude documentation for more information: http://www.wikitude.com/external/doc/documentation/latest/phonegap/referencephonegap.html#capturescreen.
	 * @param withUI A boolean indicating whether the screenshot should take the UI into account
	 * @param fileName If given, the screenshot will be saved in the device storage. If not, the screenshot will be saved in the device picture galery
	 * @returns {Promise} A promise of a screen captured.
	 */
	function captureScreen(withUI, fileName) {
		if (typeof withUI !== 'boolean') throw new TypeError('Ionicitude - captureScreen() expects first parameter to be of type \'boolean\', \'' + typeof withUI + '\' given.');
		if (fileName !== null && typeof fileName !== 'string') throw new TypeError('Ionicitude - captureScreen() expects second parameter to be \'null\' or of type \'string\', \'' + typeof fileName + '\' given.');
		var q = $q.defer();
		plugin.captureScreen(function (success) {
			q.resolve(success);
		}, function (error) {
			q.reject(error);
		}, withUI, fileName);
		return q.promise;
	}

	/**
	 * Adds an Action to the Ionicitude Action Library that can then be triggered by an AR View, with a 'document.location' statement.
	 * You can add an action by either passing a name and an anonymous callback, or just a named callback.
	 * The Ionicitude Service is returned so that you can chain calls to addAction().
	 * @param {string|function} nameOrFunction The name of the function to add if it's a string, or the function to add if it's a named function.
	 * @param {null|function}callback The function to add, if the first argument is a String.
	 * @return {Object} The Ionicitude service
	 * @throws TypeError
	 * @throws SyntaxError
	 */
	function addAction(nameOrFunction, callback) {
		if (angular.isString(nameOrFunction)) {
			if (!callback) throw new TypeError('Ionicitude - addAction() expects a second argument if first argument is of type \'string\'.');
			if (typeof callback !== 'function') throw new TypeError('Ionicitude - addAction() expects second argument to only be of type \'function\', \'' + typeof callback + '\' given.');
			checkUsedName(nameOrFunction);
			lib[nameOrFunction] = callback;
		} else if (angular.isFunction(nameOrFunction)) {
			var name = nameOrFunction.name;
			if (!name) throw new TypeError('Ionicitude - addAction() do not accept anonymous function as first argument. Please, try passing a named function instead.');
			checkUsedName(name);
			lib[name] = nameOrFunction;
		} else {
			throw new TypeError('Ionicitude - addAction() expects first argument to be only of type \'string\' or \'function\', \'' + typeof nameOrFunction + '\' given');
		}
		return service;

		/**
		 * Checks if the desired name for this new Action has already been registered or is already used in Ionicitude library.
		 * @param name
		 */
		function checkUsedName(name) {
			if (lib.hasOwnProperty(name)) throw new SyntaxError('Ionicitude - addAction() - The name \'' + name + '\' has already been added or is a reserved Ionicitude name.');
		}
	}

	/**
	 * Checks if the device supports the features needed by the AR World.
	 * The result of this check is available through the deviceSupportsFeatures property of the Ionicitude service
	 * for it to be used later (alerting the user that he's/she's device is not compatible, for instance).
	 * @return {Promise} A promise of a check result.
	 */
	function checkDevice() {
		console.log('checking device');
		var q = $q.defer();
		plugin.isDeviceSupported(function (success) {
			console.log(success);
			service.deviceSupportsFeatures = true;
			q.resolve(success);
		}, function (error) {
			console.log(error);
			service.deviceSupportsFeatures = false;
			q.reject(error);
		}, settings.reqFeatures);
		return q.promise;
	}

	/**
	 * Initializes the Ionicitude service, then returns a promise. If resolved, this promise returns the service.
	 * You can pass an object argument to this method to change it's default behavior or change some of Ionicitude's default settings.
	 * This object can have the following properties :
	 * - customCallback: A function that you want to set as your app's Custom Handling Mechanism (CHM). If not provided, the Ionicitude's CHM will be used.
	 * - doDeviceCheck: Default TRUE. Pass FALSE to skip the checkDevice() method call. If you do, you'll need to manually call the method later on.
	 * - reqFeatures: An array of strings indicating which features are required by your app. Can be 'geo', '2d_tracking' or both.
	 * - worldLoadConfig: An object of additionnals world load settings.
	 * - worldsRootFolder: A string that references your app's folder in which your AR Worlds' folders are stored.
	 * @param params An object to alter the init behavior or change default settings.
	 * @returns {Promise} A promise of the initialization.
	 */
	function init(params) {
		return $q(function (resolve, reject) {
			if (!initialized) {
				console.log('init service starting');
				loadPlugin()
					.then(setWrappers)
					.then(setCallback)
					.then(function () {
						if (doDeviceCheck()) {
							return checkDevice();
						} else {
							return console.log('check skipped due to init settings');
						}
					})
					.then(handleSettings)
					.then(function () {
						initialized = true;
					})<commit_msg>Fixed bad string constant<commit_after>/**
 * Defines the main service of Ionicitude.
 * This is the service that you will inject into your controllers in order to use the Wikitude cordova plugin functions and the service functions.
 */
angular
	.module('ionicitude-module')
	.factory('Ionicitude', Ionicitude);

/* @ngInject */
function Ionicitude($q) {
	/**
	 * Defines the service object that will be publicly accessible when injecting the Ionicitude service.
	 * @type {Object}
	 */
	var service = {
		checkDevice: checkDevice,
		deviceSupportsFeatures: false,
		init: init,
		launchAR: launchAR,
		addAction: addAction,
		listLibActions: listLibActions,
		captureScreen: captureScreen,
		ready: ready,
		// Wikitude API wrapper. Will be set by init()
		close: null,
		hide: null,
		show: null,
		callJavaScript: null,
		setLocation: null
	};

	/**
	 * This is a simple flag to prevent calling the init() public method twice.
	 * @type {boolean}
	 */
	var initialized = false;

	/**
	 * Defines the value of the url protocol used by Wikitude to call the app from within the AR View.
	 * This value MUST NOT be altered in any way since it's an internal Wikitude mechanism.
	 * @type {String}
	 */
	var protocol = 'architectsdk://';

	/**
	 * This will store the WikitudePlugin for subsequent uses, after a call to getPlugin().
	 */
	var plugin;

	/**
	 * This is where all the custom Actions that can be called from within an AR View will be stored at runtime, using the addAction() method.
	 * @type {Object}
	 */
	var lib = {};

	/**
	 * This is where any request made with the ready() function while Ionicitude is not fully initialized will be stored, waiting to be executed.
	 * @type {Array}
	 */
	var requestsQueue = [];

	/**
	 * Defines the default settings of the Wikitude service.
	 * Each of these settings can be defined when calling the init() method.
	 * @type {Object}
	 */
	var settings = {
		/**
		 * Additionnals world load config.
		 * For now, there's only one such setting available for the Wikitude plugin : camera_position.
		 */
		worldLoadConfig: {camera_position: 'back'},
		/**
		 * Defines which features your AR app needs the device to support.
		 * For now, only two features are available in the cordova WikitudePlugin.
		 * The first one is 'geo' and is used for any ARchitect World that wants to rely on the user's location.
		 * The second is 'image_tracking' and is used for any ARchitect World that wants to use image recognition and image tracking.
		 * More information : http://www.wikitude.com/developer/documentation/phonegap.
		 * @type {Array}
		 */
		reqFeatures: ['geo', 'image_tracking'],
		/**
		 * Defines where in your app are stored all your ARchitect World folders.
		 * This folder should contain sub-folders, one for each of your AR World.
		 * @type {String}
		 */
		worldsRootFolder: 'wikitude-worlds'
	};

	return service;

	//////////////////// PUBLIC SERVICE METHODS ////////////////////

	/**
	 * Should be used when wanting to call any sensitive Ionicitude's method - like launchAR() - while not being sure if the plugin will be fully initialized
	 * by the time its method is called.
	 * Since Ionicitude.init() is asynchronous when performing the device check, your AR World could be launch before the initialization process is fully resolved,
	 * causing an UnsupportedFeatureError to be falsly raised.
	 * The parameter must be a function that should encapsulate the code you want to execute. Much like $ionicPlatform.ready() function.
	 * @param {Function} request An anonymous function encapsulating the code to execute when Ionicitude's plugin is completely initialized.
	 */
	function ready(request) {
		if (initialized && angular.isFunction(request)) request();
		else requestsQueue.push(request);
	}

	/**
	 * Debug method that returns a list of the current Actions that you added using the addAction() method.
	 */
	function listLibActions() {
		console.log(Object.getOwnPropertyNames(lib));
		return Object.getOwnPropertyNames(lib);
	}

	/**
	 * Allows the user to take a screenshot with the app, while being in an AR view.
	 * This is just a wrapper aroune the Wikitude Plugin method, that uses promises instead of callback.
	 * See Wikitude documentation for more information: http://www.wikitude.com/external/doc/documentation/latest/phonegap/referencephonegap.html#capturescreen.
	 * @param withUI A boolean indicating whether the screenshot should take the UI into account
	 * @param fileName If given, the screenshot will be saved in the device storage. If not, the screenshot will be saved in the device picture galery
	 * @returns {Promise} A promise of a screen captured.
	 */
	function captureScreen(withUI, fileName) {
		if (typeof withUI !== 'boolean') throw new TypeError('Ionicitude - captureScreen() expects first parameter to be of type \'boolean\', \'' + typeof withUI + '\' given.');
		if (fileName !== null && typeof fileName !== 'string') throw new TypeError('Ionicitude - captureScreen() expects second parameter to be \'null\' or of type \'string\', \'' + typeof fileName + '\' given.');
		var q = $q.defer();
		plugin.captureScreen(function (success) {
			q.resolve(success);
		}, function (error) {
			q.reject(error);
		}, withUI, fileName);
		return q.promise;
	}

	/**
	 * Adds an Action to the Ionicitude Action Library that can then be triggered by an AR View, with a 'document.location' statement.
	 * You can add an action by either passing a name and an anonymous callback, or just a named callback.
	 * The Ionicitude Service is returned so that you can chain calls to addAction().
	 * @param {string|function} nameOrFunction The name of the function to add if it's a string, or the function to add if it's a named function.
	 * @param {null|function}callback The function to add, if the first argument is a String.
	 * @return {Object} The Ionicitude service
	 * @throws TypeError
	 * @throws SyntaxError
	 */
	function addAction(nameOrFunction, callback) {
		if (angular.isString(nameOrFunction)) {
			if (!callback) throw new TypeError('Ionicitude - addAction() expects a second argument if first argument is of type \'string\'.');
			if (typeof callback !== 'function') throw new TypeError('Ionicitude - addAction() expects second argument to only be of type \'function\', \'' + typeof callback + '\' given.');
			checkUsedName(nameOrFunction);
			lib[nameOrFunction] = callback;
		} else if (angular.isFunction(nameOrFunction)) {
			var name = nameOrFunction.name;
			if (!name) throw new TypeError('Ionicitude - addAction() do not accept anonymous function as first argument. Please, try passing a named function instead.');
			checkUsedName(name);
			lib[name] = nameOrFunction;
		} else {
			throw new TypeError('Ionicitude - addAction() expects first argument to be only of type \'string\' or \'function\', \'' + typeof nameOrFunction + '\' given');
		}
		return service;

		/**
		 * Checks if the desired name for this new Action has already been registered or is already used in Ionicitude library.
		 * @param name
		 */
		function checkUsedName(name) {
			if (lib.hasOwnProperty(name)) throw new SyntaxError('Ionicitude - addAction() - The name \'' + name + '\' has already been added or is a reserved Ionicitude name.');
		}
	}

	/**
	 * Checks if the device supports the features needed by the AR World.
	 * The result of this check is available through the deviceSupportsFeatures property of the Ionicitude service
	 * for it to be used later (alerting the user that he's/she's device is not compatible, for instance).
	 * @return {Promise} A promise of a check result.
	 */
	function checkDevice() {
		console.log('checking device');
		var q = $q.defer();
		plugin.isDeviceSupported(function (success) {
			console.log(success);
			service.deviceSupportsFeatures = true;
			q.resolve(success);
		}, function (error) {
			console.log(error);
			service.deviceSupportsFeatures = false;
			q.reject(error);
		}, settings.reqFeatures);
		return q.promise;
	}

	/**
	 * Initializes the Ionicitude service, then returns a promise. If resolved, this promise returns the service.
	 * You can pass an object argument to this method to change it's default behavior or change some of Ionicitude's default settings.
	 * This object can have the following properties :
	 * - customCallback: A function that you want to set as your app's Custom Handling Mechanism (CHM). If not provided, the Ionicitude's CHM will be used.
	 * - doDeviceCheck: Default TRUE. Pass FALSE to skip the checkDevice() method call. If you do, you'll need to manually call the method later on.
	 * - reqFeatures: An array of strings indicating which features are required by your app. Can be 'geo', 'image_tracking' or both.
	 * - worldLoadConfig: An object of additionnals world load settings.
	 * - worldsRootFolder: A string that references your app's folder in which your AR Worlds' folders are stored.
	 * @param params An object to alter the init behavior or change default settings.
	 * @returns {Promise} A promise of the initialization.
	 */
	function init(params) {
		return $q(function (resolve, reject) {
			if (!initialized) {
				console.log('init service starting');
				loadPlugin()
					.then(setWrappers)
					.then(setCallback)
					.then(function () {
						if (doDeviceCheck()) {
							return checkDevice();
						} else {
							return console.log('check skipped due to init settings');
						}
					})
					.then(handleSettings)
					.then(function () {
						initialized = true;
					})
{'fraction_non_alphanumeric': 0.09750698360828546, 'fraction_numerical': 0.00015811943287830075, 'mean_word_length': 3.636852394916911, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, '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': '6783187', 'n_tokens_mistral': 5585, 'n_tokens_neox': 4980, 'n_words': 2265}