import Foundation
import Phidget22_C

/**
Phidget Data Adapter Introduction  The Data Adapter class is used to interface third party devices and microcontrollers with Phidgets.
*/
public class LEDArrayBase : Phidget {

	public init() {
		var h: PhidgetHandle?
		PhidgetLEDArray_create(&h)
		super.init(h!)
		initializeEvents()
	}

	internal override init(_ handle: PhidgetHandle) {
		super.init(handle)
	}

	deinit {
		if (retained) {
			Phidget_release(&chandle)
		} else {
			uninitializeEvents()
			PhidgetLEDArray_delete(&chandle)
		}
	}

	/**
	The lowest LED address.

	- returns:
	Lowest LED address

	- throws:
	An error of type `PhidgetError`
	*/
	public func getMinAddress() throws -> UInt32 {
		let result: PhidgetReturnCode
		var minAddress: UInt32 = 0
		result = PhidgetLEDArray_getMinAddress(chandle, &minAddress)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
		return minAddress
	}

	/**
	The highest LED address. When using a `ColorOrder` with a white component (e.g., RGBW), this is reduced to 1535.

	- returns:
	Highest LED address

	- throws:
	An error of type `PhidgetError`
	*/
	public func getMaxAddress() throws -> UInt32 {
		let result: PhidgetReturnCode
		var maxAddress: UInt32 = 0
		result = PhidgetLEDArray_getMaxAddress(chandle, &maxAddress)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
		return maxAddress
	}

	/**
	Display an animation. For more information, visit our [LEDArray API Guide](https://www.phidgets.com/docs/LEDArray_API_Guide#Animations).

	- throws:
	An error of type `PhidgetError`

	- parameters:
		- animationID: The ID of the animation.
		- pattern: The LED pattern to animate.
		- animation: The animation parameters.
	*/
	public func setAnimation(animationID: Int, pattern: [LEDArrayColor], animation: LEDArrayAnimation) throws {
		let result: PhidgetReturnCode
		let patternTmp = UnsafeMutablePointer<PhidgetLEDArray_Color>.allocate(capacity: pattern.count)
		defer { patternTmp.deallocate() }
		for i in 0..<pattern.count {
			patternTmp[i] = pattern[i].cstruct
		}
		let patternLen: Int = pattern.count
		var animationTmp = animation.cstruct
		result = PhidgetLEDArray_setAnimation(chandle, Int32(animationID), patternTmp, patternLen, &animationTmp)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
	}

	/**
	The lowest AnimationID.

	- returns:
	Lowest AnimationID

	- throws:
	An error of type `PhidgetError`
	*/
	public func getMinAnimationID() throws -> Int {
		let result: PhidgetReturnCode
		var minAnimationID: Int32 = 0
		result = PhidgetLEDArray_getMinAnimationID(chandle, &minAnimationID)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
		return Int(minAnimationID)
	}

	/**
	The highest AnimationID.

	- returns:
	Highest AnimationID

	- throws:
	An error of type `PhidgetError`
	*/
	public func getMaxAnimationID() throws -> Int {
		let result: PhidgetReturnCode
		var maxAnimationID: Int32 = 0
		result = PhidgetLEDArray_getMaxAnimationID(chandle, &maxAnimationID)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
		return Int(maxAnimationID)
	}

	/**
	The minimum size of the LEDArrayColor array when using animations.

	- returns:
	Minimum pattern count

	- throws:
	An error of type `PhidgetError`
	*/
	public func getMinAnimationPatternCount() throws -> UInt32 {
		let result: PhidgetReturnCode
		var minAnimationPatternCount: UInt32 = 0
		result = PhidgetLEDArray_getMinAnimationPatternCount(chandle, &minAnimationPatternCount)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
		return minAnimationPatternCount
	}

	/**
	The maximum size of the LEDArrayColor array when using animations. When using a `ColorOrder` with a white component (e.g., RGBW), this is reduced to 96.

	- returns:
	Maximum pattern count

	- throws:
	An error of type `PhidgetError`
	*/
	public func getMaxAnimationPatternCount() throws -> UInt32 {
		let result: PhidgetReturnCode
		var maxAnimationPatternCount: UInt32 = 0
		result = PhidgetLEDArray_getMaxAnimationPatternCount(chandle, &maxAnimationPatternCount)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
		return maxAnimationPatternCount
	}

	/**
	The brightness value will apply to all LEDs. For more information, visit our [LEDArray API Guide](https://www.phidgets.com/docs/LEDArray_API_Guide#Brightness).

	- returns:
	Brightness value

	- throws:
	An error of type `PhidgetError`
	*/
	public func getBrightness() throws -> Double {
		let result: PhidgetReturnCode
		var brightness: Double = 0
		result = PhidgetLEDArray_getBrightness(chandle, &brightness)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
		return brightness
	}

	/**
	The brightness value will apply to all LEDs. For more information, visit our [LEDArray API Guide](https://www.phidgets.com/docs/LEDArray_API_Guide#Brightness).

	- throws:
	An error of type `PhidgetError`

	- parameters:
		- brightness: Brightness value
	*/
	public func setBrightness(_ brightness: Double) throws {
		let result: PhidgetReturnCode
		result = PhidgetLEDArray_setBrightness(chandle, brightness)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
	}

	/**
	The minimum brightness.

	- returns:
	Minimum brightness

	- throws:
	An error of type `PhidgetError`
	*/
	public func getMinBrightness() throws -> Double {
		let result: PhidgetReturnCode
		var minBrightness: Double = 0
		result = PhidgetLEDArray_getMinBrightness(chandle, &minBrightness)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
		return minBrightness
	}

	/**
	The maximum brightness.

	- returns:
	Maximum brightness

	- throws:
	An error of type `PhidgetError`
	*/
	public func getMaxBrightness() throws -> Double {
		let result: PhidgetReturnCode
		var maxBrightness: Double = 0
		result = PhidgetLEDArray_getMaxBrightness(chandle, &maxBrightness)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
		return maxBrightness
	}

	/**
	Turn off all LEDs. Any active animations will be stopped. For more information, visit our [LEDArray API Guide](https://www.phidgets.com/docs/LEDArray_API_Guide#Clear).

	- throws:
	An error of type `PhidgetError`
	*/
	public func clearLEDs() throws {
		let result: PhidgetReturnCode
		result = PhidgetLEDArray_clearLEDs(chandle)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
	}

	/**
	Specify the order of colors expected by your LEDs. For more information, visit our [LEDArray API Guide](https://www.phidgets.com/docs/LEDArray_API_Guide#Color_Order).

	- returns:
	LED Color Order

	- throws:
	An error of type `PhidgetError`
	*/
	public func getColorOrder() throws -> LEDArrayColorOrder {
		let result: PhidgetReturnCode
		var colorOrder: PhidgetLEDArray_ColorOrder = LED_COLOR_ORDER_RGB
		result = PhidgetLEDArray_getColorOrder(chandle, &colorOrder)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
		return LEDArrayColorOrder(rawValue: colorOrder.rawValue)!
	}

	/**
	Specify the order of colors expected by your LEDs. For more information, visit our [LEDArray API Guide](https://www.phidgets.com/docs/LEDArray_API_Guide#Color_Order).

	- throws:
	An error of type `PhidgetError`

	- parameters:
		- colorOrder: LED Color Order
	*/
	public func setColorOrder(_ colorOrder: LEDArrayColorOrder) throws {
		let result: PhidgetReturnCode
		result = PhidgetLEDArray_setColorOrder(chandle, PhidgetLEDArray_ColorOrder(colorOrder.rawValue))
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
	}

	/**
	The minimum fade time.

	- returns:
	Minimum fade time

	- throws:
	An error of type `PhidgetError`
	*/
	public func getMinFadeTime() throws -> UInt32 {
		let result: PhidgetReturnCode
		var minFadeTime: UInt32 = 0
		result = PhidgetLEDArray_getMinFadeTime(chandle, &minFadeTime)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
		return minFadeTime
	}

	/**
	The maximum fade time.

	- returns:
	Maximum fade time

	- throws:
	An error of type `PhidgetError`
	*/
	public func getMaxFadeTime() throws -> UInt32 {
		let result: PhidgetReturnCode
		var maxFadeTime: UInt32 = 0
		result = PhidgetLEDArray_getMaxFadeTime(chandle, &maxFadeTime)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
		return maxFadeTime
	}

	/**
	The gamma value to apply to brightnesses. PC monitors typically to use 2.2. For more information, visit our [LEDArray API Guide](https://www.phidgets.com/docs/LEDArray_API_Guide#Gamma).

	- returns:
	Gamma value

	- throws:
	An error of type `PhidgetError`
	*/
	public func getGamma() throws -> Double {
		let result: PhidgetReturnCode
		var gamma: Double = 0
		result = PhidgetLEDArray_getGamma(chandle, &gamma)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
		return gamma
	}

	/**
	The gamma value to apply to brightnesses. PC monitors typically to use 2.2. For more information, visit our [LEDArray API Guide](https://www.phidgets.com/docs/LEDArray_API_Guide#Gamma).

	- throws:
	An error of type `PhidgetError`

	- parameters:
		- gamma: Gamma value
	*/
	public func setGamma(_ gamma: Double) throws {
		let result: PhidgetReturnCode
		result = PhidgetLEDArray_setGamma(chandle, gamma)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
	}

	/**
	The minimum value gamma can be set to. Gamma values less than 1 are unsuitable for most applications.

	- returns:
	Minimum gamma

	- throws:
	An error of type `PhidgetError`
	*/
	public func getMinGamma() throws -> UInt32 {
		let result: PhidgetReturnCode
		var minGamma: UInt32 = 0
		result = PhidgetLEDArray_getMinGamma(chandle, &minGamma)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
		return minGamma
	}

	/**
	The maximum value that gamma can be set to.

	- returns:
	Maximum gamma

	- throws:
	An error of type `PhidgetError`
	*/
	public func getMaxGamma() throws -> UInt32 {
		let result: PhidgetReturnCode
		var maxGamma: UInt32 = 0
		result = PhidgetLEDArray_getMaxGamma(chandle, &maxGamma)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
		return maxGamma
	}

	/**
	Set the color of a single of LED

	- throws:
	An error of type `PhidgetError`

	- parameters:
		- address: The address of the LED.
		- color: The color.
		- fadeTime: The time to fade from the previous state in milliseconds.
	*/
	public func setLED(address: UInt32, color: LEDArrayColor, fadeTime: UInt32) throws {
		let result: PhidgetReturnCode
		var colorTmp = color.cstruct
		result = PhidgetLEDArray_setLED(chandle, address, &colorTmp, fadeTime)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
	}

	/**
	The minimum size of the LEDArrayColor array when using `setLED()` or `setLEDs()`.

	- returns:
	Minimum size of the LED array

	- throws:
	An error of type `PhidgetError`
	*/
	public func getMinLEDCount() throws -> UInt32 {
		let result: PhidgetReturnCode
		var minLEDCount: UInt32 = 0
		result = PhidgetLEDArray_getMinLEDCount(chandle, &minLEDCount)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
		return minLEDCount
	}

	/**
	The maximum size of the LEDArrayColor array when using `setLED()` or `setLEDs()`. When using a `ColorOrder` with a white component (e.g., RGBW), this is reduced to 1536.

	- returns:
	Maximum size of the LED array

	- throws:
	An error of type `PhidgetError`
	*/
	public func getMaxLEDCount() throws -> UInt32 {
		let result: PhidgetReturnCode
		var maxLEDCount: UInt32 = 0
		result = PhidgetLEDArray_getMaxLEDCount(chandle, &maxLEDCount)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
		return maxLEDCount
	}

	/**
	Set the colors of a segment of LEDs

	- throws:
	An error of type `PhidgetError`

	- parameters:
		- startAddress: The address of the first LED in the segment.
		- endAddress: The address of the last LED in the segment.
		- leds: The color pattern. This will be repeated or truncated as necessary to fill the space between startAddress and endAddress
		- fadeTime: The time to fade from the previous state in milliseconds.
	*/
	public func setLEDs(startAddress: UInt32, endAddress: UInt32, leds: [LEDArrayColor], fadeTime: UInt32) throws {
		let result: PhidgetReturnCode
		let ledsTmp = UnsafeMutablePointer<PhidgetLEDArray_Color>.allocate(capacity: leds.count)
		defer { ledsTmp.deallocate() }
		for i in 0..<leds.count {
			ledsTmp[i] = leds[i].cstruct
		}
		let ledsLen: Int = leds.count
		result = PhidgetLEDArray_setLEDs(chandle, startAddress, endAddress, ledsTmp, ledsLen, fadeTime)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
	}

	/**
	Set the colors of a segment of LEDs

	- parameters:
		- startAddress: The address of the first LED in the segment.
		- endAddress: The address of the last LED in the segment.
		- leds: The color pattern. This will be repeated or truncated as necessary to fill the space between startAddress and endAddress
		- fadeTime: The time to fade from the previous state in milliseconds.
		- completion: Asynchronous completion callback
	*/
	public func setLEDs(startAddress: UInt32, endAddress: UInt32, leds: [LEDArrayColor], fadeTime: UInt32, completion: @escaping (ErrorCode) -> ()) {
		let callback = AsyncCallback(completion)
		let callbackCtx = Unmanaged.passRetained(callback)
		let ledsTmp = UnsafeMutablePointer<PhidgetLEDArray_Color>.allocate(capacity: leds.count)
		defer { ledsTmp.deallocate() }
		for i in 0..<leds.count {
			ledsTmp[i] = leds[i].cstruct
		}
		let ledsLen: Int = leds.count
		PhidgetLEDArray_setLEDs_async(chandle, startAddress, endAddress, ledsTmp, ledsLen, fadeTime, AsyncCallback.nativeAsyncCallback, UnsafeMutableRawPointer(callbackCtx.toOpaque()))
	}

	/**
	Control power to all LEDs. For more information, visit our [LEDArray API Guide](https://www.phidgets.com/docs/LEDArray_API_Guide#PowerEnabled).

	- returns:
	Control power to all LEDs

	- throws:
	An error of type `PhidgetError`
	*/
	public func getPowerEnabled() throws -> Bool {
		let result: PhidgetReturnCode
		var powerEnabled: Int32 = 0
		result = PhidgetLEDArray_getPowerEnabled(chandle, &powerEnabled)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
		return (powerEnabled == 0 ? false : true)
	}

	/**
	Control power to all LEDs. For more information, visit our [LEDArray API Guide](https://www.phidgets.com/docs/LEDArray_API_Guide#PowerEnabled).

	- throws:
	An error of type `PhidgetError`

	- parameters:
		- powerEnabled: Control power to all LEDs
	*/
	public func setPowerEnabled(_ powerEnabled: Bool) throws {
		let result: PhidgetReturnCode
		result = PhidgetLEDArray_setPowerEnabled(chandle, (powerEnabled ? 1 : 0))
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
	}

	/**
	Disable the specified animation.

	- throws:
	An error of type `PhidgetError`

	- parameters:
		- animationID: The ID of the animation to disable
	*/
	public func stopAnimation(animationID: Int) throws {
		let result: PhidgetReturnCode
		result = PhidgetLEDArray_stopAnimation(chandle, Int32(animationID))
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
	}

	/**
	Restart all animations at the same time.

	- throws:
	An error of type `PhidgetError`
	*/
	public func synchronizeAnimations() throws {
		let result: PhidgetReturnCode
		result = PhidgetLEDArray_synchronizeAnimations(chandle)
		if result != EPHIDGET_OK {
			throw (PhidgetError(code: result))
		}
	}

}
