//
//  MapplsReactNativePlacePicker.swift
//  react-native-mappls-react-native-place-picker
//
//  Created by ceinfo on 27/01/21.
//

import Foundation
import MapplsUIWidgets
import MapplsMap

@objc(MapplsReactNativePlacePicker)
class MapplsReactNativePlacePicker: NSObject , MapplsAutocompleteViewControllerDelegate{
    func didAutocomplete(viewController: MapplsAutocompleteViewController, withPlace place: MapplsAtlasSuggestion, resultType type: MapplsAutosuggestResultType) {
        
        var result : [String: Any] = [:]
        result["eLocation"] = autosuggestResponse(response: place)
        result["isRequestForCurrentLocation"] = false
        //result["suggestedSearch"] = [:]
        
        var theJSONData: Data?
        do {
            theJSONData = try? JSONSerialization.data(withJSONObject: result, options: [])
        } catch(let jsonError) {
            print(jsonError.localizedDescription)
        }
        if let jsonData = theJSONData {
            let theJSONText = String(data: jsonData, encoding: .ascii)
            self.resolver!("\(theJSONText ?? "")")
        }
        UIApplication.shared.keyWindow?.rootViewController?.dismiss(animated: false, completion: nil)
    }
    
    func didAutocomplete(viewController: MapplsAutocompleteViewController, withFavouritePlace place: MapplsUIWidgetAutosuggestFavouritePlace) {
        
    }
    
    
    private func autosuggestResponse(response: MapplsAtlasSuggestion?) -> Any? {
        guard let response = response else {return nil}
        
        do {
            
            let encodedData = try JSONEncoder().encode(response)
//            let jsonString = String(data: encodedData,
//                                    encoding: .utf8);
            return try? JSONSerialization.jsonObject(with: encodedData);
        } catch {
            return nil
        }
    }
    
    private var  resolver: RCTPromiseResolveBlock?
    private var  rejecter: RCTPromiseRejectBlock?
    
    
    //required for exporting constants
    @objc
    static func requiresMainQueueSetup() -> Bool {
        return true
    }
    
    //exporting constants
    @objc func constantsToExport() -> NSObject {
        return [
            
            //PlaceOptions
            
            //Pods
            "POD_SUB_LOCALITY_KEY" : MapplsPodType.sublocality,
            "POD_LOCALITY_KEY": MapplsPodType.locality,
            "POD_CITY_KEY" : MapplsPodType.city,
            "POD_VILLAGE_KEY" : MapplsPodType.village,
            "POD_SUB_DISTRICT_KEY":MapplsPodType.subdistrict,
            "POD_DISTRICT_KEY": MapplsPodType.district,
            "POD_STATE_KEY" : MapplsPodType.state,
            "POD_SUB_SUB_LOCALITY_KEY": MapplsPodType.subSubLocality,
            
            //attributionHorizontalAlignment
            "GRAVITY_LEFT_KEY": MapplsHorizontalContentAlignment.left.rawValue,
            "GRAVITY_CENTER_KEY": MapplsHorizontalContentAlignment.center.rawValue,
            "GRAVITY_RIGHT_KEY": MapplsHorizontalContentAlignment.right.rawValue,
            
            //attributionVerticalAlignment
            "GRAVITY_TOP_KEY": MapplsVerticalPlacement.before.rawValue,
            "GRAVITY_BOTTOM_KEY":MapplsVerticalPlacement.after.rawValue,
            
            //logoSize
            "SIZE_SMALL_KEY": MapplsContentSize.small.rawValue,
            "SIZE_MEDIUM_KEY":MapplsContentSize.medium.rawValue,
            "SIZE_LARGE_KEY":MapplsContentSize.large.rawValue,
            
        ] as NSObject
    }
    
    //currently no use for us. Will be used with hyperlocal function
    func didAutocomplete(viewController: MapplsAutocompleteViewController, withSuggestion suggestion: MapplsSearchPrediction) {
        
        var data : [String: Any] = [:]
        
        if let keyword = suggestion.keyword { data["keyword"] = keyword }
        if let identifier = suggestion.identifier { data["identifier"] = identifier }
        if let location  = suggestion.location { data["location"] = location }
        if let hyperLink = suggestion.hyperLink { data["hyperLink"] = hyperLink }
        if let orderIndex = suggestion.orderIndex { data["orderIndex"] = orderIndex }
        
        
        var result : [String: Any] = [:]
        //result["eLocation"] =  [:]
        result["suggestedSearch"] = data
        result["isRequestForCurrentLocation"] = false

        var theJSONData: Data?
        do {
            theJSONData = try? JSONSerialization.data(withJSONObject: result, options: [])
        } catch(let jsonError) {
            print(jsonError.localizedDescription)
        }
        if let jsonData = theJSONData {
            let theJSONText = String(data: jsonData, encoding: .ascii)
            self.resolver!("\(theJSONText ?? "")")
        }
        UIApplication.shared.keyWindow?.rootViewController?.dismiss(animated: false, completion: nil)
    }
    
    func didFailAutocomplete(viewController: MapplsAutocompleteViewController, withError error: NSError) {
        // rejecter!("Fail AutoCompelte", "\(error.localizedDescription)", nil)
        
    }
    
    func didRequestForCurrentLocation() {
        var result : [String: Any] = [:]
        
        result["isRequestForCurrentLocation"] = true

        var theJSONData: Data?
        do {
            theJSONData = try? JSONSerialization.data(withJSONObject: result, options: [])
        } catch(let jsonError) {
            print(jsonError.localizedDescription)
        }
        if let jsonData = theJSONData {
            let theJSONText = String(data: jsonData, encoding: .ascii)
            self.resolver!("\(theJSONText ?? "")")
        }
        UIApplication.shared.keyWindow?.rootViewController?.dismiss(animated: false, completion: nil)
    }
    
    func wasCancelled(viewController: MapplsAutocompleteViewController) {
        rejecter!("Cancle", "Close", nil)
    }
    
    @objc func openPlaceWidget(_ params:NSDictionary,reslover resolve: @escaping RCTPromiseResolveBlock,rejecter reject: @escaping RCTPromiseRejectBlock ) -> Void  {
        
        DispatchQueue.main.async {
            self.resolver = resolve
            self.rejecter = reject
            var baseUrl: String? = nil;
            
            if let autoSuggestBaseUrl = params["autoSuggestBaseUrl"] as? String {
                 baseUrl = autoSuggestBaseUrl
            }
            let controller = MapplsAutocompleteViewController(baseURL: baseUrl)

            controller.delegate = self
            controller.autocompleteFilter = self.autoCompleteFilter(params: params)
            
            if params["historyCount"] != nil {
                let historyCount=params["historyCount"] as! Int
                MaxHistoryCountToSave = historyCount
            }
            
            if params["saveHistory"] != nil {
                let mSaveHistory=params["saveHistory"] as! Bool
                IsHistoryEnabled = mSaveHistory
            }
            if params["backgroundColor"] != nil {
                let mBackgroundColor = params["backgroundColor"] as! String
                controller.tableCellBackgroundColor = self.colorWithHexString(hexString: mBackgroundColor)
            }
            
            
            if params["toolbarTintColor"] != nil {
                let mToolbarTintColor = params["toolbarTintColor"] as! String
                UINavigationBar.appearance(whenContainedInInstancesOf: [MapplsAutocompleteViewController.self]).barTintColor=self.colorWithHexString(hexString: mToolbarTintColor)
            }
            
            if params["toolbarColor"] != nil {
                let mToolbarColor = params["toolbarColor"] as! String
                UINavigationBar.appearance(whenContainedInInstancesOf: [MapplsAutocompleteViewController.self]).backgroundColor=self.colorWithHexString(hexString: mToolbarColor)
            } else {
                UINavigationBar.appearance(whenContainedInInstancesOf: [MapplsAutocompleteViewController.self]).backgroundColor=self.colorWithHexString(hexString: "#FFFFFF")
            }
            
            if params["hint"] != nil {
                let mHint = params["hint"] as! String
                SearchBarPlaceHolderText = mHint
            }
            
            if params["attributionVerticalAlignment"] != nil {
                let attributionVerticalAlignment = params["attributionVerticalAlignment"] as! Int
                controller.attributionSettings.attributionVerticalPlacement = MapplsVerticalPlacement(rawValue: attributionVerticalAlignment)!
                
            }
            
            if params["attributionHorizontalAlignment"] != nil {
                let attributionHorizontalAlignment = params["attributionHorizontalAlignment"] as! Int
                controller.attributionSettings.attributionHorizontalContentAlignment = MapplsHorizontalContentAlignment(rawValue: attributionHorizontalAlignment)!
            }
            
            if params["logoSize"] != nil {
                let logoSize = params["logoSize"] as! Int
                controller.attributionSettings.attributionSize = MapplsContentSize(rawValue: logoSize)!
            }
            
            if params["enableTextSearch"] != nil {
                let enableTextSearch = params["enableTextSearch"] as! Bool
                IsTextSearchEnabledOnPressingEnterOrSearchKey = enableTextSearch
            }
            
            if params["showPoweredByText"] != nil {
                let showPoweredByText = params["showPoweredByText"] as! Bool
                
                if showPoweredByText {
                    controller.attributionSettings.attributionLength = .long
                }else{
                    controller.attributionSettings.attributionLength = .short
                }
            }
            
            if params["minCharactersForSearch"] != nil {
                let minCharactersForSearch = params["minCharactersForSearch"] as! Int
                MinimumNumberOfCharacterToStartSearch = minCharactersForSearch
            }
            
            if params["userAddedLocationEnable"] != nil {
                
            }
            
            if params["isShowCurrentLocation"] != nil {
                let isShowCurrentLocation = params["isShowCurrentLocation"] as! Bool
                IsShowCurrentLocationEnable = isShowCurrentLocation
            }
            
            if params["debounce"] != nil {
                let debounce = params["debounce"] as! Int
                controller.debounceInterval = debounce
            }
            
            if params["favoritePlaces"] != nil {
//                let favoritePlaces = params["favoritePlaces"] as! [String: Any]
//                MapplsUIWidgetAutosuggestFavouritePlace(placeName: favoritePlaces["placeName"] as! String, placeAdress: favoritePlaces["placeAddress"] as? String);
                
            }
            
//            if params["backgroundColor"] != nil {
//                let mBackgroundColor = params["backgroundColor"] as! String
//                controller.tableCellBackgroundColor = self.colorWithHexString(hexString: mBackgroundColor)
//            }
            controller.modalPresentationStyle = .fullScreen
            
            UIApplication.shared.keyWindow?.rootViewController?.present(controller, animated: false, completion: nil)
        }
    }
    
    func autoCompleteFilter(params : NSDictionary) -> MapplsAutocompleteFilter {
        let autocompleteFilter = MapplsAutocompleteFilter()
        if params["tokenizeAddress"] != nil {
            let mTokenizeAddress=params["tokenizeAddress"] as! Bool
            if mTokenizeAddress {
                autocompleteFilter.attributions = mTokenizeAddress
            }
        }
        
        if params["zoom"] != nil {
            let mZoom = params["zoom"] as! NSNumber
            autocompleteFilter.zoom = mZoom
        }
        
        if params["bridge"] != nil {
            let mBridge = params["bridge"] as! Bool
            autocompleteFilter.isBridgeEnabled = mBridge
        }
        if params["hyperLocal"] != nil {
            let mHyperLocal = params["hyperLocal"] as! Bool
                        autocompleteFilter.hyperLocal = mHyperLocal
        }
        
        if params["pod"] != nil {
            let pod = params["pod"] as! String
            autocompleteFilter.resultPlaceType = MapplsPodType(rawValue: pod)
        }
        
        if params["location"] != nil {
            let locationString = params["location"] as! NSArray
            if locationString.count==2 {
                let lat=(locationString[1] as! NSNumber).doubleValue
                let lng=(locationString[0] as! NSNumber).doubleValue
                autocompleteFilter.origin = CLLocation(latitude: lat, longitude:lng)
            }
        }
        
        if params["filter"] != nil {
            let mFilter = params["filter"] as! String
            
            if mFilter.contains("bounds") {
                let filterArray = (params["filter"] as! String).components(separatedBy: ":")
                let boundsArray = filterArray[1].components(separatedBy: ";")
                let firstBound = boundsArray[0].components(separatedBy: ",")
                let secondBound = boundsArray[1].components(separatedBy: ",")
                let firstLng=(firstBound[1] as NSString).doubleValue
                let firstLat=(firstBound[0] as NSString).doubleValue
                let secondLng=(secondBound[1] as NSString).doubleValue
                let secondLat=(secondBound[0] as NSString).doubleValue
                
                let southwest = CLLocationCoordinate2D(latitude: firstLat, longitude: firstLng)
                let northeast = CLLocationCoordinate2D(latitude: secondLat, longitude: secondLng)
                autocompleteFilter.searchAreaRestrictions = MapplsBoundsFilter(bounds: MapplsRectangularRegion(topLeft: northeast, bottomRight: southwest))
            }
            else if mFilter.contains("cop")  {
                let filterArray = (params["filter"] as! String).components(separatedBy: ":")
                
                autocompleteFilter.searchAreaRestrictions = MapplsMapplsPinFilter.init(mapplsPin: filterArray[1])
            }
            else if mFilter.contains("pin") {
                let filterArray = (params["filter"] as! String).components(separatedBy: ":")
                
                autocompleteFilter.searchAreaRestrictions = MapplsPinFilter.init(pincode: filterArray[1])
            }
            
        }
        
        
        return autocompleteFilter
    }
    
    func colorWithHexString(hexString: String, alpha:CGFloat = 1.0) -> UIColor {
        
        // Convert hex string to an integer
        let hexint = Int(self.intFromHexString(hexStr: hexString))
        let red = CGFloat((hexint & 0xff0000) >> 16) / 255.0
        let green = CGFloat((hexint & 0xff00) >> 8) / 255.0
        let blue = CGFloat((hexint & 0xff) >> 0) / 255.0
        
        // Create color object, specifying alpha as well
        let color = UIColor(red: red, green: green, blue: blue, alpha: alpha)
        return color
    }
    
    func intFromHexString(hexStr: String) -> UInt32 {
        var hexInt: UInt32 = 0
        // Create scanner
        let scanner: Scanner = Scanner(string: hexStr)
        // Tell scanner to skip the # character
        scanner.charactersToBeSkipped = CharacterSet(charactersIn: "#")
        // Scan hex value
        scanner.scanHexInt32(&hexInt)
        return hexInt
    }
}
