class Ruckus::SyncService < Ruckus::BaseApi
  def initialize ruckus_integration_type
    @ruckus_config = ruckus_integration_type
    @vendor_org_id = @ruckus_config.org_id
    @organisation = @ruckus_config.organisation
    # @api_key = @ruckus_config
    @api_version = @ruckus_config.details['api_version']
  end

  def get_zones_list domainid=nil
    zones = list_zones domainid
    return [] if zones.blank? || zones['list'].blank?
    return zones['list']
  end

  # apis for ruckus location networks(zones)
  def list_zones domainid=nil
    response = []
    params = {}
    params["domainId"] = domainid unless domainid.blank?
    
    begin
      response = RuckusApi.make_api_call @ruckus_config, "#{@api_version}/rkszones", 'GET', {}, params
    rescue Exception => e
      raise "[ERROR][RUCKUS][get_list_rkszones][params: #{params}] ERROR:: #{e}"
    end

    response
  end

  def zone_details(zone_id)
    begin
      response = RuckusApi.make_api_call @ruckus_config, "#{@api_version}/rkszones/#{zone_id}", 'GET', {}
    rescue Exception => e
      raise "[ERROR][RUCKUS][get_details_rkszones][ZONE ID: #{zone_id}] ERROR:: #{e}"
    end
  end

  def all_zone_details domainid=nil
    zones = get_zones_list domainid
    zones.each do |zone|
      zone_details zone['id']
    end
  end

  def sync_domains

  end

  def domain_name domainid
    domain_details = fetch_domain domainid
    return domain_details.blank? ? "" : domain_details["name"]
  end

  def fetch_domain domainid
    begin
      response = RuckusApi.make_api_call @ruckus_config, "#{@api_version}/domains/#{domainid}", 'GET', {}
    rescue Exception => e
      raise "[ERROR][RUCKUS][fetch_domain][#{domainid}] ERROR:: #{e}"
    end
  end

  def fetch_all_domain
    begin
      response = RuckusApi.make_api_call @ruckus_config, "#{@api_version}/domains", 'GET', {}
    rescue Exception => e
      raise "[ERROR][RUCKUS][fetch_all_domain] ERROR:: #{e}"
    end    
  end

  def sync_all_zones domainid=nil
    domainid = @ruckus_config.details['domainid'] if domainid.blank?
    zones = get_zones_list domainid
    zones.each do|zone|
      z_details = zone_details(zone['id'])
      create_zone_in_pcc(z_details)
    end
  end

  def create_zone_in_pcc(zone)
    network = @organisation.location_networks.where(:vendor_network_id => zone["id"]).first
    hsh = {
      :network_name=> zone["name"], 
      :vendor_network_id=>zone["id"], 
      :timezone=>zone["timezone"].blank? ? nil : zone["timezone"]["systemTimezone"],
      :vendor_type=>"5",
      :network_configuration=>"ruckus",
      :vendor_details=>{:domainid=>zone["domainId"],:countryCode=>zone["countryCode"]}, #TODO: Add firmware version
      :skip_sync => true,
      :integration_type_id => @ruckus_config.id
    }
    p hsh
    if network.present?
      network.update_attributes(hsh)
      Rails.logger.info ":::::::::::::::::::::::::::::::::::::_________ locationNetwork updated #{hsh}"
    else
      network = @organisation.location_networks.create(hsh)
      Rails.logger.info "**************************************locationNetwwork created #{hsh}"
    end
    sync_radio_config(zone, network)
    sync_wlan_group(network)
    sync_ap_group(network)
    # add_zone_to_network_tag(zone,org,network) if zone["domainId"].present?
  end

  def sync_radio_config zone, network
    radio24g = zone['radioConfig']['radio24g'] 
    radio5g = zone['radioConfig']['radio5g'] 
    radio6g = zone['radioConfig']['radio6g'] 
    radio_obj = network.associated_radio_profile
    radio_obj = network.radio_profiles.new name: "#{network.network_name} Radio" unless radio_obj.present?
    radio_obj.vendor_network_id = zone['id']
    radio_obj.organisation_id = network.organisation_id
    radio_obj.associated_resources = ["network:#{network.id}"]
    radio_obj.skip_sync = true
    radio_obj.save
    zone['radioConfig'].each do |k,radio_config|
      next if !['radio24g', 'radio5g', 'radio6g'].include?(k)
      if k == 'radio24g'
        band = '2.4'
      elsif k == 'radio5g'
        band = '5'
      elsif k == 'radio6g'
        band = '6'
      end
      radio_setting = radio_obj.radio_settings.where(band: band).last
      radio_setting = radio_obj.radio_settings.new(band: band) unless radio_setting.present?
      next if radio_config.blank?
      radio_setting.channel_utlilization = radio_config['autoCellSizing'] ? 'true' : 'false'
      radio_setting.power = Ruckus::ObjectMapper::POWERTX.key(radio_config['txPower'])
      radio_setting.bandwidth = radio_config['channelWidth'].to_s
      radio_setting.channel = radio_config['channel']
      radio_setting.valid_auto_channel = radio_config['channelRange'].map(&:to_s)
      radio_setting.is_disable = !radio_config['wlanServiceEnabled']
      radio_setting.save
    end
  end

  def sync_ap_group network
    ap_groups = Ruckus::ConfigurationService.new(network).list_ap_group

    ap_groups.each do |ap_group|
      ap_g = network.ap_groups.where(vendor_id: ap_group['id']).last
      ap_g = network.ap_groups.new unless ap_g.present?
      
      ap_group_detail = Ruckus::ConfigurationService.new(network).get_ap_group_details ap_group['id']
      ap_g.vendor_id = ap_group['id']
      ap_g.name = ap_group['name']
      ap_g.wlan_group_id = network.get_default_wlan_group
      ap_g.skip_sync = true
      # TODO: Associate ap group to respective WLAN groups
      # - Provision AP to our inventory
      ap_g.save
      ap_group_detail['members'].each do |device|
        ri = network.router_inventories.where(mac_id: device['apMac'].upcase).last
        ri = network.router_inventories.new(mac_id: device['apMac'].upcase, vendor_type: "5", organisation_id: network.organisation_id) unless ri.present?
        ap_detail = Ruckus::ConfigurationService.new(network).get_devices_details device['apMac']
        ri.serial = ap_detail["serial"]
        ri.model = ap_detail["model"]
        ri.name = ap_detail["name"]
        ri.longitude = ap_detail['longitude'].to_s
        ri.latitude = ap_detail['latitude'].to_s
        ri.ap_group_id = ap_g.id
        ri.save
        # TODO: Extract Radio Config from AP

      end  
    end
  end

  def sync_wlan_group network
    wlan_groups = Ruckus::ConfigurationService.new(network).get_all_wlan_groups 
    wlan_groups.each do |wlan_group|
      p "WLG :: #{wlan_group}"
      wl_g = network.wlan_groups.where(vendor_id: wlan_group['id']).last
      unless wl_g.present?
        wl_g = network.wlan_groups.create name: wlan_group['name'], vendor_id: wlan_group['id'], skip_sync: true
      else
        wl_g.name = wlan_group['name']
        wl_g.skip_sync = true
        wl_g.save
      end
      sync_wlans(wlan_group['members'], wl_g, network)
    end
  end

  def sync_wlans(wlans, wl_g, network)
    wlans.each do |wlan_detail|
      wlan = Ruckus::ConfigurationService.new(network).wlan_details wlan_detail['id']
      encryption = wlan['encryption'] || {}
      ssid = network.network_ssids.select {|d| (d.vendor_details || {})["id"] == wlan['id'] }.last
      ssid = network.network_ssids.new unless ssid.present?
      ssid.skip_sync = true
      ssid.ssid_name = wlan['ssid']
      ssid.security_mode = Ruckus::ObjectMapper::MSECURITY.key(encryption['method'])
      ssid.vendor_details = {'id' => wlan['id']}

      if ssid.security_mode == 'psk2'
        ssid.wpa_key = encryption['passphrase'] 
        ssid.ssid_802_11_w = Ruckus::ObjectMapper::W80211.key(encryption['mfp'])
      end

      if wlan['externalDpsk'].present? && wlan['externalDpsk']['enabled']
        auth_radius_id = (wlan['externalDpsk']['authService'] || {})['id']
        if auth_radius_id.present?
          radius_auth_details = Ruckus::ConfigurationService.new(network).radius_details 'auth', auth_radius_id
          if radius_auth_details.present?
            radius = network.organisation.radiuses.select {|r| (r.vendor_details||{})['id'] == auth_radius_id}.last
            radius = network.organisation.radiuses.new unless radius.present?
          
            radius.radius_name = radius_auth_details['name']
            radius.radius_ip = (radius_auth_details['primary'] || {})['ip']
            radius.radius_port = (radius_auth_details['primary'] || {})['port']
            radius.radius_secret = (radius_auth_details['primary'] || {})['sharedSecret']
            radius.vendor_details = {'id' => auth_radius_id}

            radius.save

            ssid.auth_radius_id = radius.id
            ssid.multi_psk = "radius"
          end
        end
      end

      if wlan['vlan'].present? && wlan['vlan']['accessVlan'].present?
        ssid.ssid_mode = '0'
        if ssid.v_lan.present?
          ssid.v_lan.update_attributes(:v_lan_id => wlan['vlan']['accessVlan']) if ssid.v_lan.v_lan_id != wlan['vlan']['accessVlan']
        else
          ssid.v_lan_attributes = {:v_lan_id => wlan['vlan']['accessVlan']}
        end
      end

      ssid.is_isolate = wlan['advancedOptions']['clientIsolationEnabled']
      ssid.is_hidden = wlan['advancedOptions']['hideSsidEnabled']
      ssid.band_steering = Ruckus::ObjectMapper::BANDBALANCING.key(wlan['advancedOptions']['bandBalancing'])
      ssid.ssid_802_11_k = wlan['advancedOptions']['support80211kEnabled']
      ssid.wlan_groups << wl_g unless ssid.wlan_groups.include?(wl_g)
      ssid.associated_aps_and_tags = ["network:#{network.id}"] if wl_g.name == 'default'
      ssid.captive_portal = "0" #NOTE: overwrite this setting when we implement the captive portal.
      ssid.enable_ssid_qos = false
      ssid.is_enabled = true
      ssid.acl_mac = "0"
      ssid.save

      #############################
      # TODO: CP for SSID
      # { "authServiceOrProfile" => {"id" => auth_radius.vendor_details["id"],"name" => auth_radius.radius_name,"throughController"=>true},"accountingServiceOrProfile" => {"id" => acct_radius.vendor_details["id"],"name" => acct_radius.radius_name,"interimUpdateMin"=>ssid.default_interim_time.to_i/60, "throughController"=>true,"accountingDelayEnabled"=>false}, "portalServiceProfile"=>{"id"=>portalservice},"radiusOptions"=>{"nasIdType"=>"AP_MAC","nasIpType"=>"control","singleSessionIdAcctEnabled"=>true} }


      # if ssid.captive_portal.to_i != 0
      #   cpservice = self.get_cp_services(ssid, ln)
      #   Rails.logger.info "------------------ IN CP -------------- #{cpservice}"
      #   ssid_map = ssid_map.merge(cpservice) unless cpservice.blank?
      #   wlanendpoint = "wlans/wispr" unless cpservice.blank?
      #   Rails.logger.info "------------------ IN CP -------------- #{ssid_map}"
      # end
    end
  end

  def sync_all_devices org
    list_devices = get_devices
    list_devices.each do|device|
      device_details = get_devices_details(device)
      create_device_for_zone_pcc(device_details, org)
      add_zone_to_network_tag() if domainid_available?
    end
  end

  def sync_zone_devices network
    zone_devices = Ruckus::ConfigurationService.new(network).get_zone_devices network.vendor_network_id
    wlan_group_map = {}
    zone_devices.each do |device|
      #Create RouterInventory

      wlan_group_map[device]
    end
  end

  def create_device_for_zone_pcc(device_details)
    dev_mac = device_details["mac"].upcase
    loc_nw = LocationNetwork.where(:vendor_network_id => device_details["zoneId"],organisation_id: org.id).first
    if loc_nw.present?  
      devices = RouterInventory.where(:mac_id=>dev_mac).last
      if devices.blank?
        Rails.logger.info "New :: Device(#{dev_mac}) Added with Network(#{loc_nw.network_name}) "
        macc, status = RouterInventory.ruckus_routers_activation([dev_mac, loc_nw.id,org.id], devices)
      else
        Rails.logger.info "Already Exisit:: Device(#{dev_mac}) Added with Network(#{devices.location_network_id}) "
      end
    #else
     # router = [dev_mac, nil, org.id]
      #Rails.logger.info "New :: Device(#{dev_mac}) Added without Network "
      #macc, status = RouterInventory.meraki_routers_activation(router, dev)
    end
  end  
end


#RADIUS AUTH

# {
#   "id": "82109ce0-64e6-11e4-8916-0026b9f85aaf",
#   "mvnoId": "839f87c6-d116-497e-afce-aa8157abd30c",
#   "domainId": "userDomainId",
#   "protocol": "RADIUS",
#   "name": "rapheal-auth-x3",
#   "friendlyName": "rapheal-auth-x",
#   "description": "authentication service created by rapheal via public API",
#   "mappings": [
#     {
#       "id": "73587760-6589-11e4-800c-0026b9f85aaf",
#       "groupAttr": "abc",
#       "userRole": {
#         "id": "a4c288b0-63cf-11e4-a18a-080027b147d4",
#         "name": "identity user role name",
#         "userTrafficProfile": {
#           "id": "9474cc20-63cf-11e4-a18a-080027b147d4",
#           "name": "rapheal-usertraffic-profile"
#         }
#       }
#     },
#     {
#       "id": "735e6ad0-6589-11e4-800c-0026b9f85aaf",
#       "groupAttr": "*",
#       "userRole": {
#         "id": "9ac45fd6-a87b-4eef-87d7-b759fed376c5",
#         "name": "identity user role name",
#         "userTrafficProfile": {
#           "id": "03ec5340-60a4-11e4-87fc-080027b147d4",
#           "name": "System Default"
#         }
#       }
#     }
#   ],
#   "primary": {
#     "ip": "1.1.1.155",
#     "port": 1812,
#     "sharedSecret": "abc"
#   },
#   "secondary": {
#     "ip": "2.2.2.231",
#     "port": 1812,
#     "sharedSecret": "abc"
#   },
#   "standbyPrimary": {
#     "ip": "3.3.3.3",
#     "port": 1812,
#     "sharedSecret": "abc"
#   },
#   "healthCheckPolicy": {
#     "responseWindow": 20,
#     "reviveInterval": 120,
#     "zombiePeriod": 40
#   },
#   "rateLimiting": {
#     "maxOutstandingRequestsPerServer": 0,
#     "threshold": 0,
#     "sanityTimer": 10
#   },
#   "standbyServerEnabled": true
# }