//
//  ListProductsCell.swift
//  NearbyStores
//
//  Created by Amine on 5/30/18.
//  Copyright © 2018 Amine. All rights reserved.
//


import UIKit
import GoogleMaps
import Cosmos
import RealmSwift
import MapKit
import SwiftEventBus


class GeoMapView: UIView, GMSMapViewDelegate, EmptyLayoutDelegate, ErrorLayoutDelegate, StoreLoaderDelegate, CLLocationManagerDelegate {
  
    
    func onReloadAction(action: EmptyLayout) {
        
    }
    
    func onReloadAction(action: ErrorLayout) {
        
    }
    
    func onSearch(search: String, radius: Int, args: [String : String]) {
        
    }
    
    
    var viewController: UIViewController? = nil
    //Cell ID for collection
    var cellId = "geostoreCellId"
    
    
    //instance for scrolling
    var isFetched = false
    
    
    
       let locationManager = CLLocationManager()
       var currentLocation: CLLocationCoordinate2D? = nil
       
      
       enum Request {
           static let nearby = 0
           static let saved = -1
       }
       
       //request
          var __req_category: Int = 0
          var __req_redius: Int = AppConfig.distanceMaxValue
          var __req_list: Int = Request.nearby
          var __req_search: String = ""
          var __req_page: Int = 1


          var __req_lat: Double?
          var __req_lng: Double?


    
    func setupViews() {
       
        
        //update location
                  self.locationManager.delegate = self
                  self.requestLocation()
                  
          
            self.setupGeoHeader()
            self.setupViewloader()
                  
               
                  
                  find_direction_icon.setIcon(icon: .googleMaterialDesign(.directions), textColor: Colors.primaryColor, backgroundColor: .clear, size: CGSize(width: 25,height: 25))
                  
                  self.find_direction_btn.initItalicFont()
                  self.find_direction_btn.setTitleColor(Colors.primaryColor, for: .normal)
                  
                  let tap = UITapGestureRecognizer(target: self, action: #selector(onTapStoreHeader))
                  self.storeContainer.addGestureRecognizer(tap)
                  
                  
                  if let guest = Guest.getInstance() {
                      
                      self.latitude = guest.lat
                      self.longitude = guest.lng
                      
                      let camera = GMSCameraPosition.camera(withLatitude: guest.lat, longitude: guest.lng, zoom: 6.0)
                      self.mapView = GMSMapView.map(withFrame: CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height), camera: camera)
                      
                      mapView?.delegate = self
                      
                      if let mapView = self.mapView  {
                          
                          mapView.animate(toZoom: 16)
                          viewContainer.addSubview(mapView)
                        
                        viewContainer.addConstraintsWithFormat(format: "H:|[v0]|", views: mapView)
                        viewContainer.addConstraintsWithFormat(format: "V:|[v0]|", views: mapView)

                          
                          // Creates a marker in the center of the map.
                          let marker = GMSMarker()
                          marker.position = CLLocationCoordinate2D(latitude:  guest.lat, longitude: guest.lng)
                          marker.map = mapView
                          
                          
                      }

                      
                      self.load()
                      
                  }else if let lat = self.latitude, let lng = self.longitude{
                      
                      let camera = GMSCameraPosition.camera(withLatitude: lat, longitude: lng, zoom: 6.0)
                      self.mapView = GMSMapView.map(withFrame: CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height), camera: camera)
                      
                      mapView?.delegate = self
                      
                      if let mapView = self.mapView  {
                          
                          mapView.animate(toZoom: 17)
                          viewContainer.addSubview(mapView)
                        
                        viewContainer.addConstraintsWithFormat(format: "H:|[v0]|", views: mapView)
                        viewContainer.addConstraintsWithFormat(format: "V:|[v0]|", views: mapView)

                        
                          // Creates a marker in the center of the map.
                          let marker = GMSMarker()
                          marker.position = CLLocationCoordinate2D(latitude:  lat, longitude: lng)
                          marker.map = mapView
                          
                      }
                      
                  }
                  
        
            //get params
             SwiftEventBus.onMainThread(self, name: "on_search_geo_stores") { result in

                 if let object = result?.object {

                     let array: [String: String] = object as! [String: String]

                     self.__req_lat = nil
                     self.__req_lng = nil
                     
                     self.__req_redius = Int(array["radius"]!)!
                     self.__req_search = array["search"]!
                     self.__req_page = 1

                     if let cat = array["category"] {
                         self.__req_category = Int(cat)!
                     }

                     if let lat = array["req_lat"] {
                         self.__req_lat = Double(lat)!
                     }

                     if let lng = array["req_lng"] {
                         self.__req_lng = Double(lng)!
                     }

                     self.viewManager.showAsLoading()
                     self.load()

                    
                    self.onSeachFeature = true

                 }

             }
    }
    
    
    
    @IBOutlet weak var viewContainer: UIView!
      
     
       //store geo map header
    @IBOutlet weak var storeContainer: UIView!
    @IBOutlet weak var storeClose: UIButton!
    @IBOutlet weak var storeRating: UIView!
    @IBOutlet weak var storeName: UILabel!
       
    @IBOutlet weak var find_direction_btn: UIButton!
    @IBOutlet weak var find_direction_icon: UIImageView!
     
    @objc func onTapStoreHeader()  {
         if let object = lastObject{
            
             //show detail of store
             let sb = UIStoryboard(name: "StoreDetail", bundle: nil)
             if sb.instantiateInitialViewController() != nil {
                 
                 let ms: StoreDetailViewController = sb.instantiateViewController(withIdentifier: "storedetailVC") as! StoreDetailViewController
                 ms.storeId = object.id
                 
                if let c = self.viewController{
                    c.present(ms, animated: true)
                }
                 
             }
         }
     }
     
       
    var mapView: GMSMapView? = nil
    
    var lastObject: Store? = nil
       
       @IBAction func find_direction_action(_ sender: Any) {
           
           if let object = lastObject{
              
               let latitude: CLLocationDegrees = object.latitude
               let longitude: CLLocationDegrees = object.longitude
                                                                
               let regionDistance:CLLocationDistance = object.distance
               let coordinates = CLLocationCoordinate2DMake(latitude, longitude)
                                                                
               let regionSpan = MKCoordinateRegion.init(center: coordinates, latitudinalMeters: regionDistance, longitudinalMeters: regionDistance)
               let options = [
                   MKLaunchOptionsMapCenterKey: NSValue(mkCoordinate: regionSpan.center),
                   MKLaunchOptionsMapSpanKey: NSValue(mkCoordinateSpan: regionSpan.span)
               ]
                                              
               let placemark = MKPlacemark(coordinate: coordinates, addressDictionary: nil)
               let mapItem = MKMapItem(placemark: placemark)
               mapItem.name = object.name
               mapItem.openInMaps(launchOptions: options)
              
           }
           
       }
       //end
       @IBAction func zoomPlus(_ sender: Any) {
           
           if let mapView = self.mapView  {
               
               mapView.animate(toZoom: mapView.camera.zoom+1)
               
           }
           
       }
       
       @IBAction func zoomLess(_ sender: Any) {
           
           if let mapView = self.mapView  {
               
               mapView.animate(toZoom: mapView.camera.zoom-1)
    
           }
       }
       
       @IBAction func onClose(_ sender: Any) {
          
        self.storeHeader(hidden: true)
           
           UIView.animate(withDuration: 0.2, delay: 1.0, options: .curveEaseOut, animations: {
                self.components_height_constraint.constant = CGFloat(0)
           }, completion: { finished in
                self.components_container.isHidden = true
            self.layoutIfNeeded()
           })
       }
    
    
    func storeHeader(hidden: Bool) {
        
        if hidden {
           
           // let animation = UIAnimation(view: self.storeContainer)
            //animation.zoomOut()
            
            self.storeContainer.isHidden = true
        }else{
            
          //  let animation = UIAnimation(view: self.storeContainer)
           // animation.zoomIn()
            
            self.storeContainer.isHidden = false
        }
       
    }
    
    
    
      let ratingView: CosmosView = {
          
          
          
          let cosmosView = CosmosView()
          
          cosmosView.rating = 0
          
          // Change the text
          cosmosView.text = " 0 (0)"
          cosmosView.settings.textColor = Colors.black
          cosmosView.settings.updateOnTouch = false
          
          if let font = UIFont(name: AppConfig.Design.Fonts.regular, size: 12) {
              cosmosView.settings.textFont = font
          }
          
          
          // Called when user finishes changing the rating by lifting the finger from the view.
          // This may be a good place to save the rating in the database or send to the server.
          cosmosView.didFinishTouchingCosmos = { rating in }
          
          // A closure that is called when user changes the rating by touching the view.
          // This can be used to update UI as the rating is being changed by moving a finger.
          cosmosView.didTouchCosmos = { rating in }
          
          
          return cosmosView
      }()
      
   
    func setupGeoHeader()  {
           
           
           self.storeContainer.isHidden = true
           self.storeRating.addSubview(ratingView)
           self.storeClose.setIcon(icon: .ionicons(.androidClose), iconSize: 24, color: Colors.gray, forState: .normal)
           self.storeName.initBolodFont()
       
       }
    
    var viewManager: LoaderViewManager =  LoaderViewManager()
      
    func setupViewloader()  {
           
           //setup view loader, Error, Empty layouts
           viewManager.setup(parent: viewContainer)
           viewManager.getEmptyLayout().delegate = self
           viewManager.getErrorLayout().delegate = self
           
           if Session.isLogged() ==  false {
               
               return
           }else{
               
           }
       }
    
    func fetch(request: String) {
        
        
        load()
        
    }
    
    
    
    
    
    
    
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
           
           guard let locValue: CLLocationCoordinate2D = manager.location?.coordinate else { return }
           
           self.currentLocation = locValue
           
           Utils.printDebug("\(locations)")
           self.current_lat = locValue.latitude
           self.current_lng = locValue.longitude
           
           if let guest = Guest.getInstance(), let cl = self.currentLocation {
               
               
               let realm = try! Realm()
               try! realm.write {
                   
                   guest.lat = cl.latitude
                   guest.lng = cl.longitude
                   realm.add(guest,update: .all)
                   
               }
               
               self.locationManager.stopUpdatingLocation()
               
           }
           
           DispatchQueue.main.asyncAfter(deadline: .now() + 15.0) {
               self.locationManager.startUpdatingLocation()
           }
           
       }
       
       
       func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
           
           
           if CLLocationManager.locationServicesEnabled() {
               switch CLLocationManager.authorizationStatus() {
               case .notDetermined, .restricted, .denied:
                   self.requestLocation()
               case .authorizedAlways, .authorizedWhenInUse:
                   self.requestLocation()
               }
           }
           
           
       }
       
       
       func requestLocation() {
           
           self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
           self.locationManager.requestWhenInUseAuthorization()
           self.locationManager.startUpdatingLocation()
           
       }
      
       var latitude: Double? = nil
       var longitude: Double? = nil
       var name: String? = nil
       
       var _req_limit = 30
   
    //API
    
    var storeLoader: StoreLoader = StoreLoader()
    var LIST: [Store] = [Store]()
    
    
    var current_lat = 0.0
    var current_lng = 0.0
    
    func mapView(_ mapView: GMSMapView, didChange position: GMSCameraPosition) {
        current_lat = position.target.latitude
        current_lng = position.target.longitude
    }
    
    
    
    func load () {
        
        MyProgress.show(parent: self)
        
        self.storeLoader.delegate = self
        
        //Get current Location
        
        var parameters = [
            "limit"          : "\(self._req_limit)"
        ]
        
        /*if let guest = Guest.getInstance() {
            
            if self.LIST.count>0{
                parameters["latitude"] = String(lat)
                parameters["longitude"] = String(lng)
                
            }else{
                parameters["latitude"] = String(guest.lat)
                parameters["longitude"] = String(guest.lng)
                
            }
            
            parameters["order_by"] = String(0)
            
            
        }*/
        
        
        if let lat = __req_lat, let lng = __req_lng {

            parameters["latitude"] = String(describing: lat)
            parameters["longitude"] = String(describing: lng)

        } else if let guest = Guest.getInstance() {

            parameters["latitude"] = String(guest.lat)
            parameters["longitude"] = String(guest.lng)

        }

        if __req_redius > 0 && __req_redius < 100 {
            parameters["radius"] = String((__req_redius * 1000)) //radius by merters
        }

        parameters["category_id"] = String(__req_category)
        parameters["order_by"] = String(0)
        
        Utils.printDebug("\(parameters)")
        
    
        self.storeLoader.load(url: Constances.Api.API_USER_GET_STORES,parameters: parameters)
        
        
    }
    
    
    func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
        
        
        if(marker.iconView != nil ){
            let view: CustomViewStoreMarker = marker.iconView as! CustomViewStoreMarker
            if let object = view.object {
                
                object.save()
                
                self.lastObject = object
                storeName.text = object.name
                
                
                let formatter = NumberFormatter()
                formatter.usesGroupingSeparator = true
                formatter.numberStyle = .decimal
                formatter.maximumFractionDigits = 1
                // localize to your grouping and decimal separator
                formatter.locale = Locale.current
                
                let number = NSNumber(value: object.votes)
             
                
                if let value = formatter.string(from: number){
                    self.ratingView.text = "\(value) (\(object.nbr_votes)) "
                }else{
                    self.ratingView.text = "\(object.votes) (\(object.nbr_votes)) "
                }
                
            
                self.ratingView.rating = object.votes
                
                self.storeHeader(hidden: false)
                
                if object.nbrProducts > 0{
                    self.load_component_recent_products(store: object)
                }
                
                let camera = GMSCameraPosition.camera(withLatitude: object.latitude, longitude: object.longitude, zoom: 16)
                // self.mapView?.camera = camera
                self.mapView?.animate(to: camera)
                
            }
        }
        
       
        return true
    }
    
    var onSeachFeature = false
       
    func success(parser: StoreParser,response: String) {
        
        
       MyProgress.dismiss()
      
        if parser.success == 1 {
            
            
            let stores = parser.parse()
            
          
            if stores.count > 0 {
                
                Utils.printDebug("We loaded \(stores.count)")
            
                 self.LIST = stores
                
                if stores.count > 0 {
                    mapView?.clear()
                    
                    if let guest = Guest.getInstance(), let mapView = self.mapView {
                        // Creates a marker in the center of the map.
                        let marker = GMSMarker()
                        marker.position = CLLocationCoordinate2D(latitude:  self.latitude!, longitude: self.longitude!)
                        marker.map = mapView
                        
                        var lt = 0.0
                        var lg = 0.0
                                             
                        lt = stores[0].latitude
                        lg = stores[0].longitude
                        
                       
                        let zoom_scale = getZoomScale(distance: Float(stores[0].distance))
                        
                        if onSeachFeature{
                            //move camera
                            let camera = GMSCameraPosition.camera(withLatitude: lt, longitude: lg, zoom: Float(zoom_scale))
                            self.mapView?.camera = camera
                            self.mapView?.animate(to: camera)
                                                    
                        }else{
                            //move camera
                            let camera = GMSCameraPosition.camera(withLatitude: guest.lat, longitude: guest.lng, zoom: Float(zoom_scale))
                            self.mapView?.camera = camera
                            self.mapView?.animate(to: camera)
                        }
                        
                    
                    }
                }
                
                if let mapView = self.mapView {
                
                    for store in self.LIST{
                        
                        let marker = GMSMarker()
                        marker.position = CLLocationCoordinate2D(latitude:  store.latitude, longitude: store.longitude)
                        marker.map = mapView
                        
                       
                        let icon = CustomViewStoreMarker()
                        icon.object = store
                        icon.setup(marker: marker)

                        marker.iconView = icon
                        
                    }
                    
                }
                
                
                
            }else{
                
                if self.LIST.count == 0 {
                    
                   // viewManager.showAsEmpty()
                    
                }
                
                
            }
            
        }else {
            
            if let errors = parser.errors {
                
                Utils.printDebug("===> Request Error with Messages! ListStores")
                Utils.printDebug("\(errors)")
                
                //viewManager.showAsError()
                
            }
            
        }
        
        
        onSeachFeature = false
                  
        
    }
    
    func error(error: Error?, response: String) {
        MyProgress.dismiss()
        //viewManager.showAsError()
    }
    
    
    @IBOutlet weak var components_container: UIView!
     @IBOutlet weak var components_height_constraint: NSLayoutConstraint!
     
    
      var mProducts_HCards_instance:Products_HCards?=nil
      
      func load_component_recent_products(store: Store)  {
          
          let style = CardHorizontalStyle(width: 280, height: 240, type: .Recent_Products,title: "recent_products")
          
          if let instance = mProducts_HCards_instance{
              
              instance.__req_store = store.id
              instance.load()
              
              UIView.animate(withDuration: 0.2, delay: 1.0, options: .curveEaseOut, animations: {
               
                self.components_height_constraint.constant = CGFloat(style.height!)
                self.components_container.isHidden = false
                
              }, completion: { finished in
                self.layoutIfNeeded()
              })
              
              return
          }
          
          
          mProducts_HCards_instance = (Products_HCards.newInstance(style: style) as! Products_HCards)
          mProducts_HCards_instance!.h_label.text = "recent_products".localized
          mProducts_HCards_instance!.viewController = self.viewController
          mProducts_HCards_instance!.__req_store = store.id
          mProducts_HCards_instance!.load()
                             
          if let title = style.Title{
              mProducts_HCards_instance!.h_label.text = title.localized
          }
          
          
        
        
        mProducts_HCards_instance!.viewController = self.viewController
      
          
          components_container.addSubview(mProducts_HCards_instance!)
          components_container.addConstraintsWithFormat(format: "H:|[v0]|", views: mProducts_HCards_instance!)
          components_container.addConstraintsWithFormat(format: "V:|[v0]|", views: mProducts_HCards_instance!)
                 
          
          UIView.animate(withDuration: 0.2, delay: 1.0, options: .curveEaseOut, animations: {
              self.components_height_constraint.constant = CGFloat(style.height!)
           }, completion: { finished in
           // self.layoutIfNeeded()
           })
                             
      }
}


func getZoomScale(distance: Float) -> Float {
    
    /*20 : 1128.497220
    19 : 2256.994440
    18 : 4513.988880
    17 : 9027.977761
    16 : 18055.955520
    15 : 36111.911040
    14 : 72223.822090
    13 : 144447.644200
    12 : 288895.288400
    11 : 577790.576700
    10 : 1155581.153000
    9  : 2311162.307000
    8  : 4622324.614000
    7  : 9244649.227000
    6  : 18489298.450000
    5  : 36978596.910000
    4  : 73957193.820000
    3  : 147914387.600000
    2  : 295828775.300000
    1  : 591657550.500000*/
    
 
    var zoom_scale = 1.0
    
    if(distance >= 1128 && distance < 2256){
        zoom_scale = 18.0
    }else if(distance >= 2256 && distance < 4513){
        zoom_scale = 17.0
    }else if(distance >= 4513 && distance < 9027){
        zoom_scale = 16.0
    }else if(distance >= 9027 && distance < 18055){
        zoom_scale = 15.0
    }else if(distance >= 18055 && distance < 72223){
        zoom_scale = 14.0
    }else if(distance >= 72223 && distance < 144447){
        zoom_scale = 13.0
    }else if(distance >= 144447 && distance < 288895){
        zoom_scale = 12.0
    }else if(distance >= 288895 && distance < 577790){
        zoom_scale = 11.0
    }else if(distance >=  577790 && distance < 1155581){
        zoom_scale = 10.0
    }else if(distance >=  1155581 && distance < 2311162){
        zoom_scale = 9.0
    }else if(distance >=  2311162 && distance < 4622324){
        zoom_scale = 8.0
    }else if(distance >=  4622324 && distance < 9244649){
        zoom_scale = 7.0
    }else if(distance >=  9244649 && distance < 18489298){
        zoom_scale = 6.0
    }else if(distance >=  18489298 && distance < 36978596){
        zoom_scale = 5.0
    }else if(distance >=  36978596 && distance < 73957193){
        zoom_scale = 4.0
    }else if(distance >=  73957193 && distance < 147914387){
        zoom_scale = 3.0
    }else if(distance >=  147914387 && distance < 295828775){
        zoom_scale = 2.0
    }else if(distance >=  295828775){
        zoom_scale = 1.0
    }
    
    return Float(zoom_scale)
    
}
