<commit_before>//
//  QueueManager.swift
//  IGZQueueManager
//
//  Created by <NAME> on 9/27/16.
//
//  Copyright (c) 2016 <NAME> (http://miahpoisson.com)
//
//	Permission is hereby granted, free of charge, to any person obtaining a copy
//	of this software and associated documentation files (the "Software"), to deal
//	in the Software without restriction, including without limitation the rights
//	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//	copies of the Software, and to permit persons to whom the Software is
//	furnished to do so, subject to the following conditions:
//
//	The above copyright notice and this permission notice shall be included in
//	all copies or substantial portions of the Software.
//
//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//	THE SOFTWARE.

import Foundation

// MARK: - Types  -
public typealias IGZNetworkSuccess = ((Any?) -> Void)
public typealias IGZNetworkFailure = ((NSError?) -> Void)
public typealias PackageParams = [String: Any]
public typealias PackageHeaders = [String: String]
public typealias IGZQueueName = String

// MARK: - Errors -
public enum IGZ_NetworkErrors : Error {
	
	// Queue Errors
	case queueNameUnavailable
	case queueDoesNotExists
	case cannotRemoveDefaultQueue
	
	// Package Errors
	case packageHandlerNotSet
	case packageUnknownError
	case packageQueueDoesNotExist
}

// MARK: - Queue Manager Class -

/**
 * Main manager class. This will handle the adding and removing of queues 
 * as well as calling the handlers to send the network call or apply any
 * needed Authentication.
 *
 * Calling `IGZQueue.QueueManager.manager` will give you the default shared
 * manager. If you want to create your own manager you can call `IGZQueue.QueueManager()`.
 *
 * The queue manager comes with a default queue names `GENERAL`.
 */
public class QueueManager {
	
	public static let manager = QueueManager()
	
	/// Flag indicating if debug mode is on
	fileprivate var debug : Bool = false
	
	/// Default Queue that willbe preloaded into the queues dict
	fileprivate var GENERAL_QUEUE_NAME : IGZQueueName = "GENERAL"
	
	/// Dict of queues that are available. Defaults with a general queue available
	fileprivate var queues : [String: DispatchQueue] = [String: DispatchQueue]()
	
	/// The handler responsible for making the network call
	fileprivate var networkHandler : IGZNetworkHandlerProtocol?
	
	/// The handler responsible for making any authentication adjustments to the package
	fileprivate var authenticationHandler : IGZNAuthenticationProtocol?
	
	public init() {
		self.removeAllQueues()
	}
	
}

// MARK: - Authentication extension -
extension QueueManager {
	
	/**
	Set the authentication handle to use. The handler must adhere to the `IGZNAuthenticationProtocol`.
	
	- parameter handler: The authentication handler
	*/
	public func setAuthenticationHandler<T: IGZNAuthenticationProtocol>(_ handler: T) {
		self.authenticationHandler = handler
	}
	
}

// MARK: - Network Handler Extentions -
extension QueueManager {
	
	/**
	Use this method to set the network handler to use. This handler will allow you to
	integrate this manager with any network system available. The handler needs to
	implement the `IGZNetworkHandlerProtocol` so the `IGZNetworkingQueue` can call
	your handler when making a network call.
	
	- parameter handler:	A custom class hooking this network manager up with another manager.
	*/
	public func setNetworkHandler<T: IGZNetworkHandlerProtocol>(_ handler: T) {
		self.networkHandler = handler
	}
	
	/**
	Use this method to make a network call.
	
	- throws:
		- `IGZ_NetworkErrors.packageHandlerNotSet` if the network handler has not been set
		- `IGZ_NetworkErrors.queueDoesNotExists` if the requested queue does not exist
		- `IGZ_NetworkErrors.packageUnknownError` if an unknown error occurs. This should never be thrown...
	
	- parameters:
		- url:		The `NSURL` the package is going to
		- method:	The type of request to make. Refer to `PackageMethod` for available types
		- queue:	The name of the queue to add the call into. This must be a `String`
		- params:	The parameter dictionary to send along with the package
		- success:	The success callback to make when the call has been successful
		- failure:	The failure callback to make when the call has failed for any reason
	*/
	public func createPackage(_ url: URL, method: PackageMethod, queue: IGZQueueName, params: PackageParams, success: @escaping IGZNetworkSuccess, failure: @escaping IGZNetworkFailure) throws {
		
		do {
			let package = Package(action: url, method: method, queue: queue, parameters: params, headers: [:], success: success, failure: failure)
			try queuePackage(package.queue, package: package)
		} catch IGZ_NetworkErrors.packageHandlerNotSet {
			throw IGZ_NetworkErrors.packageHandlerNotSet
		} catch IGZ_NetworkErrors.queueDoesNotExists {
			throw IGZ_NetworkErrors.queueDoesNotExists
		} catch {
			throw IGZ_NetworkErrors.packageQueueDoesNotExist
		}
		<commit_msg>Update createPackage(_:method:queue:params:success:failure:) to accept a nil queue parameter<commit_after>//
//  QueueManager.swift
//  IGZQueueManager
//
//  Created by <NAME> on 9/27/16.
//
//  Copyright (c) 2016 <NAME> (http://miahpoisson.com)
//
//	Permission is hereby granted, free of charge, to any person obtaining a copy
//	of this software and associated documentation files (the "Software"), to deal
//	in the Software without restriction, including without limitation the rights
//	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//	copies of the Software, and to permit persons to whom the Software is
//	furnished to do so, subject to the following conditions:
//
//	The above copyright notice and this permission notice shall be included in
//	all copies or substantial portions of the Software.
//
//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//	THE SOFTWARE.

import Foundation

// MARK: - Types  -
public typealias IGZNetworkSuccess = ((Any?) -> Void)
public typealias IGZNetworkFailure = ((NSError?) -> Void)
public typealias PackageParams = [String: Any]
public typealias PackageHeaders = [String: String]
public typealias IGZQueueName = String

// MARK: - Errors -
public enum IGZ_NetworkErrors : Error {
	
	// Queue Errors
	case queueNameUnavailable
	case queueDoesNotExists
	case cannotRemoveDefaultQueue
	
	// Package Errors
	case packageHandlerNotSet
	case packageUnknownError
	case packageQueueDoesNotExist
}

// MARK: - Queue Manager Class -

/**
 * Main manager class. This will handle the adding and removing of queues 
 * as well as calling the handlers to send the network call or apply any
 * needed Authentication.
 *
 * Calling `IGZQueue.QueueManager.manager` will give you the default shared
 * manager. If you want to create your own manager you can call `IGZQueue.QueueManager()`.
 *
 * The queue manager comes with a default queue names `GENERAL`.
 */
public class QueueManager {
	
	public static let manager = QueueManager()
	
	/// Flag indicating if debug mode is on
	fileprivate var debug : Bool = false
	
	/// Default Queue that willbe preloaded into the queues dict
	fileprivate var GENERAL_QUEUE_NAME : IGZQueueName = "GENERAL"
	
	/// Dict of queues that are available. Defaults with a general queue available
	fileprivate var queues : [String: DispatchQueue] = [String: DispatchQueue]()
	
	/// The handler responsible for making the network call
	fileprivate var networkHandler : IGZNetworkHandlerProtocol?
	
	/// The handler responsible for making any authentication adjustments to the package
	fileprivate var authenticationHandler : IGZNAuthenticationProtocol?
	
	public init() {
		self.removeAllQueues()
	}
	
}

// MARK: - Authentication extension -
extension QueueManager {
	
	/**
	Set the authentication handle to use. The handler must adhere to the `IGZNAuthenticationProtocol`.
	
	- parameter handler: The authentication handler
	*/
	public func setAuthenticationHandler<T: IGZNAuthenticationProtocol>(_ handler: T) {
		self.authenticationHandler = handler
	}
	
}

// MARK: - Network Handler Extentions -
extension QueueManager {
	
	/**
	Use this method to set the network handler to use. This handler will allow you to
	integrate this manager with any network system available. The handler needs to
	implement the `IGZNetworkHandlerProtocol` so the `IGZNetworkingQueue` can call
	your handler when making a network call.
	
	- parameter handler:	A custom class hooking this network manager up with another manager.
	*/
	public func setNetworkHandler<T: IGZNetworkHandlerProtocol>(_ handler: T) {
		self.networkHandler = handler
	}
	
	/**
	Use this method to make a network call.
	
	- throws:
		- `IGZ_NetworkErrors.packageHandlerNotSet` if the network handler has not been set
		- `IGZ_NetworkErrors.queueDoesNotExists` if the requested queue does not exist
		- `IGZ_NetworkErrors.packageUnknownError` if an unknown error occurs. This should never be thrown...
	
	- parameters:
		- url:		The `NSURL` the package is going to
		- method:	The type of request to make. Refer to `PackageMethod` for available types
		- queue:	The name of the queue to add the call into. This must be a `String` or nil. If nil is passed the general queue will be used
		- params:	The parameter dictionary to send along with the package
		- success:	The success callback to make when the call has been successful
		- failure:	The failure callback to make when the call has failed for any reason
	*/
	public func createPackage(_ url: URL, method: PackageMethod, queue: IGZQueueName?, params: PackageParams, success: @escaping IGZNetworkSuccess, failure: @escaping IGZNetworkFailure) throws {
		
		do {
			let package = Package(action: url, method: method, queue: (queue == nil ? GENERAL_QUEUE_NAME : queue!), parameters: params, headers: [:], success: success, failure: failure)
			try queuePackage(package.queue, package: package)
		} catch IGZ_NetworkErrors.packageHandlerNotSet {
			throw IGZ_NetworkErrors.packageHandlerNotSet
		} catch IGZ_NetworkErrors.queueDoesNotExists {
			throw IGZ_NetworkErrors.queueDoesNotExists
		} catch {
			throw IGZ_NetworkErrors.packageQueueDoesNotExist
		}
		
{'fraction_non_alphanumeric': 0.07159142726858185, 'fraction_numerical': 0.0016415868673050615, 'mean_word_length': 4.098093909809391, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 15, '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': '4103267', 'n_tokens_mistral': 3142, 'n_tokens_neox': 2895, 'n_words': 1286}