﻿﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

using EOSDigital.API;
using EOSDigital.SDK;

namespace EDSDKLib.API.Base
{
	public sealed class CameraMock : ICamera
	{
		private static List<MemoryStream> _mockImages = new List<MemoryStream>();

		/// <summary>
		/// Fires if any process reports progress
		/// </summary>
		public event ProgressHandler? ProgressChanged;

		/// <summary>
		/// Fires if the live view image is updated
		/// </summary>
		public event LiveViewUpdate? LiveViewUpdated;

		/// <summary>
		/// Fires if an image is ready for download.
		/// Call the <see cref="DownloadFile(DownloadInfo,string)"/> or <see cref="DownloadFile(DownloadInfo)"/> method to get the image or <see cref="CancelDownload"/> to cancel.
		/// </summary>
		public event DownloadHandler? DownloadReady;

		/// <summary>
		/// Fires if a property has changed
		/// </summary>
		public event PropertyChangeHandler? PropertyChanged;

		/// <summary>
		/// Fires if a state has changed
		/// </summary>
		public event StateChangeHandler? StateChanged;

		/// <summary>
		/// Fires if an object has changed
		/// </summary>
		public event ObjectChangeHandler? ObjectChanged;

		/// <summary>
		/// This event fires if the camera is disconnected or has shut down
		/// </summary>
		public event CameraUpdateHandler? CameraHasShutdown;

		/// <summary>
		/// This event fires when the live view loop has ended
		/// </summary>
		public event CameraUpdateHandler? LiveViewStopped;

		/// <summary>
		/// Pointer to the SDKs camera object
		/// </summary>
		public IntPtr Reference { get; }

		/// <summary>
		/// An ID for the camera object in this session. It's essentially the pointer of the Canon SDK camera object
		/// </summary>
		public long ID { get; }

		/// <summary>
		/// States if a session with this camera is open
		/// </summary>
		public bool SessionOpen { get; private set; }

		/// <summary>
		/// States if the camera is disposed. If true, it can't be used anymore
		/// </summary>
		public bool IsDisposed { get; }

		/// <summary>
		/// The name of the camera (can be retrieved without an open session)
		/// </summary>
		public string DeviceName { get; } = "MockCamera";

		/// <summary>
		/// The name of the port the camera is connected to (can be retrieved without an open session)
		/// </summary>
		public string PortName { get; }

		/// <summary>
		/// States if the live view is running on the computer or not
		/// </summary>
		public bool IsLiveViewOn { get; }

		/// <summary>
		/// States if Record property is available for this camera
		/// </summary>
		public bool IsRecordAvailable { get; }

		/// <summary>
		/// Token for the live view runner
		/// </summary>
		private CancellationTokenSource _tokenSource = new CancellationTokenSource();

		/// <summary>
		/// The mock image file infos
		/// </summary>
		private List<FileInfo> mockImageFiles = new List<FileInfo>();


		/// <summary>
		/// the constrcutor
		/// </summary>
		public CameraMock()
		{
			DirectoryInfo di = new DirectoryInfo(Directory.GetCurrentDirectory());
			var imgPath = Path.Combine(di.Parent.Parent.Parent.Parent.FullName, "CameraMockFrames");

			foreach (var f in Directory.GetFiles(imgPath))
			{
				this.mockImageFiles.Add(new FileInfo(f));
				CameraMock._mockImages.Add(new MemoryStream(File.ReadAllBytes(f)));
			}
		}
		
		/// <summary>
		/// Open a new session with camera
		/// </summary>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public void OpenSession()
		{
			if (!this.SessionOpen)
			{
				this.SessionOpen = true;
			}
		}

		/// <summary>
		/// Downloads a file to given directory with the filename in the <see cref="DownloadInfo"/>
		/// </summary>
		/// <param name="Info">The <see cref="DownloadInfo"/> that is provided by the <see cref="DownloadReady"/> event</param>
		/// <param name="directory">The directory where the file will be saved to</param>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="ArgumentNullException">The DownloadInfo is null</exception>
		public void DownloadFile(IDownloadInfo Info, string directory)
		{
			if (this.mockImageFiles.Count == 0)
			{
				throw new InvalidOperationException("No mock images available");
			}

			Random random = new Random();
			int randomIndex = random.Next(0, this.mockImageFiles.Count);
			File.WriteAllBytes(Path.Combine(directory, Info.FileName), File.ReadAllBytes(this.mockImageFiles[randomIndex].FullName));
		}
		
		/// <summary>
		/// Starts the live view
		/// </summary>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public void StartLiveView()
		{
			int loop = 0;
			this._tokenSource = new CancellationTokenSource();
			
			Task.Run(
				async () =>
				{
					while (this.SessionOpen)
					{
						this.LiveViewUpdated?.Invoke(this, CameraMock._mockImages[loop]);
						await Task.Delay(75);
						loop++;
						if (loop == this.mockImageFiles.Count)
							loop = 0;
					}
				}, this._tokenSource.Token);
		}

		/// <summary>
		/// Stops the live view
		/// </summary>
		/// <param name="LVOff">If true, the live view is shut off, if false, the live view will be shown on the cameras screen</param>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public void StopLiveView(bool LVOff = true)
		{
			this._tokenSource.Cancel();
		}

		/// <summary>
		/// Takes a photo with the current camera settings with the TakePicture command
		/// </summary>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		public void TakePhoto()
		{
			Random random = new Random();
			
			this.DownloadReady?.Invoke(this, new DownloadInfoMock()
			{
				FileName = $"MockPhoto_{Guid.NewGuid().ToString()}.jpg"
			});
		}
		
		/// <summary>
		/// Close session with camera
		/// </summary>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public void CloseSession()
		{
		}

		#region unused code
		
		
		/// <summary>
		/// Releases all data and closes session
		/// </summary>
		public void Dispose()
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Takes a photo with the current camera settings asynchronously with the TakePicture command
		/// </summary>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		public void TakePhotoAsync()
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Takes a photo with the current camera settings with the PressShutterButton command
		/// </summary>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		public void TakePhotoShutter()
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Takes a photo with the current camera settings asynchronously with the PressShutterButton command
		/// </summary>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		public void TakePhotoShutterAsync()
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Takes a bulb photo with the current camera settings.
		/// The Tv camera value must be set to Bulb before calling this
		/// </summary>
		/// <param name="bulbTime">The time in ms for how long the shutter will be open</param>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		public void TakePhotoBulb(int bulbTime)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Takes a bulb photo with the current camera settings asynchronously.
		/// The Tv camera value must be set to Bulb before calling this
		/// </summary>
		/// <param name="bulbTime">The time in ms for how long the shutter will be open</param>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		public void TakePhotoBulbAsync(int bulbTime)
		{
			throw new NotImplementedException();
		}



		/// <summary>
		/// Downloads a file into a stream
		/// </summary>
		/// <param name="Info">The <see cref="DownloadInfo"/> that is provided by the <see cref="DownloadReady"/> event</param>
		/// <returns>The stream containing the file data</returns>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="ArgumentNullException">The DownloadInfo is null</exception>
		public Stream DownloadFile(IDownloadInfo Info)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Cancels the download of an image
		/// </summary>
		/// <param name="Info">The DownloadInfo that is provided by the "<see cref="DownloadReady"/>" event</param>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="ArgumentNullException">The DownloadInfo is null</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public void CancelDownload(IDownloadInfo Info)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Gets all volumes available on the camera
		/// </summary>
		/// <returns>An array of CameraFileEntries that are the volumes</returns>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		public CameraFileEntry[] GetAllVolumes()
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Gets all volumes, folders and files existing on the camera
		/// </summary>
		/// <returns>A <see cref="CameraFileEntry"/> that contains all the information</returns>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		public CameraFileEntry GetAllEntries()
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Gets all images saved on the cameras memory card(s)
		/// </summary>
		/// <returns>An array of CameraFileEntries that are the images</returns>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		public CameraFileEntry[] GetAllImages()
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Formats a given camera volume. Get the available volumes with <see cref="GetAllVolumes"/>
		/// <para>Warning: All data on this volume will be lost!</para>
		/// </summary>
		/// <param name="volume">The volume that will get formatted</param>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="ArgumentException">CameraFileEntry is not a volume</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public void FormatVolume(CameraFileEntry volume)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Downloads all given files into a folder. To get all images on the camera, use
		/// <see cref="GetAllImages"/> or for all files <see cref="GetAllEntries"/>
		/// <para>
		/// Note: All given CameraFileEntries will be disposed after this.
		/// Call <see cref="GetAllImages"/> or <see cref="GetAllEntries"/> to get valid entries again.
		/// </para>
		/// </summary>
		/// <param name="folderpath">The path to the folder where the files will be saved to</param>
		/// <param name="files">The files that will be downloaded</param>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		public void DownloadFiles(string folderpath, CameraFileEntry[] files)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Deletes all given files on the camera.
		/// To get all images on the camera, use <see cref="GetAllImages"/> or for all files <see cref="GetAllEntries"/>
		/// <para>Warning: All given files will be lost!</para>
		/// </summary>
		/// <param name="files">The images that will be deleted</param>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		public void DeleteFiles(CameraFileEntry[] files)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Tells the camera how much space is available on the host PC
		/// </summary>
		/// <param name="bytesPerSector">Bytes per HD sector</param>
		/// <param name="numberOfFreeClusters">Number of free clusters on the HD</param>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public void SetCapacity(int bytesPerSector, int numberOfFreeClusters)
		{
		}


		/// <summary>
		/// Locks or unlocks the camera UI
		/// </summary>
		/// <param name="lockState">True to lock, false to unlock</param>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public void UILock(bool lockState)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Gets the list of possible values for the current camera to set.
		/// Only the PropertyIDs "AEModeSelect", "ISO", "Av", "Tv", "MeteringMode" and "ExposureCompensation" are allowed.
		/// </summary>
		/// <param name="propId">The property ID</param>
		/// <returns>A list of available values for the given property ID</returns>
		public CameraValue[] GetSettingsList(PropertyID propId)
		{
			return new CameraValue[0];
		}


		/// <summary>
		/// Sends a command safely to the camera
		/// </summary>
		/// <param name="command">The command</param>
		/// <param name="inParam">Additional parameter</param>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public void SendCommand(CameraCommand command, int inParam = 0)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Sends a Status Command to the camera
		/// </summary>
		/// <param name="command">The command</param>
		/// <param name="inParam">Additional parameter</param>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public void SendStatusCommand(CameraStatusCommand command, int inParam = 0)
		{
			throw new NotImplementedException();
		}


		

		/// <summary>
		/// Starts recording a video
		/// <para>Note: The camera has to be set into filming mode before using this (usually a physical switch on the camera)</para>
		/// <para>This works only on cameras that support filming</para>
		/// </summary>
		/// <param name="PCLiveview">If true, the live view will be transferred to the computer otherwise it's shown on the camera</param>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="InvalidOperationException">The camera is not in film mode</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public void StartFilming(bool PCLiveview)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Stops recording a video
		/// </summary>
		/// <param name="saveFilm">If true, the <see cref="DownloadReady"/> event will fire as soon as the video file is created on the camera</param>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public void StopFilming(bool saveFilm)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Stops recording a video
		/// </summary>
		/// <param name="saveFilm">If true, the <see cref="DownloadReady"/> event will fire as soon as the video file is created on the camera</param>
		/// <param name="stopLiveView">If true, the PC live view will stop and will only be shown on the camera</param>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public void StopFilming(bool saveFilm, bool stopLiveView)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Sets a value for the given property ID
		/// </summary>
		/// <param name="propID">The property ID</param>
		/// <param name="value">The value which will be set</param>
		/// <param name="inParam">Additional property information</param>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public void SetSetting(PropertyID propID, object value, int inParam = 0)
		{
		}


		/// <summary>
		/// Sets a string value for the given property ID
		/// </summary>
		/// <param name="propID">The property ID</param>
		/// <param name="value">The value which will be set</param>
		/// <param name="inParam">Additional property information</param>
		/// <param name="MAX">The maximum length of the string</param>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public void SetSetting(PropertyID propID, string value, int inParam = 0, int MAX = 32)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Sets a struct value for the given property ID
		/// </summary>
		/// <param name="propID">The property ID</param>
		/// <param name="value">The value which will be set</param>
		/// <param name="inParam">Additional property information</param>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public void SetStructSetting<T>(PropertyID propID, T value, int inParam = 0)
			where T : struct
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Gets the current setting of given property ID
		/// </summary>
		/// <param name="propID">The property ID</param>
		/// <param name="inParam">Additional property information</param>
		/// <returns>The current setting of the camera</returns>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public bool GetBoolSetting(PropertyID propID, int inParam = 0)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Gets the current setting of given property ID
		/// </summary>
		/// <param name="propID">The property ID</param>
		/// <param name="inParam">Additional property information</param>
		/// <returns>The current setting of the camera</returns>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public byte GetByteSetting(PropertyID propID, int inParam = 0)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Gets the current setting of given property ID
		/// </summary>
		/// <param name="propID">The property ID</param>
		/// <param name="inParam">Additional property information</param>
		/// <returns>The current setting of the camera</returns>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public short GetInt16Setting(PropertyID propID, int inParam = 0)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Gets the current setting of given property ID
		/// </summary>
		/// <param name="propID">The property ID</param>
		/// <param name="inParam">Additional property information</param>
		/// <returns>The current setting of the camera</returns>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public ushort GetUInt16Setting(PropertyID propID, int inParam = 0)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Gets the current setting of given property ID
		/// </summary>
		/// <param name="propID">The property ID</param>
		/// <param name="inParam">Additional property information</param>
		/// <returns>The current setting of the camera</returns>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public uint GetUInt32Setting(PropertyID propID, int inParam = 0)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Gets the current setting of given property ID
		/// </summary>
		/// <param name="propID">The property ID</param>
		/// <param name="inParam">Additional property information</param>
		/// <returns>The current setting of the camera</returns>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public int GetInt32Setting(PropertyID propID, int inParam = 0)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Gets the current setting of given property ID as a string
		/// </summary>
		/// <param name="propID">The property ID</param>
		/// <param name="inParam">Additional property information</param>
		/// <returns>The current setting of the camera</returns>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public string GetStringSetting(PropertyID propID, int inParam = 0)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Gets the current setting of given property ID as a integer array
		/// </summary>
		/// <param name="propID">The property ID</param>
		/// <param name="inParam">Additional property information</param>
		/// <returns>The current setting of the camera</returns>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public bool[] GetBoolArrSetting(PropertyID propID, int inParam = 0)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Gets the current setting of given property ID as a integer array
		/// </summary>
		/// <param name="propID">The property ID</param>
		/// <param name="inParam">Additional property information</param>
		/// <returns>The current setting of the camera</returns>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public short[] GetInt16ArrSetting(PropertyID propID, int inParam = 0)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Gets the current setting of given property ID as a integer array
		/// </summary>
		/// <param name="propID">The property ID</param>
		/// <param name="inParam">Additional property information</param>
		/// <returns>The current setting of the camera</returns>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public int[] GetInt32ArrSetting(PropertyID propID, int inParam = 0)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Gets the current setting of given property ID as a integer array
		/// </summary>
		/// <param name="propID">The property ID</param>
		/// <param name="inParam">Additional property information</param>
		/// <returns>The current setting of the camera</returns>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public byte[] GetByteArrSetting(PropertyID propID, int inParam = 0)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Gets the current setting of given property ID as a unsigned integer array
		/// </summary>
		/// <param name="propID">The property ID</param>
		/// <param name="inParam">Additional property information</param>
		/// <returns>The current setting of the camera</returns>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public uint[] GetUInt32ArrSetting(PropertyID propID, int inParam = 0)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Gets the current setting of given property ID as a rational array
		/// </summary>
		/// <param name="propID">The property ID</param>
		/// <param name="inParam">Additional property information</param>
		/// <returns>The current setting of the camera</returns>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public Rational[] GetRationalArrSetting(PropertyID propID, int inParam = 0)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Gets the current setting of given property ID as a struct
		/// </summary>
		/// <param name="propID">The property ID</param>
		/// <param name="inParam">Additional property information</param>
		/// <typeparam name="T">One of the EDSDK structs</typeparam>
		/// <returns>The current setting of the camera</returns>
		/// <exception cref="ObjectDisposedException">Camera is disposed</exception>
		/// <exception cref="CameraSessionException">Session is closed</exception>
		/// <exception cref="SDKStateException">Canon SDK is not initialized</exception>
		/// <exception cref="SDKException">An SDK call failed</exception>
		public T GetStructSetting<T>(PropertyID propID, int inParam = 0)
			where T : struct
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// There is an overflow bug in the SDK that messes up the Evf_OutputDevice property.
		/// With this method you can get the adjusted and correct value.
		/// </summary>
		/// <returns>The current output device of the live view</returns>
		public EvfOutputDevice GetEvf_OutputDevice()
		{
			throw new NotImplementedException();
		}
		
		#endregion
	}
}