import DocumentDetector

public enum SDKError: Error {
    case invalidFormatMessage(String)
    case requiredMethodMessage(String)
}

private struct DecoderSettings: Decodable {
    let documentDetectorFlow: [DocumentDetectorStep]?
    let cafStage: DDCAFStage?
    let personId: String?
    let analyticsSettings: Bool?
    let popupSettings: Bool?
    let networkSettings: Double?
    let sensorSettings: SensorSettingsDeserializer.SensorSettingsStruct?
    let proxySettings: DDProxySettings?
    let previewSettings: PreviewSettingsDeserializer.PreviewSettingsStruct?
    let compressSettings: CGFloat?
    let manualCaptureSettings: ManualCaptureSettingsDeserializer.ManualCaptureSettingsStruct?
    let enableMultiLanguage: Bool?
    let imageUrlExpireTime: String?
    let currentStepDoneDelay: Double?
    let resolutionSettings: CafResolution?
    let allowedPassportList: [DDCountryCodes]?
    let uploadSettings: DDUploadSettings?
    let messageSettings: MessageSettingsDeserializer.MessageSettingsStruct?
    let style: DocumentDetectorLayout?
    let colorConfiguration: ColorConfiguration?

    
    private enum CodingKeys: String, CodingKey {
        case messageSettings
    }
    
    init(from decoder: Decoder) throws {
        documentDetectorFlow = try DocumentDetectorFlowDeserializer(from: decoder).getDocumentDetectorFlow
        cafStage = try CafStageDeserializer(from: decoder).getCafStage
        personId = try PersonIdDeserializer(from: decoder).getPersonId
        analyticsSettings = try AnalyticsSettingsDeserializer(from: decoder).getAnalyticsSettings
        popupSettings = try PopupSettingsDeserializer(from: decoder).getPopupSettings
        networkSettings = try NetworkSettingsDeserializer(from: decoder).getNetworkSettings
        sensorSettings = try SensorSettingsDeserializer(from: decoder).getSensotSettings
        proxySettings = try ProxySettingsDeserializer(from: decoder).getProxySettings
        previewSettings = try PreviewSettingsDeserializer(from: decoder).getPreviewSettings
        compressSettings = try CompressSettingsDeserializer(from: decoder).getCompressSettings
        manualCaptureSettings = try ManualCaptureSettingsDeserializer(from: decoder).getManualCaptureSettings
        enableMultiLanguage = try EnableMultiLanguageDeserializer(from: decoder).getEnableMultiLanguage
        imageUrlExpireTime = try ImageUrlExpireTimeDeserializer(from: decoder).getImageUrlExpireTime
        currentStepDoneDelay = try CurrentStepDoneDelayDeserializer(from: decoder).getCurrentStepDoneDelay
        resolutionSettings = try ResolutionSettingsDeserializer(from: decoder).getResolutionSettings
        allowedPassportList = try AllowedPassportListDeserializer(from: decoder).getAllowedPassportList
        uploadSettings = try UploadSettingsDeserializer(from: decoder).getUploadSettings
        messageSettings = try MessageSettingsDeserializer(from: decoder).getMessageSettings
        style = try StyleDeserializer(from: decoder).getStyle
        colorConfiguration = try StyleDeserializer(from: decoder).getColorConfiguration
    }
}

class DocumentDetectorDecoder {
    private var decodedSettings: DecoderSettings?
    
    init(configDictionary: [String: Any]) throws {
        do {
            let jsonData = try JSONSerialization.data(withJSONObject: configDictionary, options: [])
            let configuration = try JSONDecoder().decode(DecoderSettings.self, from: jsonData)
            self.decodedSettings = configuration
        } catch SDKError.invalidFormatMessage(let invalidFormatMessage) {
            throw SDKError.invalidFormatMessage(invalidFormatMessage)
        } catch {
            throw error
        }
    }
    
    var getDocumentDetectorFlow: [DocumentDetectorStep]? {
        decodedSettings?.documentDetectorFlow
    }
    
    var getCafStage: DDCAFStage? {
        DDCAFStage(rawValue: (decodedSettings?.cafStage ?? .PROD).rawValue)
    }
    
    var getPersonId: String? {
        decodedSettings?.personId
    }
    
    var getAnalyticsSettings: Bool? {
        decodedSettings?.analyticsSettings
    }
    
    var getPopupSettings: Bool? {
        decodedSettings?.popupSettings
    }
    
    var getNetworkSettings: Double? {
        decodedSettings?.networkSettings
    }
    
    var getSensorSettings: SensorSettingsDeserializer.SensorSettingsStruct? {
        decodedSettings?.sensorSettings
    }
    
    var getProxySettings: DDProxySettings? {
        decodedSettings?.proxySettings
    }
    
    var getPreviewSettings: PreviewSettingsDeserializer.PreviewSettingsStruct? {
        decodedSettings?.previewSettings
    }
    
    var getCompressSettings: CGFloat? {
        decodedSettings?.compressSettings
    }
    
    var getManualCaptureSettings: ManualCaptureSettingsDeserializer.ManualCaptureSettingsStruct? {
        decodedSettings?.manualCaptureSettings
    }
    
    var getEnableMultiLanguage: Bool? {
        decodedSettings?.enableMultiLanguage
    }
    
    var getImageUrlExpireTime: String? {
        decodedSettings?.imageUrlExpireTime
    }
    
    var getCurrentStepDoneDelay: Double? {
        decodedSettings?.currentStepDoneDelay
    }
    
    var getResolutionSettings: CafResolution? {
        decodedSettings?.resolutionSettings
    }
    
    var getAllowedPassportList: [DDCountryCodes]? {
        decodedSettings?.allowedPassportList
    }
    
    var getUploadSettings: DDUploadSettings? {
        decodedSettings?.uploadSettings
    }
    
    var getMessageSettings: MessageSettingsDeserializer.MessageSettingsStruct? {
        decodedSettings?.messageSettings
    }
    
    var getStyle: DocumentDetectorLayout? {
        decodedSettings?.style
    }
    
    var getColorConfiguration: ColorConfiguration? {
        decodedSettings?.colorConfiguration
    }
}
