from datetime import datetime
from construct import (
    Array,
    Byte,
    Container,
    Embedded,
    Enum,
    ExprAdapter,
    Pass,
    PrefixedArray,
    Range,
    Struct,
    Switch,
)

import logging
logger = logging.getLogger(__name__)

class EOSPropertiesMixin(object):

    def _EOSImageSize(self):
        return Enum(
            self._UInt32,
            default=Pass,
            Large=0x00,
            Medium=0x01,
            Small=0x02,
            S1=0x0e,
            S2=0x0f,
            S3=0x10,
        )

    def _EOSImageType(self):
        return Enum(
            self._UInt32,
            default=Pass,
            JPEG=0x01,
            RAW=0x06,
        )

    def _EOSImageCompression(self):
        return Enum(
            self._UInt32,
            default=Pass,
            Standard=0x02,
            Fine=0x03,
            Lossless=0x04,
        )

    def _EOSImageFormat(self):
        return PrefixedArray(
            self._UInt32,
            Struct(
                'Bytes' / self._UInt32,
                'Type' / self._EOSImageType,
                'Size' / self._EOSImageSize,
                'Compression' / self._EOSImageCompression,
            )
        )

    def _EOSWhiteBalance(self):
        return Enum(
            self._UInt32,
            default=Pass,
            Auto=0,
            Daylight=1,
            Cloudy=2,
            Tungsten=3,
            Fluorescent=4,
            Custom=6,
            FluorescentH=7,
            ColorTemperature=9,
            CustomWhitebalancePC1=10,
            CustomWhitebalancePC2=11,
	        CustomWhitebalancePC3=12,
	        MissingNumber=13,
        )

    def _EOSFocusMode(self):
        return Enum(
            self._UInt32,
            default=Pass,
            OneShot=0,
            AIServo=1,
            AIFocus=2,
            Manual=3,
        )

    def _DataType(self, **product_datatypes):
        '''Dictionary for EOS property constructors'''
        canon_datatypes = {
            'EpochTime': ExprAdapter(
                self._UInt32,
                encoder=lambda obj, ctx:
                int((obj - datetime(1970, 1, 1)).total_seconds()),
                decoder=lambda obj, ctx: datetime.fromtimestamp(obj)
            ),
            'ImageFormat': self._EOSImageFormat,
            'Compression': self._EOSImageCompression,
            'WhiteBalance': self._EOSWhiteBalance,
            'FocusMode': self._EOSFocusMode,
        }
        canon_datatypes.update(product_datatypes if product_datatypes else {})
        return super(EOSPropertiesMixin, self)._DataType(**canon_datatypes)

    # Expected datatypes per `_EOSPropertyCode`
    _EOSDataTypeCode = {
            'Aperture': None,
            'ShutterSpeed': None,
            'ISO': None,
            'ExposureCompensation': None,
            'ShootingMode': None,
            'DriveMode': None,
            'ExposureMeteringMode': None,
            'AutoFocusMode': 'FocusMode',
            'WhiteBalance': 'WhiteBalance',
            'ColorTemperature': None,
            'WhiteBalanceAdjustBA': 'Int32',
            'WhiteBalanceAdjustMG': 'Int32',
            'WhiteBalanceBracketBA': 'UInt32',
            'WhiteBalanceBracketMG': 'UInt32',
            'ColorSpace': None,
            'PictureStyle': None,
            'CameraTime': 'EpochTime',
            'BatteryPower': None,
            'BatterySelect': None,
            'AutoPowerOff': None,
            'Owner': None,
            'ModelID': None,
            'PTPExtensionVersion': None,
            'DPOFVersion': None,
            'AvailableShots': 'UInt32',
            'CaptureDestination': None,
            'BracketMode': None,
            'CurrentStorage': None,
            'CurrentFolder': None,
            'ImageFormat': 'ImageFormat',
            'ImageFormatCF': 'ImageFormat',
            'ImageFormatSD': 'ImageFormat',
            'ImageFormatHDD': 'ImageFormat',
            'CompressionS': 'Compression',
            'CompressionM1': 'Compression',
            'CompressionM2': 'Compression',
            'CompressionL': 'Compression',
            'AEModeDial': None,
            'AEModeCustom': None,
            'MirrorUpSetting': None,
            'HighlightTonePriority': None,
            'AFSelectFocusArea': None,
            'HDRSetting': None,
            'PCWhiteBalance1': None,
            'PCWhiteBalance2': None,
            'PCWhiteBalance3': None,
            'PCWhiteBalance4': None,
            'PCWhiteBalance5': None,
            'MWhiteBalance': None,
            'MWhiteBalanceEx': None,
            'PictureStyleStandard': None,
            'PictureStylePortrait': None,
            'PictureStyleLandscape': None,
            'PictureStyleNeutral': None,
            'PictureStyleFaithful': None,
            'PictureStyleBlackWhite': None,
            'PictureStyleAuto': None,
            'PictureStyleUserSet1': None,
            'PictureStyleUserSet2': None,
            'PictureStyleUserSet3': None,
            'PictureStyleParam1': None,
            'PictureStyleParam2': None,
            'PictureStyleParam3': None,
            'HighISOSettingNoiseReduction': None,
            'MovieServoAF': None,
            'ContinuousAFValid': None,
            'Attenuator': None,
            'UTCTime': 'EpochTime',
            'Timezone': None,
            'Summertime': None,
            'FlavorLUTParams': None,
            'CustomFunc1': None,
            'CustomFunc2': None,
            'CustomFunc3': None,
            'CustomFunc4': None,
            'CustomFunc5': None,
            'CustomFunc6': None,
            'CustomFunc7': None,
            'CustomFunc8': None,
            'CustomFunc9': None,
            'CustomFunc10': None,
            'CustomFunc11': None,
            'CustomFunc12': None,
            'CustomFunc13': None,
            'CustomFunc14': None,
            'CustomFunc15': None,
            'CustomFunc16': None,
            'CustomFunc17': None,
            'CustomFunc18': None,
            'CustomFunc19': None,
            'InnerDevelop': None,
            'MultiAspect': None,
            'MovieSoundRecord': None,
            'MovieRecordVolume': None,
            'WindCut': None,
            'ExtenderType': None,
            'OLCInfoVersion': None,
            'CustomFuncEx': None,
            'MyMenu': None,
            'MyMenuList': None,
            'WftStatus': None,
            'WftInputTransmission': None,
            'HDDDirectoryStructure': None,
            'BatteryInfo': None,
            'AdapterInfo': None,
            'LensStatus': None,
            'QuickReviewTime': None,
            'CardExtension': None,
            'TempStatus': None,
            'ShutterCounter': None,
            'SpecialOption': None,
            'PhotoStudioMode': None,
            'SerialNumber': None,
            'EVFOutputDevice': None,
            'EVFMode': None,
            'DepthOfFieldPreview': None,
            'EVFSharpness': None,
            'EVFWBMode': None,
            'EVFClickWBCoeffs': None,
            'EVFColorTemp': None,
            'ExposureSimMode': None,
            'EVFRecordStatus': None,
            'LvAfSystem': None,
            'MovSize': None,
            'LvViewTypeSelect': None,
            'MirrorDownStatus': None,
            'MovieParam': None,
            'MirrorLockupState': None,
            'FlashChargingState': None,
            'AloMode': None,
            'FixedMovie': None,
            'OneShotRawOn': None,
            'ErrorForDisplay': None,
            'AEModeMovie': None,
            'BuiltinStroboMode': None,
            'StroboDispState': None,
            'StroboETTL2Metering': None,
            'ContinousAFMode': None,
            'MovieParam2': None,
            'StroboSettingExpComposition': None,
            'MovieParam3': None,
            'LVMedicalRotate': None,
            'Artist': None,
            'Copyright': None,
            'BracketValue': None,
            'FocusInfoEx': None,
            'DepthOfField': None,
            'Brightness': None,
            'LensAdjustParams': None,
            'EFComp': None,
            'LensName': None,
            'AEB': None,
            'StroboSetting': None,
            'StroboWirelessSetting': None,
            'StroboFiring': None,
            'LensID': None,
            'LCDBrightness': None,
            'CADarkBright': None,
        }
