//
//  QSICamera.h
//  QSICamera
//
//  Copyright (c) 2011, 2012, Joe Shimkus
//   All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//  	• 	Redistributions of source code must retain the above copyright
//      	notice, this list of conditions and the following disclaimer.
//  	• 	Redistributions in binary form must reproduce the above copyright
//        notice, this list of conditions and the following disclaimer in the
//        documentation and/or other materials provided with the distribution.
//  	• 	The name of Joe Shimkus may not be used to endorse or promote
//        products derived from this software without specific prior written
//        permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
//  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
//  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
//  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

#import "QSIObject.h"

#import "QSICameraParameters.h"
#import "QSICameraState.h"
#import "QSIComms.h"
#import "QSICameraExposureRequest.h"
#import "QSICameraDefaults.h"

#define QSICameraAltMode1ExposurePulseOutputBit 0x01
#define QSICameraAltMode1ManualShutterModeBit   0x02
#define QSICameraAltMode1HostTimedExposureBit   0x04
#define QSICameraAltMode1ManualShutterOpenBit   0x10
#define QSICameraAltMode1ManualShutterCloseBit  0x20

@protocol QSICamera <QSIComms>
- (QSIStatus) abortExposure;
- (QSIStatus) advancedDetails : (out QSICameraAdvancedDetails * *) anAdvancedDetails;
- (QSIStatus) advancedSettings : (out QSICameraAdvancedSettingsParameters * *) anAdvancedSettings;
- (QSIStatus) autoZeroControl : (out QSICameraAutoZeroControl * *) anAutoZeroControl;

- (QSIStatus) cameraState : (out QSICameraState *) aCameraState;
- (QSIStatus) canAbortExposure : (out bool *) aCanAbortExposure;
- (QSIStatus) canGetCoolerPower : (out bool *) aCanGetCoolerPower;
- (QSIStatus) canPulseGuide : (out bool *) aCanPulseGuide;
- (QSIStatus) canSetReadoutSpeed : (out bool *) aCanSetReadoutSpeed;
- (QSIStatus) canSetTemperature : (out bool *) aCanSetTemperature;
- (QSIStatus) ccdHeight : (out uint16_t *) aHeight;
- (QSIStatus) ccdTargetTemperature : (out double *) aTargetTemperature;
- (QSIStatus) ccdTemperature : (out double *) aCCDTemperature;
- (QSIStatus) ccdWidth : (out uint16_t *) aWidth;
- (bool)      colorCamera;
- (QSIStatus) columnBinning : (out uint16_t *) aBinning;
- (QSIStatus) combinedDetails : (out QSICameraCombinedDetails * *) aCombinedDetails;
- (QSIStatus) connect;
- (QSIStatus) coolerPower : (out double *) aCoolerPower;

- (QSIStatus) electronsPerADU : (out double *) anElectronsPerADU;
- (QSIStatus) exposeForDuration : (in uint32_t) aDuration
                withShutterOpen : (in bool) aShutterOpen;
- (QSIStatus) exposeUsingRequest : (in QSICameraExposureRequest *) anExposureRequest;
- (QSIStatus) exposureHeight : (out uint16_t *) aHeight;
- (QSIStatus) exposureLastDuration : (out uint32_t *) aDuration;
- (QSIStatus) exposureSettings : (out QSICameraExposureParameters * *) anExposureSettings;
- (QSIStatus) exposureStartingColumn : (out uint16_t *) aColumn;
- (QSIStatus) exposureStartingRow : (out uint16_t *) aRow;
- (QSIStatus) exposureWidth : (out uint16_t *) aWidth;

- (QSIStatus) fanMode : (out QSICameraFanMode *) aFanMode;
- (QSIStatus) filterCount : (out uint8_t *) aFilterCount;
- (QSIStatus) filterPosition : (out uint8_t *) aFilterPosition;
- (QSIStatus) filterWheelConnected : (out bool *) aFilterWheelConnected;
- (QSIStatus) focusOffset : (out int32_t *) aFocusOffset
                forFilter : (in uint8_t) aFilterPosition;
- (QSIStatus) fullWellCapacity : (out double *) aFullWellCapacity;

- (QSIStatus) getName : (out NSString * *) aName
            forFilter : (in uint8_t) aFilterPosition;

- (QSIStatus) hasFilterWheel : (out bool *) aHasFilterWheel;
- (QSIStatus) hasShutter : (out bool *) aHasShutter;
- (QSIStatus) heatsinkTemperature : (out double *) aHeatsinkTemperature;

- (QSIStatus) imageArray : (inout NSMutableData * *) anImageArray;
- (QSIStatus) imageArrayWidth : (out uint16_t *) aWidth
                       height : (out uint16_t *) aHeight
               andElementSize : (out uint16_t *) anElementSize;
- (QSIStatus) imageIsReady : (out bool *) anImageIsReady;
- (QSIStatus) isCoolerOn : (out bool *) aIsCoolerOn;
- (QSIStatus) isLEDEnabled : (out bool *) anLEDEnabled;
- (QSIStatus) isMainCamera : (out bool *) aMainCamera;
- (QSIStatus) isPulseGuiding : (out bool *) anIsPulseGuiding;
- (QSIStatus) isSoundEnabled : (out bool *) aSoundEnabled;

- (QSIStatus) maxADU : (out uint32_t *) aMaxADU;
- (QSIStatus) maxColumnBinning : (out uint16_t *) aBinning;
- (QSIStatus) maxPixelsPerBlock : (out int32_t *) aMaxPixelsPerBlock;
- (QSIStatus) maxRowBinning : (out uint16_t *) aBinning;
- (QSIStatus) modelName : (out NSString * *) aModelName;
- (QSIStatus) modelNumber : (out NSString * *) aModelNumber;

- (QSIStatus) pixelHeight : (out double *) aHeight;
- (QSIStatus) pixelWidth : (out double *) aWidth;
- (QSIStatus) powerOfTwoBinning : (out bool *) aPowerOfTwoBinning;
- (QSIStatus) pulseGuide : (in QSICameraGuiding) aGuideDirection
            withDuration : (in uint16_t) aDuration;

- (QSIStatus) readoutSpeed : (out QSICameraReadoutSpeed *) aReadoutSpeed;
- (QSIStatus) rowBinning : (out uint16_t *) aBinning;

- (QSIStatus) serialNumber : (out NSString * *) aSerialNumber;
- (QSIStatus) setAntiBlooming : (in QSICameraAntiBloom) anAntiBlooming;
- (QSIStatus) setCCDTargetTemperature : (in double) aTargetTemperature;
- (QSIStatus) setColumnBinning : (in uint16_t) aBinning;
- (QSIStatus) setCoolerOn : (in bool) aCoolerOn;
- (QSIStatus) setExposureWidth : (in uint16_t) aWidth;
- (QSIStatus) setExposureHeight : (in uint16_t) aHeight;
- (QSIStatus) setExposureStartingColumn : (in uint16_t) aColumn;
- (QSIStatus) setExposureStartingRow : (in uint16_t) aRow;
- (QSIStatus) setFanMode : (in QSICameraFanMode) aFanMode;
- (QSIStatus) setFilterPosition : (in uint8_t) aFilterPosition;
- (QSIStatus) setFocusOffset : (in int32_t) aFocusOffset
                   forFilter : (in uint8_t) aFilterPosition;
- (QSIStatus) setGain : (in QSICameraGain) aGain;
- (QSIStatus) setLEDEnabled : (in bool) anLEDEnabled;
- (QSIStatus) setMainCamera : (in bool) aMainCamera;
- (QSIStatus) setMaxPixelsPerBlock : (in int32_t) aMaxPixelsPerBlock;
- (QSIStatus) setName : (in NSString *) aName
            forFilter : (in uint8_t) aFilterPosition;
- (QSIStatus) setPreExposureFlush : (in QSICameraPreExposureFlush) aPreExposureFlush;
- (QSIStatus) setReadoutSpeed : (in QSICameraReadoutSpeed) aReadoutSpeed;
- (QSIStatus) setRowBinning : (in uint16_t) aBinning;
- (QSIStatus) setShutterPriority : (in QSICameraShutterPriority) aShutterPriority;
- (QSIStatus) setSoundEnabled : (in bool) aSoundEnabled;
- (QSIStatus) supportsAsymmetricBinning : (out bool *) aSupportsAsymmetricBinning;

- (QSIStatus) temperature : (out QSICameraTemperature * *) aTemperature;
@end // @protocol QSICamera <QSIComms>

@interface QSICamera : QSIObject <QSICamera>
{
@private
  QSICameraDefaults                   *_cameraDefaults;

  QSICameraAdvancedDetails            *_advancedDetails;
  QSICameraAdvancedSettingsParameters *_advancedSettings;
  QSICameraAutoZero                   *_autoZero;
  QSICameraAutoZeroControl            *_autoZeroControl;

  bool                                _cameraStateCacheInvalid;
  bool                                _colorProfiling;
  QSICameraCombinedDetails            *_combinedDetails;
  QSIComms                            *_commsObject;
  uint8_t                             _currentFilterPosition;

  int32_t                             _exposureHeight;
  uint32_t                            _exposureLastDuration;
  QSICameraExposureParameters         *_exposureSettings;
  bool                                _exposureTaken;
  bool                                _exposureUseFast;
  int32_t                             _exposureWidth;

  NSMutableArray                      *_filters;

  NSString                            *_firmwareVersion;
  NSString                            *_hardwareVersion;
  bool                                _isMainCamera;

  bool                                _imageIsDownloading;
  bool                                _imageIsValid;
  bool                                _imageDownloadPending;

  int32_t                             _maxPixelsPerBlock;
  int32_t                             _numberOfPixelsRead;

  int32_t                             _overscanAdjustment;
  uint16_t                            _overscanLastMean;
  uint16_t                            _overscanPixels[8192];

  NSMutableData                       *_readoutBuffer;

  bool                                _testBayerImage;
}
@end // @interface QSICamera : QSIObject <QSICamera>

@interface QSICamera (QSICameraPublicClassMethods)
+ (Class) cameraClassFromComms : (QSIComms *) aComms;
+ (uint16_t) extendedReadTimeout;
+ (uint16_t) extendedWriteTimeout;
+ (uint16_t) shortReadTimeout;
+ (uint16_t) shortWriteTimeout;
+ (uint16_t) standardReadTimeout;
+ (uint16_t) standardWriteTimeout;

+ (NSArray *) simulatedCameras;
@end // @interface QSICamera (QSICameraPublicClassMethods)

@interface QSICamera (QSICameraPublicInstanceMethods)
- (id) initWithComms : (QSIComms *) aCommsObject;
@end // @interface QSICamera (QSICameraPublicInstanceMethods)
