//
//  Copyright (c) 2017-2021 Slang Labs Private Limited. All rights reserved.
//  

import Foundation
import SlangFitnessAssistant
import SlangAssistant

var configOptions:Dictionary<String, Any>?

func getStringConfig(_ key:String) -> String {
    return configOptions?[key] as? String ?? ""
}

func getBooleanConfig(_ key:String, defaultValue: Bool = false) -> Bool  {
    return configOptions?[key] as? Bool ?? defaultValue
}

func getFloatConfig(_ key:String) -> Float  {
    return configOptions?[key] as? Float ?? 0.0
}

func getIntConfig(_ key:String) -> Int  {
    return configOptions?[key] as? Int ?? -1
}

func getAssistantDefaultSubdomainConfig(_ key:String) -> AssistantSubDomain  {
    guard let configOptions = configOptions else {
        return .food
    }
    
    if let value = configOptions[key] as? String, AssistantSubDomain(rawValue: value.lowercased()) != nil {
        return AssistantSubDomain(rawValue: value.lowercased())!
    }
    
    else {
        return .food
    }
}

func getAssistantDefaultUserJourneyConfig(_ key:String) -> AssistantUserJourney?  {
    guard let configOptions = configOptions else {
        return nil
    }
    
    if let value = configOptions[key] as? String {
        return getAssistantDefaultUserJourney(value)
    }
    
    else {
        return nil
    }
}

func getAssistantDefaultUserJourney(_ userJourneyString: String) -> AssistantUserJourney {
    if let userjourney
        = AssistantUserJourney(rawValue: userJourneyString) {
        return userjourney
    }
    
    else {
        return .foodLogging
    }
}

func getEnvironmentFromString(_ key:String) -> BaseConfiguration.Environment {
    guard let configOptions = configOptions else {
        return .production
    }
    
    if let value = configOptions[key] as? String {
        switch value {
        case "PRODUCTION" :
            return .production
        case "STAGING" :
            return .staging
        default:
            return .production
        }
    }
    
    return .production
}

func getStringListConfig(_ key:String) -> [String]? {
    return configOptions?[key] as? [String]
}

func getLocaleStringMapConfig(_ key:String) -> [Locale: String]? {
    var localeStringMap = [Locale: String]()
    
    guard let configOptions = configOptions else {
        return nil
    }
    
    if let valueMap = configOptions[key] as? [String: Any] {
        for (key,value) in valueMap {
            if let locale = getLocale(key) {
                if let localeValue = value as? String {
                    localeStringMap[locale] = localeValue
                }
            }
        }
    }
    else {
        return nil
    }
    
    return localeStringMap
}

func getAssistantUIConfig(_ key:String) -> BaseUIPosition {
    
    var uiPosition = AssistantUIPosition.AssistantUIPositionEnum.centerBottom
    
    var assistantUIPosition
    = AssistantUIPosition.Builder()
        .setBaseUIPosition(uiPosition)
        .setIsDraggable(false)
        .setIsForcedAtStartup(false)
        .build()
    
    guard let configOptions = configOptions else {
        return assistantUIPosition
    }
    
    guard let assistantUIMap = configOptions[key] as? [String: Any] else {
        return assistantUIPosition
    }
    
    
    let baseUIPosition = assistantUIMap["baseUIPosition"] as? String
    
    switch baseUIPosition {
    case "BOTTOM_LEFT" :
        uiPosition = AssistantUIPosition.AssistantUIPositionEnum.leftBottom
    case "CENTER_LEFT" :
        uiPosition = AssistantUIPosition.AssistantUIPositionEnum.leftCenter
    case "CENTER" :
        uiPosition = AssistantUIPosition.AssistantUIPositionEnum.center
        
    case "CENTER_RIGHT" :
        uiPosition = AssistantUIPosition.AssistantUIPositionEnum.rightCenter
    case "TOP_LEFT" :
        uiPosition = AssistantUIPosition.AssistantUIPositionEnum.leftTop
    case "TOP_CENTER" :
        uiPosition = AssistantUIPosition.AssistantUIPositionEnum.centerTop
        
    case "TOP_RIGHT" :
        uiPosition = AssistantUIPosition.AssistantUIPositionEnum.rightTop
    case "BOTTOM_RIGHT" :
        uiPosition = AssistantUIPosition.AssistantUIPositionEnum.rightBottom
    case "BOTTOM_CENTER" :
        uiPosition = AssistantUIPosition.AssistantUIPositionEnum.centerBottom
        
    default:
        uiPosition = AssistantUIPosition.AssistantUIPositionEnum.centerBottom
        
    }
    
    let offsetX = (assistantUIMap["offsetX"] as? Int) ?? 0
    let offsetY = (assistantUIMap["offsetY"] as? Int) ?? 0
    let draggable = (assistantUIMap["draggable"] as? Bool) ?? false
    let forcedAtStartup = (assistantUIMap["forcedAtStartup"] as? Bool) ?? false
    
    
    assistantUIPosition
    = AssistantUIPosition.Builder()
        .setBaseUIPosition(uiPosition)
        .setOffsetX(offsetX)
        .setOffsetY(offsetY)
        .setIsDraggable(draggable)
        .setIsForcedAtStartup(forcedAtStartup)
        .build()
    
    return assistantUIPosition
    
}

func convertToStringMap(_ map: Dictionary<String, Any>) -> [String: String] {
    var stringMap = [String: String]()
    for (key, value) in map {
        if let stringValue = value as? String {
            stringMap[key] = stringValue
        }
        else if let intValue = value as? Int {
            stringMap[key] = String(intValue)
        }
        else if let boolValue = value as? Bool {
            stringMap[key] = String(boolValue)
        }
    }
    
    return stringMap
}


func mapNavigationInfo(_ navigationInfo:NavigationInfo) -> [String:Any] {
    let navigationInfoMap = [String:Any]()
    return navigationInfoMap
}

func mapFoodInfo(_ foodInfo:FoodInfo) -> [String:Any] {
    var foodInfoMap = [String:Any]()
    
    if let logDate = foodInfo.logDate {
        foodInfoMap["logDate"] = logDate.timeIntervalSince1970
    }
    if let logTime = foodInfo.logTime {
        foodInfoMap["logTime"] = logTime.timeIntervalSince1970
    }
    if let mealType = foodInfo.mealType {
        foodInfoMap["mealType"] = mealType.rawValue
    }
    foodInfoMap["confirmationStatus"] = foodInfo.confirmationStatus.rawValue
    if let foods = foodInfo.foods {
        foodInfoMap["foods"] = mapFoods(foods)
    }
    
    return foodInfoMap
}

func mapSugarInfo(_ sugarInfo: SugarInfo) -> [String: Any] {
    var sugarInfoMap = [String:Any]()
    
    if let logDate = sugarInfo.logDate {
        sugarInfoMap["logDate"] = logDate.timeIntervalSince1970
    }
    if let logTime = sugarInfo.logTime {
        sugarInfoMap["logTime"] = logTime.timeIntervalSince1970
    }
    if let logPeriod = sugarInfo.logPeriod {
        sugarInfoMap["logPeriod"] = logPeriod.rawValue
    }
    if let sugarValue = sugarInfo.sugarValue {
        sugarInfoMap["sugarValue"] = sugarValue
    }
    sugarInfoMap["confirmationStatus"] = sugarInfo.confirmationStatus.rawValue
    
    return sugarInfoMap
}

func mapWeightInfo(_ weightInfo: WeightInfo) -> [String: Any] {
    var weightInfoMap = [String:Any]()
    
    if let logDate = weightInfo.logDate {
        weightInfoMap["logDate"] = logDate.timeIntervalSince1970
    }
    if let logTime = weightInfo.logTime {
        weightInfoMap["logTime"] = logTime.timeIntervalSince1970
    }
    if let weightValue = weightInfo.weightValue?.value {
        weightInfoMap["weightValue"] = weightValue
    }
    if let weightUnit = weightInfo.weightValue?.unit?.stringValue {
        weightInfoMap["weightUnit"] = weightUnit
    }
    weightInfoMap["confirmationStatus"] = weightInfo.confirmationStatus.rawValue
    
    return weightInfoMap
}

func mapFoodInfo(_ foodInfo:Dictionary<String, Any>) -> Food? {
    guard let name = foodInfo["name"] as? String else {
        return nil
    }
    var quantity = Quantity(1, unit: .number)
    if let quantityMap = foodInfo["quantity"] as? Dictionary<String, Any> {
        quantity = Quantity((quantityMap["amount"] as? NSNumber)?.floatValue, unit: .number)
    }
    return Food(name, quantity: quantity)
}


func mapFoods(_ foods:[Food]) -> [[String:Any]] {
    var foodsArray = [[String:Any]]()
    for food in foods {
        foodsArray.append(mapFood(food))
    }
    return foodsArray
}

func mapFood(_ food:Food) -> [String:Any] {
    var foodMap = [String:Any]()
    foodMap["foodName"] = food.foodName
    if let foodQuantity = food.quantity {
        foodMap["foodQuantity"] = mapFoodQuantity(foodQuantity)
    }
    
    //TODO : Fix once unrecognized flow is completed.
    foodMap["isRecognized"] = true
    return foodMap
}

func mapFoodQuantity(_ quantity:Quantity) -> [String:Any] {
    var quantityMap = [String:Any]()
    quantityMap["amount"] = quantity.amount
    quantityMap["unit"] = quantity.unit?.description
    return quantityMap
}

func convertHexToColor (hex: String) -> UIColor? {
    let red, green, blue, alpha: CGFloat
    
    if hex.hasPrefix("#") {
        let start = hex.index(hex.startIndex, offsetBy: 1)
        var hexColor = String(hex[start...])
        
        if hexColor.count == 6 {
            hexColor += "FF"
        }
        
        if hexColor.count == 8 {
            let scanner = Scanner(string: hexColor)
            var hexNumber: UInt64 = 0
            
            if scanner.scanHexInt64(&hexNumber) {
                red = CGFloat((hexNumber & 0xff000000) >> 24) / 255
                green = CGFloat((hexNumber & 0x00ff0000) >> 16) / 255
                blue = CGFloat((hexNumber & 0x0000ff00) >> 8) / 255
                alpha = CGFloat(hexNumber & 0x000000ff) / 255
                
                return UIColor(red: red, green: green, blue: blue, alpha: alpha)
            }
        }
    }
    
    return nil
}
