# == Schema Information
#
# Table name: router_inventories
#
#  id                   :integer          not null, primary key
#  mac_id               :string(255)
#  router_serial_number :string(255)
#  location_network_id  :integer
#  user_id              :integer
#  created_at           :datetime
#  updated_at           :datetime
#  name                 :string(255)
#  notes                :text
#  address              :text
#  gre                  :string(255)
#  dhcp_relay           :string(255)
#  ip_type              :string(255)
#  ip                   :string(255)
#  subnet_mask          :string(255)
#  gateway              :string(255)
#  primary_dns          :string(255)
#  secondary_dns        :string(255)
#  channel              :string(255)
#  enable_gre_on_lan    :string(255)
#  enable_dhcp_on_lan   :string(255)
#  snmp_config_id       :integer
#  power                :string(255)
#  dhcp_start_range     :string(255)
#  dhcp_end_range       :string(255)
#  organisation_id      :integer
#  city                 :string(255)
#  country              :string(255)
#  zipcode              :string(255)
#  latitude             :string(255)
#  longitude            :string(255)
#  region_name          :string(255)
#  presence             :boolean          default(FALSE)
#  wl_association       :string(255)
#  wl_wpa_key           :string(255)
#  wl_band              :string(255)
#  wl_ssid_name         :string(255)
#  wds_enabled          :boolean          default(FALSE)
#  uplink_type          :string(255)      default("1")
#  wl_ssid_uniqe_id     :integer
#  hardware_part_id     :integer
#  state                :string(255)
#  address2             :string(255)
#  mo_service           :string(255)
#  mo_apn               :string(255)
#  mo_device            :string(255)
#  mo_username          :string(255)
#  mo_password          :string(255)
#  loc_mac_id           :string(255)
#  enable_lb            :boolean          default(FALSE)
#

class RouterInventory < ActiveRecord::Base
  resourcify
  include RedisWrapper
  extend RedisWrapper
  include PublicActivity::Model

  tracked owner: ->(controller, model) { controller && controller.tracked_current_user },params:
  { :attributes => proc {|controller, model_instance| {"#{model_instance.hardware_part.try(:hardware_category).try(:name)}(#{model_instance.mac_id})" => model_instance.changes}}},organisation_id: ->(controller, model) { (controller && controller.tracked_current_user) ? controller.tracked_current_user.organisation_id : model.organisation_id},:location_network_id => proc {|controller, model_instance| model_instance.location_network_id}

  tracked assumed_by: proc {|controller, model| controller.user_assumed_by if controller}
  MAC_ID_REGEX = /^([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2})$/
  UPLINK_TYPE = {"1" => "Wired", "2" => "Wireless(Bridge)", "3" => "Wireless(Router)", "4" => "Mobile Broadband"}
  MACID_RANGE_ALLOWED = APPLICATION['defaults']['macid_allowed_range']
  EXTRA_FIELDS = ["uplink_name","name","address", "notes", "latitude", "longitude", "city", "country", "state", "address2","tag_list" ,"updated_at"]
  VENDOR_TYPE = {'1' => 'PIAP', '2' => 'Aruba', '3' => 'Meraki', '4' => 'OpenWifi (TIP)', '5' => 'Ruckus', '6' => 'PIAP-Switch'}
  VENDOR_TYPE_1 = {'1' => 'PIAP', '2' => 'Aruba', '3' => 'Meraki', '6' => 'PIAP-Switch'}
  # VENDOR_TYPE = {'1' => 'PIAP','2' => 'Aruba', '3' => 'Meraki','4'=>'Fortinet','5'=>'Cradlepoint'}
  #belongs_to :user
  belongs_to :location_network
  belongs_to :organisation
  belongs_to :hardware_part
  belongs_to :ap_group
  has_one :snmp_config
  has_one :sqm
  has_many :upgrades, :dependent => :destroy
  has_one :sim_management, :dependent => :destroy
  has_one :purchase_order, :dependent => :destroy
  has_many :uplinks, :dependent => :destroy
  has_one :pending_upgrade, -> { where status: nil }, class_name: "Upgrade"
  has_one :waiting_upgrade, -> { where status: "waiting for response" }, class_name: "Upgrade"

  has_and_belongs_to_many :commands

  has_many :acl_inventories, :dependent => :destroy
  has_many :acl_groups, -> { uniq }, :through => :acl_inventories

  has_many :pf_inventories, :dependent => :destroy
  has_many :portforwarding_groups, -> { uniq }, :through => :pf_inventories

  has_many :config_mappings, as: :resourceable, :dependent => :destroy
  has_one :wired_config, as: :resourceable, :class_name => 'ConfigMapping'
  has_one :radio_profile, as: :resourceable, :class_name => 'ConfigMapping'
  has_one :switch_configuration, as: :resourceable, :class_name => 'ConfigMapping'
  has_many :associated_network_ssids, through: :config_mappings, source: :configurable, source_type: "NetworkSsid"
  has_many :associated_air_quality_configs, through: :config_mappings, source: :configurable, source_type: "AirQualityConfig"
  has_one :associated_radio_profile, through: :radio_profile, source: :configurable, source_type: "RadioProfile"
  has_one :associated_wired_config, through: :wired_config, source: :configurable, source_type: "WiredConfig"
  has_many :associated_portforwarding_groups, through: :config_mappings, source: :configurable, source_type: "PortforwardingGroup"
  has_many :associated_acl_groups, through: :config_mappings, source: :configurable, source_type: "AclGroup"
  has_many :associated_static_routes, through: :config_mappings, source: :configurable, source_type: "StaticRoute"
  has_many :associated_snmp_configurations, through: :config_mappings, source: :configurable, source_type: "SnmpConfig"
  has_many :associated_sqms, through: :config_mappings, source: :configurable, source_type: "Sqm"
  has_many :associated_loggings, through: :config_mappings, source: :configurable, source_type: "Logging"
  has_many :associated_tags, through: :config_mappings ,source: :configurable, source_type: "AssociatedTag"
  has_many :associated_firewall_configs, through: :config_mappings ,source: :configurable, source_type: "FirewallConfig"
  has_many :associated_vpn_configs, through: :config_mappings ,source: :configurable, source_type: "VpnConfig"
  has_one :associated_switch_configuration, ->(router_inventory_id) { where(:hardware_part_id => RouterInventory.where(id: router_inventory_id).first.try(:hardware_part_id)) }, through: :switch_configuration ,source: :configurable, source_type: "SwitchConfiguration"
  has_many :ap_metadatas, :dependent => :destroy
  has_many :medias, :through => :ap_metadatas, :dependent => :destroy
  accepts_nested_attributes_for :uplinks, allow_destroy: true
  acts_as_taggable
  #validate :uplink_primary
  
  serialize :vendor_details, Hash

  scope :switches, ->(hw_part_ids=nil) { where(hardware_part_id: (hw_part_ids || HardwarePart.switch_hardware_parts.pluck(:id) )) }

  after_destroy do |ri|
    redis_del "#{ri.mac_id}"
    redis_del "AP:#{ri.mac_id}"
    begin
      Notification.where(:ap_mac_id.in => [ri.mac_id]).destroy_all
    rescue
    end    
  end

  after_create do |ri|
    $redis.del "NP:AP:#{ri.mac_id}"
  end

  def json_build
    if self.hardware_part.present?
      hardware_part_name = self.hardware_part.name
      device_type = self.hardware_part.hardware_category.blank? ? "access_point" : self.hardware_part.hardware_category.name
    end
    last_hb_data = $redis.hgetall "AP:#{self.mac_id}" || {}
    #{id: self.id, mac_id: self.mac_id, location_network_id: self.location_network_id, organisation_name: organisation.organisation_name, name: self.name, notes: self.notes, address: self.address, gre: self.gre, dhcp_relay: self.dhcp_relay, ip_type: self.ip_type, ip: self.ip, subnet_mask: self.subnet_mask, gateway: self.gateway, primary_dns: self.primary_dns, secondary_dns: self.secondary_dns, channel: self.channel, enable_gre_on_lan: self.enable_gre_on_lan, enable_dhcp_on_lan: self.enable_dhcp_on_lan, snmp_config_id: self.snmp_config_id, power: self.power, dhcp_start_range: self.dhcp_start_range, dhcp_end_range: self.dhcp_end_range, city: self.city, country: self.country, zipcode: self.zipcode, latitude: self.latitude, longitude: self.longitude, region_name: self.region_name, device_model: hardware_part_name, state: self.state, address2: self.address2, enable_lb: self.enable_lb, sim_iccid: self.sim_iccid, sim_imei: self.sim_imei, kernal_version: self.kernal_version, enable_pci: self.enable_pci}
    ri = {id: self.id, mac_id: self.mac_id, serial: self.router_serial_number, location_network_id: self.location_network_id, location_network_name: last_hb_data['Network'], organisation_name: self.organisation.try(:organisation_name), name: self.name, notes: self.notes, address: self.address, gre: self.gre, dhcp_relay: self.dhcp_relay, enable_gre_on_lan: self.enable_gre_on_lan, enable_dhcp_on_lan: self.enable_dhcp_on_lan, device_model: hardware_part_name, device_type: device_type, firmware_version: last_hb_data['version'], city: self.city, country: self.country, zipcode: self.zipcode, latitude: self.latitude, longitude: self.longitude, state: self.state, address2: self.address2, enable_lb: self.enable_lb, enable_pci: self.enable_pci, uplinks: self.get_uplinks, public_ip: last_hb_data['pub_ip'], last_seen_time: (last_hb_data["last_hb"].blank? ? nil : last_hb_data["last_hb"].to_i), device_status: (self.is_up? ? "UP" : "DOWN"), tag_list: self.tag_list}
    ri[:switch_configuration] = self.get_associated_switch_configuration.try(:json_build) if self.switch?
    ri
  end

  def get_uplinks
    uplinks = self.uplinks.map do |u|
      uplink = {id: u.id, uplink_name: u.uplink_name, uplink_type: u.uplink_type, is_primary: u.is_primary}
      if u.uplink_type == "4" && u.last_mobile_status.present?
        mb_uplink = Hash[u.last_mobile_status.try(:split,'|').map {|x| return if x.blank?; [x.split(":")[0].strip, x.split(":")[1].strip]}]
        mob_hsh = {imei: mb_uplink["IMEI"], imsi: mb_uplink["IMSI"], iccid: mb_uplink["ICCID"]} if mb_uplink.present?
        uplink.merge!(mob_hsh)
      else
        uplink
      end
    end
    uplinks
  end

  def uplink_primary
    ups = uplinks.pluck(:is_primary)
    ups.delete(false)
    errors.add('Oops!',"There cannot be two primary uplinks ") if ups.count > 1
  end

  def name_with_mac_id
    return "#{name} (#{mac_id.last(8)})" if name.present?
    "#{mac_id}"
  end

  def self.router_provision(router,network,current_user)
    result = self.validate_router(router,current_user.organisation)
    return unless result[0]
    network.router_inventories.build({mac_id: router,organisation_id: current_user.organisation_id})
    network.save!
  end

  def self.auto_provisioning_ap(router, network, current_user)
    if network.try(:id).blank? && router.location_network_id.present?
      loc_network = LocationNetwork.find(router.location_network_id)
      new_network_name = set_network_name(loc_network.network_name,current_user)
      cloned_loc_network = LocationNetwork.new(network_name: new_network_name,network_configuration: "clone",cloned_network_id: loc_network.id,timezone: loc_network.timezone,organisation_id: current_user.organisation_id,model_current_user: current_user)
      cloned_loc_network.save
      router.location_network_id = cloned_loc_network.try(:id)
    else
      router.location_network_id = network.try(:id)
    end
    router.organisation_id = current_user.organisation_id
    router.is_auto_provisioned = false
    router.save
  end 

  def self.set_network_name(new_network_name,current_user)
    network = current_user.organisation.location_networks.where(network_name: new_network_name).first
    if network.present?
      i = 1
      while true
        new_network_name = network.network_name + "_#{i}"
        i += 1
        if !current_user.organisation.location_networks.where(network_name: new_network_name).first.present?
          new_network_name = new_network_name
          break
        end
      end
    end
    new_network_name
  end

  def self.router_activation(router,current_user,is_auto_provisioned)
    result = self.validate_router(router[0],current_user.organisation)
    return router[0], false if result[0].blank?
    network = router[1].present? ? current_user.organisation.location_networks.find_by(:network_name => router[1]) : nil
    if router[1].present? && network.blank? && current_user.role.name != 'network_admin'
      network = current_user.organisation.location_networks.create({:network_name=>router[1], :network_configuration => "default", model_current_user: current_user})
      #current_user.unities.create(:location_network_id => network.id, :role_id => Role.find_by_name('admin').id, :permission => "full")
    end
    if current_user.role.name != 'network_admin'
      if result[0].try(:mac_id).present?
        auto_provisioning_ap(result[0],network,current_user)
      else
        self.create({mac_id: router[0].strip, location_network_id: network.try(:id), organisation_id: current_user.organisation_id,is_auto_provisioned: is_auto_provisioned, vendor_type: router[2], hardware_part_id: router[3]})
      end
      return router[0], true
    elsif current_user.networks_with_full_access.where(network_name: router[1]).first.present?
      if result[0].try(:mac_id).present?
        auto_provisioning_ap(result[0],network,current_user)
      else
        self.create({mac_id: router[0].strip, location_network_id: network.try(:id), organisation_id: current_user.organisation_id,is_auto_provisioned: is_auto_provisioned, vendor_type: router[2], hardware_part_id: router[3]})
      end
      return router[0], true
    else
      return router[0], false
    end

  end

  def network_device_count(network, device_type)
    ap_invs = network.router_inventories.where("name LIKE ?", "%#{device_type}%")
    ap_count = []
    if ap_invs.present?
      ap_invs.each do |ap|
        ap_count << ap.name.split("_").last.to_i
      end
    else
      ap_count << 0
    end
    ap_count
  end

  def nomenclature_naming(hardware_category = nil, network)
    case hardware_category   
    when HardwareCategory::ACCESS_POINT
      "AP_#{self.network_device_count(network, "AP").max+1}"   
    when HardwareCategory::SWITCH
      "SWITCH_#{self.network_device_count(network, "SWITCH").max+1}"   
    when HardwareCategory::ROUTER
      "ROUTER_#{self.network_device_count(network, "ROUTER").max+1}"   
    end   
  end

  def device_nomenclature(org_stng)
    network = self.location_network
    return unless (hardware_category = self.hardware_part.try(:hardware_category).try(:name)).present?
    org_stng["nomenclature"] ? self.nomenclature_naming(hardware_category, network) : (hardware_category == HardwareCategory::ROUTER ? network.network_name : nil)
  end

  def self.meraki_routers_activation(router, inv={})
    router_serial_number = (inv.present? ? inv["serial"] : nil )
    network = router[1].present? ? LocationNetwork.where(id: router[1],organisation_id: router[2]).first : nil
    if network.present?
      self.create({mac_id: router[0].strip, location_network_id: network.try(:id), organisation_id: network.try(:organisation_id), vendor_type: '3', vendor_details: inv, router_serial_number: router_serial_number, model: inv['model'], latitude: inv["lat"].to_s, longitude: inv["lng"].to_s, address: inv["address"]})
      return router[0], true
    else
      self.create({mac_id: router[0].strip, organisation_id: router[2], vendor_type: '3', vendor_details: inv, router_serial_number: router_serial_number, model: inv['model'], latitude: inv["lat"].to_s, longitude: inv["lng"].to_s, address: inv["address"]})
      return router[0], true
    end
  end

  def self.ruckus_routers_activation(router, inv={})
    network = router[1].present? ? LocationNetwork.where(id: router[1],organisation_id: router[2]).first : nil
    if network.present?
      self.create({mac_id: router[0].strip, location_network_id: network.try(:id), organisation_id: network.try(:organisation_id), vendor_type: '5', vendor_details: inv, model: inv['model'], latitude: inv["lat"].to_s, longitude: inv["lng"].to_s, address: inv["address"]})
      return router[0], true
    else
      self.create({mac_id: router[0].strip, organisation_id: router[2], vendor_type: '5', vendor_details: inv, model: inv['model'], latitude: inv["lat"].to_s, longitude: inv["lng"].to_s, address: inv["address"]})
      return router[0], true
    end
  end

  after_save do |x|
    changes = x.changed  - EXTRA_FIELDS 
    if changes.blank?
     changes = x.uplinks.map{|a| a.previous_changes.map{|b| b[0]}}
     changes = changes.flatten.compact
     changes =   changes - EXTRA_FIELDS
    end
    if x.location_network_id_changed?
      x.config_mappings.where(configurable_type: ['NetworkSsid', 'WiredConfig','FirewallConfig','VpnConfig','StaticRoute','RadioProfile']).each(&:delete)
      if x.vendor_type == "3"
        if !x.location_network_id_was.blank? && x.location_network_id.blank?
          begin
            ln=LocationNetwork.where(id: x.location_network_id_was).first
            Meraki::Platform::ConfigurationService.new(ln).remove_network_device(x.router_serial_number)
          rescue

          end
        end
      end
      #Enable the telemetry data for devices
      if x.vendor_type == '4'
        ln=LocationNetwork.where(id: x.location_network_id_was).first
        disable_telemetry = ln.try(:presence)
        # If previous network's presence is enabled and current network presence's disable then we should disable the previous network's telemetry.
        x.enable_telemetry if x.location_network.presence || disable_telemetry
      end
    end
    x.update_redis(true, x.switch?) if (changes.present? ||  (x.changes['tag_list'].present? && RouterInventory.where(location_network_id: x.location_network_id).tagged_with(x.changes['tag_list'][1].try(:flatten), :on => :tags, :any => true).present?) || (x.changes['tag_list'].present? && x.changes['tag_list'][1].blank?))
    if x.location_network.blank?
      $redis.hdel "AP:#{x.mac_id}",["Network","alert"]
    else
      $redis.hset "AP:#{x.mac_id}","Network",x.location_network.network_name
      unless x.location_network.alerts.blank?
        $redis.hset "AP:#{x.mac_id}","alert",'1' 
      else
        $redis.hset "AP:#{x.mac_id}","alert",'0'
      end
    end
    $redis.hset("AP:#{x.mac_id}", "AP", x.name) if x.changes['name'].present?
  end

  before_update do |ri|
    #Rename Router
    org_stng = ri.get_org_stng
    ri.set_name_to_network_name(org_stng) if ri.location_network_id_changed?
  end

  before_save do |ri|
    if ri.mac_id.length == 12
      ri.mac_id = ri.mac_id.try(:upcase).gsub(/(.{2})/,'\1:').slice(0,17)
    else  
      ri.mac_id = ri.mac_id.try(:upcase)
    end  
    # WDS should be enabled always if the uplink type is Bridge
    ri.wds_enabled = true if ri.uplink_type == '2'
  end

  before_create do |ri|
    wired_uplink = ri.uplinks.build(uplink_name: "Wired", uplink_type: "1", wds_enabled: false, ip_type: 'dhcp', is_primary: true, load_balance_percentage: 0,hb_type: 1, hb_interval: self.try(:location_network).try(:hb_freq) || 5)

    master_inventory = MasterRouterInventory.where(:mac_id => ri.mac_id).first
    redis_data = $redis.get "NP:AP:" + "#{ri.mac_id}"
    redis_data = JSON.parse(redis_data) unless redis_data.blank?
    orgspecific_setting = ri.get_org_stng
    org_apn = orgspecific_setting["apn"] 
    apn = org_apn.present? ? org_apn : ""
    wired_uplink.set_custom_dns(orgspecific_setting["custom_dns"]) if orgspecific_setting["custom_dns"].present?
    wired_uplink.set_custom_failover_settings(orgspecific_setting["failoverback"]) if orgspecific_setting["failoverback"].present?
    ri.router_serial_number = master_inventory.serial unless master_inventory.blank?
    if ri.hardware_part_id.nil?
      hw = redis_data.nil? ? master_inventory.try(:hardware_part) : HardwarePart.where(:part_number => redis_data["IN"]["HW_PART_NO"]).first
      ri.hardware_part_id = hw.try(:id)
    end
    if hw.present? && hw.wired_count > 5
      operator_bands = orgspecific_setting['operator_bands']
      operator = orgspecific_setting['operator']
      if redis_data.present?
        uplinks = redis_data["UL"].blank? ? [] : redis_data["UL"].select{|uplink| uplink["TYPE"] == 4 && !uplink["APN"].blank? }
        if uplinks.present?
          uplinks.each do |uplink|
            apn = (uplink["APN"].nil? || uplink["APN"] == "pronto") ? apn : uplink["APN"]
            ri.build_4g_uplink apn,operator_bands,operator,orgspecific_setting unless apn.blank?
          end
        else
          ri.build_4g_uplink apn,operator_bands,operator,orgspecific_setting unless apn.blank?
        end
      else
        ri.build_4g_uplink apn,operator_bands,operator,orgspecific_setting unless apn.blank?
      end
    end
    if master_inventory.present? && master_inventory.wan_mac_address.present?
      ri.mac_id = master_inventory.wan_mac_address.upcase
      ri.name = master_inventory.mac_id
    end
    #Rename Router to network name
    ri.set_name_to_network_name(orgspecific_setting)
  end

  def build_4g_uplink apn,operator_bands,operator,orgspecific_setting
    uplink_4g = self.uplinks.build(uplink_name: "4g", uplink_type: "4", wds_enabled: false, mo_apn: apn, is_primary: false,hb_type: 1, hb_interval: self.try(:location_network).try(:hb_freq) || 5, operator_band: operator_bands, operator: operator)
    uplink_4g.set_custom_dns(orgspecific_setting['custom_dns']) if orgspecific_setting["custom_dns"].present?
  end

  def public_ip
    $redis.hget "AP:#{self.mac_id}", "pub_ip"
  end

  def get_org_stng
    self.organisation.organisation_settings
  end

  def set_name_to_network_name(org_stng)
    self.name = (self.location_network.present? ? self.device_nomenclature(org_stng) : self.mac_id) if org_stng["rename_router"]
  end
  
  def rename_router_allowed?
    self.organisation.organisation_settings["rename_router"] && self.hardware_part.try(:hardware_category).try(:name) == "router"
  end

  def self.change_network(router, network, configuration)
    @ids = []
    router.each do |x|
      inventory = RouterInventory.find_by_id(x)
      if inventory.vendor_type == "3"
         inventory.remove_meraki_device_from_network unless inventory.location_network.blank?
         Rails.logger.info "[MERAKI] REMOVED FROM NETWORK -----------"
        #elsif inventory.vendor_type == "2"
         # network_id = network.vendor_network_id
          #unless inventory.location_network.blank?
              #TODO inventory.remove_aruba_device_from_network
          #end
          #inventory.move_device_in_network(inventory.organisation_id, network_id, inventory.router_serial_number)
      end      
      unless inventory.blank?
        ssids = []
        unless (configuration == "no")
          device_ssids = inventory.associated_network_ssids || []
          device_ssids.each do |device_ssid|
            if (device_ssid.associated_aps_and_tags.length != 1) || (device_ssid.associated_aps_and_tags.grep /^AP/).length == 0
              next
            else
              ssids.push([device_ssid.associated_aps_and_tags,device_ssid])
            end
          end
        end
        inventory.location_network_id = network.id
        inventory.save!
	      inventory.claim_device_in_network [inventory.router_serial_number] if network.present? && ["3", "5"].include?(inventory.vendor_type)
        unless (configuration == "no")
          ssids.each do |ssid|
            ssid[1].reload
            ssid[1].location_network_id = network.id
            ssid[1].associated_aps_and_tags = ssid[0]
            ssid[1].save
          end
        end
      else
        @ids << [x]
      end
    end
    return @ids
  end

  def self.change_HW_part(router, hw)
    router.each do |x|
     inventory = RouterInventory.find_by_id(x)
     next if inventory.blank?
     inventory.hardware_part_id = hw.id
     inventory.save
    end
  end

  def self.validate_router(router,organisation, allow_nonassociated_device=false)
    if router.length == 12
      router = router.gsub(/(.{2})/,'\1:').slice(0,17)
    end
    return false, "MAC ID is not valid. Please check! " if router.blank? || router.match(MAC_ID_REGEX).nil?
    return false, "MAC ID is not valid. Please check! " unless MACID_RANGE_ALLOWED.include?(router.strip[0,8].upcase)
    return false,"You have reached the maximum limit #{organisation.no_of_aps} to add inventories" if organisation.router_inventories.count.to_i >= organisation.no_of_aps.to_i
    a = RouterInventory.find_by_mac_id(router.strip)
    return true, "MAC ID is available!" if a.blank?
    return a, "MAC ID is available!" if a.is_auto_provisioned == true
    #Allow device which are not assocaited with any network but present in org inventory
    return true, "MAC ID is valid" if allow_nonassociated_device && organisation.id == a.organisation_id && a.location_network_id.blank?
    return false, "MAC ID is already Provisioned"
  end

  def self.import(file,current_user,is_auto_provisioned, vendor_type,hw_part)
    count = 0
    tot_count = 0
    status = true
    CSV.foreach(file.path, headers: true) do |row|
      ap = row.to_hash.values
      ap << vendor_type
      ap << hw_part
      router,result = self.router_activation(ap, current_user,is_auto_provisioned) unless ap[0].blank? || ap[0].match(MAC_ID_REGEX).nil?
      tot_count += 1
      count += 1 unless result
      status = result unless result
    end
    return status,count,tot_count
  end

  def is_up?
    threshold_value = Time.zone.now - (self.switch? ? 10.minutes : RouterInventory.get_hb_intreval((self.location_network.try(:hb_freq) || APPLICATION['defaults']['on_or_off']).seconds))
    hb=$redis.hget("AP:#{self.mac_id}", "last_hb")
    
    hb && hb.to_i >= threshold_value.to_i
    
    #last_monitored = MonitoringDataCapped.where('info.NASID' => self.mac_id, 'created_at' => {'$gte' => threshold_value})
    #last_monitored.present?
  end



  def get_uplink_config uplink
      wds_ssid_config = {}
      wds_ssid = nil
      if ["2","3"].include? uplink.uplink_type
        wds_ssid = NetworkSsid.find_by_id uplink.wl_ssid_uniqe_id.to_i
        if wds_ssid.blank?
          wds_ssid_config = { "SSID" => uplink.wl_ssid_name,
                              "SECURITY" => {"AUTH_TYPE"=> uplink.wl_association, "PASS_PHRASE" => uplink.wl_wpa_key},
                              "BAND" => uplink.wl_band.eql?("5") ? "2" : "1",
                              "WDS" => uplink.wds_enabled? ? 1 : 0 }
        else
          wds_ssid_config = { "SSID" => wds_ssid.ssid_name,
                              "SECURITY" => {"AUTH_TYPE"=> wds_ssid.security_mode,"PASS_PHRASE"=> wds_ssid.wpa_key},
                              "BAND" => (wds_ssid.radio_bands.size == 1 && wds_ssid.radio_bands.include?("5")) ? "2" : "1",
                              "WDS" => wds_ssid.wds_enabled? ? 1 : 0 }

        end
      end
      mobile_config = {}
      if uplink.uplink_type == "4"
        operator_band = []
        op_band = uplink.operator_band.split(',') if (uplink.operator_band).present?
        operator_band = op_band.map(&:to_i) if (uplink.operator_band).present?
        mobile_config = { "SERVICE" => '1',
                          "APN" => uplink.mo_apn,
                          "MTYPE" => uplink.uplink_module,
                          "DEVICE" => uplink.mo_is_advanced? ? uplink.mo_device : '',
                          "PROTO" => uplink.mo_is_advanced? ? uplink.mo_proto_key : '',
                          "DLBC" => uplink.default_lbc,
                          "LBC"=>operator_band,
                          "USERNAME" => uplink.mo_username,
                          "PASSWORD" => uplink.mo_password }
      end
      pppoe = {}
      if uplink.uplink_type == "1" && uplink.ip_type == 'pppoe'
        pppoe = {"USERNAME" => uplink.pppoe_username,"PASSWORD" => uplink.pppoe_password }
      end
      return wds_ssid_config, mobile_config, wds_ssid,pppoe
  end

  def self.default_radio
    RadioProfile.default_radio
  end 

  def update_redis(stat = true,switch=false,swhb=false)
    ln = self.location_network
    if self.vendor_type == '4' || (self.vendor_type == '6' && switch)
      config_id = $redis.hget "AP:#{self.mac_id}", "openwifi_config_uuid"
      if config_id.blank?
        Rails.logger.info "[OPENWIFI-#{self.mac_id}] Adding new device configuration"
        OpenWifi::ProvisioningService.new(ln, self.organisation, self).add_device_with_config self,swhb
      else
        Rails.logger.info "[OPENWIFI-#{self.mac_id}] Updating configuration"
        OpenWifi::ProvisioningService.new(ln, self.organisation, self).update_configuration self, config_id,swhb
      end
      unless ln.blank?
        $redis.set self.mac_id, {"BASIC_CONFIG" => {"CONSUME_ID" => Time.now.to_i},"NETWORK_ID" => "lnsocket#{self.location_network.id}"}.to_json if self.vendor_type != '6'
      end
      set_ap_profile(self)
      return true
    end
    unless ln.blank?
      ntp = ln.ntp_server
      ntp = ntp.blank? ? {} : {"ENABLE" => ntp.is_enabled? ? 1 : 0, "NTP_LIST" => ntp.urls.split(',')}
      consume_id = Time.now.to_i.to_s
      unless stat
        a = redis_get "#{self.mac_id}"
        begin
          t = JSON.parse(a)
        rescue
        return
        end
        consume_id = t["BASIC_CONFIG"]["CONSUME_ID"]
        consume_id = consume_id.blank? ? Time.now.to_i.to_s : consume_id
      end
      #Redis for snmp config
      #snmp_config = SnmpConfig.find_by_id(self.snmp_config_id)
      snmp_config = self.associated_snmp_configurations.last
      snmp_config = self.location_network.associated_snmp_configurations.last unless snmp_config.present?
      snmp_config = SnmpConfig.joins(:config_mappings).where(:config_mappings => { :resourceable_type => 'ActsAsTaggableOn::Tag',:resourceable_id.in => self.tags.pluck(:id)}).last unless snmp_config.present?
      snmp_config = snmp_config.blank? ? {} : snmp_config.get_redis_hash
      #Redis for sqm
      sqm = self.associated_sqms.last
      sqm = self.location_network.associated_sqms.last unless sqm.present?
      sqm = Sqm.joins(:config_mappings).where(:config_mappings => { :resourceable_type => 'ActsAsTaggableOn::Tag',:resourceable_id.in => self.tags.pluck(:id)}).last unless sqm.present?
      sqm = sqm.blank? ? {} : sqm.get_redis_hash
      #Redis for port forwarding group
      pfg = []
      (self.associated_portforwarding_groups || []).each{|x| pfg << "portfw#{x.id}"}
      (self.location_network.associated_portforwarding_groups || []).each{|x| pfg << "portfw#{x.id}"}
      (PortforwardingGroup.joins(:config_mappings).where(:config_mappings => { :resourceable_type => 'ActsAsTaggableOn::Tag',:resourceable_id.in => self.tags.pluck(:id)}) || []).each{|x| pfg << "portfw#{x.id}"}
      pfg = pfg.uniq
      # #Redis for static routes
      # routes = self.associated_static_routes.last
      # routes = self.location_network.associated_static_routes.last unless routes.present?
      # routes = StaticRoute.joins(:config_mappings).where(:config_mappings => { :resourceable_type => 'ActsAsTaggableOn::Tag',:resourceable_id.in => self.tags.pluck(:id)}).last unless routes.present?
      # routes = routes.blank? ? {} : routes.get_redis_hash
      #Redis for commands
       cmds = []; (self.commands.where(status: "pending") || []).each{|x| cmds << { "CMD_ID" => x.id,"CMD"=>x.commands}.to_json}
        #replace find_all_by_status with where coz deprecated in Rails 4.1 
       p "Commands Length:",cmds.length
      #Redis for ACL group
      acl = []
      client_devices = $redis.scard("LN:#{self.location_network.id}:BLOCKED:CLIENTS:LIST")
      acl << "LN:#{self.location_network.id}:ACL:BLOCK:CLIENTS" if client_devices > 0
      (self.associated_acl_groups || []).each{|x| if x.access_control_lists.present?;acl << "acl#{x.id}";end;}
      (self.location_network.associated_acl_groups || []).each{|x| if x.access_control_lists.present?;acl << "acl#{x.id}";end;}
      (AclGroup.joins(:config_mappings).where(:config_mappings => { :resourceable_type => 'ActsAsTaggableOn::Tag',:resourceable_id.in => self.tags.pluck(:id)}) || []).each{|x| if x.access_control_lists.present?;acl << "acl#{x.id}";end;}
      acl = acl.uniq
      #ediss for ACL Group Layer7
      acll7 = []
      (self.associated_acl_groups || []).each{|x| if x.access_control_list_layer_nines.present?;acll7 << "acll7:#{x.id}";end;}
      (self.location_network.associated_acl_groups || []).each{|x| if x.access_control_list_layer_nines.present?;acll7 << "acll7:#{x.id}";end;}
      (AclGroup.joins(:config_mappings).where(:config_mappings => { :resourceable_type => 'ActsAsTaggableOn::Tag',:resourceable_id.in => self.tags.pluck(:id)}) || []).each{|x| if x.access_control_list_layer_nines.present?;acll7 << "acll7:#{x.id}";end;}
      acll7 = acll7.uniq      
      
      #Redis for Static Route
      routes = []
      (self.associated_static_routes || []).each{|x| routes << "route#{x.id}"}
      (self.location_network.try(:associated_static_routes) || []).each{|x| routes << "route#{x.id}"}
      (StaticRoute.joins(:config_mappings).where(:config_mappings => { :resourceable_type => 'ActsAsTaggableOn::Tag',:resourceable_id.in => self.tags.pluck(:id)}) || []).each{|x| routes << "route#{x.id}"}
      routes = routes.uniq

      #Redis for sim Management ########

      #Redis for Wired Config
      wired_config = self.associated_wired_config
      wired_config = ln.associated_wired_config unless wired_config.present?
      wired_config_object = wired_config
      wired_config = wired_config.try(:id)

      #find all associated netwok ssids from network, self, tags
      ssids = self.get_all_associated_ssids ln
      $redis.hset "AP:#{self.mac_id}", "ssids", ssids.inject({}) {|h, s| h[s.ssid_name] = s.id;h}.to_json
      #Redis for VLan
      vlan_ssid = []
      vlan_wired = []
      wired_vlan_ids = []
      #vlanids = VLan.where(id: ssids.collect(&:vlan_id).compact)
      ssid_vlan_ids = (ssids.map {|a| [a.v_lan.try(:id), a.v_lan.try(:v_lan_id)] if a.ssid_mode == '0' && a.v_lan.present? && a.v_lan.v_lan_id != '0'}).compact.uniq
      res_ssids_vlan_ids = []
      ssid_vlan_ids.each{|a| res_ssids_vlan_ids << a unless res_ssids_vlan_ids.map(&:last).include?(a[1])}

      #(ssid_vlan_ids || []).each {|vl| vlan_ssid << "vl#{vl}"}
      #vlanids = VLan.where(wired_config_id: wired_config.try(:id))
      #vlanids = wired_config_object.present? ? wired_config_object.try(:v_lans) : []
      #(vlanids || []).each {|vl| vlan_wired << "vl#{vl.id}"}
      #(vlanids || []).each {|vl| wired_vlan_ids << vl.v_lan_id}
      piap_version = redis_hgetall("AP:#{self.mac_id}")['version']
      if piap_version.blank? || piap_version.gsub('.','').to_i > 20222
        vlanids = wired_config_object.present? ? wired_config_object.try(:v_lans) : []
        (vlanids || []).each {|vl| vlan_wired << "vl#{vl.id}"}
        (vlanids || []).each {|vl| wired_vlan_ids << vl.v_lan_id}
      end
      res_ssids_vlan_ids.each {|vl| vlan_wired << "vl#{vl[0]}" if !wired_vlan_ids.include?(vl[1])}
      
      #Redis profile for associated radio profile
      radio_profile = self.get_associated_radio_profile ln
      adv_option = {"ART" => "-75",  "KSR"=> "-78"}
      if radio_profile.present?
	rm = radio_profile.radio_management
	adv_option = {"ART"=>rm.required_probe_snr.present? ? rm.required_probe_snr : "-75",  "KSR" =>  rm.required_roam_snr.present? ? rm.required_roam_snr : "-78"} if !rm.blank?
      end
      radio_profile = radio_profile.present? ? ["radio#{radio_profile.id}"] : ["default_radio"]
      if self.vendor_type == '3'
        Meraki::Wireless::ConfigurationService.new(ln).update_device_radio_profile self
      end

      uplink_configs = []
      self.uplinks.each do |uplink|
        wds_ssid_config, mobile_config, wds_ssid,pppoe = get_uplink_config(uplink) #TODO: create method for this
        ssids.delete(wds_ssid) unless wds_ssid.blank?
        mobile_config["LBC"] = operator_band if !operator_band.nil?
        upobj = {"TYPE" => uplink.uplink_type.blank? ? "1" : uplink.uplink_type,
                           "PROTO"=>uplink.ip_type.blank? ? "dhcp" : uplink.ip_type,
                           "IPADDR"=>uplink.ip,
                           "NETMASK"=>uplink.subnet_mask,
                           "GATEWAY"=>uplink.gateway,
                           "PRI_DNS"=>uplink.primary_dns,
                           "SEC_DNS"=>uplink.secondary_dns,
                           "DNS_MODE" => uplink.dns_mode,
                           "UID"=>uplink.id.to_s,
                           "UPLINK_NAME"=>uplink.uplink_name,
                           "DLBC"=>uplink.default_lbc,
                           "TTL"=>uplink.ttl,
                           "HBT" => uplink.hb_type.to_s,
                           "HBI" => uplink.hb_interval.to_s,
                           "HA"=>{"PRI"=>uplink.is_primary? ? 1 : 0,"LB"=>self.enable_lb? ? uplink.load_balance_percentage : 0},
                           "RETRY_COUNT" => "1",#self.retry_count.to_s,
                           "MON_INT" => "5",#self.retry_interval.to_s,
                           "MON_IP1" => self.retry_ip1,
                           "MON_IP2" => self.retry_ip2,
                           "RANGE_START"=>self.dhcp_start_range,
                           "RANGE_END"=>self.dhcp_end_range,
                           "GRE"=>self.enable_gre_on_lan,
                           "DHCP_RELAY"=>self.enable_dhcp_on_lan,
                           "SSID_CONFIG" => wds_ssid_config,
                           "MOBILE_CONFIG" => mobile_config,
                           "PPPOE_CONFIG" => pppoe}
        upobj["MWAN3_CFG"] = uplink.mwan3_config_hsh if uplink.mwan3_config_applicable?
        uplink_configs << upobj
     end
      #Redis for firewall config
      firewall_config = self.associated_firewall_configs.last
      firewall_config = self.location_network.associated_firewall_configs.last unless firewall_config.present?
      if firewall_config.present?
        firewall_config = firewall_config.client_communications.order('priority asc').map do |f|
          if f.source_interface == '-1' || f.destination_interface == '-1'
            rule = set_firewall_old_rules(f.source_interface,f.destination_interface, wired_config, ssids.map(&:id))
          else  
            rule = set_firewall_rules(f.source_interface,f.destination_interface, wired_config, ssids.map(&:id))
          end
          next if rule[0].blank? || rule[1].blank?
          {"SRC_UNIQ_ID" => rule[0],"DST_UNIQ_ID" => rule[1] ,"POLICY" => f.policy,"UNIDIR"=>f.unidir}
        end
      else
        {"SRC_UNIQ_ID"=>0,"DST_UNIQ_ID"=>0,"POLICY"=>"1"}
      end
      ssids = ssids.map {|s| "ns#{s.id}"}

     #Redis for Logging and Event Logging
      logging = self.associated_loggings.last
      logging = self.location_network.associated_loggings.last unless logging.present?
      logging = Logging.joins(:config_mappings).where(:config_mappings => { :resourceable_type => 'ActsAsTaggableOn::Tag',:resourceable_id.in => self.tags.pluck(:id)}).last unless logging.present?
      event = Logging.where(:location_network_id => ln.id,logging_type: 'event_logging')
      alert_condition = []
      Alert.where(:location_network_id => ln.id).each{|al| alert_condition << al.alert_rules.pluck(:condition)}
      alert_condition = alert_condition.flatten.compact.uniq
      event_alert = alert_condition.map{|a| Alert::ALERT_EVENT_TYPE[a]}
      event_alert = event_alert.flatten.compact
      event_hash = event.present? ? {"ENABLE" => 1,"ALERTS" => event_alert} : {"ENABLE" => 0,"ALERTS" => event_alert}
      if logging.present?
      calea_hash = {"NAME" => logging.name,"ENABLE" => logging.is_enabled.to_i,"UPLOAD_TYPE" => logging.upload_type,"UPLOAD_URL" => logging.extra_data['upload_url'],"UPLOAD_USERNAME" => logging.extra_data['uploaded_user'], "UPLOAD_PASSWD" => logging.extra_data['upload_password']}
      else
        calea_hash = {}
      end
      syslog = Logging.where(:location_network_id => ln.id,logging_type: 'sys_log').last
      syslog_hash ={}
      unless syslog.blank?
        syslog_hash = {"REM_IP"=>syslog.extra_data['ip_address'],"REM_PORT"=>syslog.extra_data['port'],"REM_PROTO"=>"udp","ENABLE"=>syslog.is_enabled.to_i}
        syslog_hash["REM_LOG_MODE"] = "2" if syslog.name.include?("DEBUG_") unless syslog.blank?
      end      
      #Redis for VPN Config
      v_configs = self.associated_vpn_configs
      v_configs = self.location_network.associated_vpn_configs unless v_configs.present?
      vpn_config_hash = []
      v_configs.each do |v|
        peer_arr = []
        vpn_hash = {"CONNECTION_NAME" => v.id.to_s,"TC" => v.tunnel_connection,"IKE_LIFETIME" => v.ike_time,"LOCAL_SUBNET" => v.l_subnet,"SER_CLI" => (v.enable_server_client ? 1 : 0),"REMOTE_IP" => (v.enable_server_client && v.is_server ? 'any' : v.remote_ip),"REMOTE_NW_IP" => v.remote_nw_ip,"REMOTE_SUBNET" => v.remote_nw_subnet, "PRE_SHARED_KEY" => Base64.urlsafe_encode64(v.pre_shared_key),"IKE" => v.ike + "!","ESP" => v.esp  + "!", } if v.is_enabled == '1'
        if (v.is_enabled == '1')
          if v.protocol == "Wireguard"
            vpn_hash["TY"] = "2"
          else
            vpn_hash["TY"] = "1"
          end
      
          if (v.wireguard == "client")
            peer_hash = {"PPUBK" => v.public_key, "PIP" =>  v.end_point_ip, "PPORT" => v.end_point_port, "ALIPS" => v.allowed_ips}
            peer_arr.push(peer_hash)
            vpn_hash["VPTN"] = v.wireguard_passthrough
            vpn_hash["WPL"] = peer_arr
            vpn_hash["MPORT"] = v.listener_port  if (v.listener_port != "")
            vpn_hash["SER_CLI"] = 1 if (v.wireguard != "")
            vpn_hash["PSK"] = v.psk if v.psk != ""
          elsif (v.wireguard == "server")
            vpn_hash["MPORT"] = v.listener_port if (v.listener_port != "")
            vpn_hash["VGW"] = v.wireguard_gateway_ip
            vpn_hash["VNAT"] = v.wireguard_enable_nat? ? 1:0
            vpn_hash["SER_CLI"] = 1 if (v.wireguard != "")
            vpn_hash["PSK"] = v.psk if v.psk != ""
            (v.server_peer).each do |peer|
              peer_hash = {"PPUBK" => peer["public_key"], "ALIPS" =>  peer["ips"]}
              peer_arr.push(peer_hash)
            end
            vpn_hash["WPL"] = peer_arr
          elsif (v.wireguard == "site_to_site")
            peer_hash = {"PPUBK" => v.public_key, "PIP" =>  v.end_point_ip, "PPORT" => v.end_point_port, "ALIPS" => v.allowed_ips}
            peer_arr.push(peer_hash)
            vpn_hash["MPORT"] = v.listener_port  if (v.listener_port != "")
            vpn_hash["WPL"] = peer_arr
            vpn_hash["SER_CLI"] = 0 if (v.wireguard != "")
            vpn_hash["PSK"] = v.psk if v.psk != ""
          else
            vpn_hash["VPTN"] = v.pass_through if v.pass_through != ""
            vpn_hash["VGW"] = v.gateway_ip if v.gateway_ip != ""
            vpn_hash["VNAT"] = v.enable_nat? ? 1:0
          end
          vpn_hash["PRIK"] = v.private_key if (v.private_key != "")
          vpn_hash["MIP"] = v.address if (v.address != "")
          vpn_hash["MTU"] = (v.mtu).present? ? v.mtu : nil
          vpn_config_hash << vpn_hash
        end
      end

      redis_set "#{self.mac_id}", {"BASIC_CONFIG" => {"HB_SERVER_URL"=>(ln.try(:heartbeat_url) || self.organisation.try(:heartbeat_url) || APPLICATION[Rails.env]["heartbeat_url"]),
                                                      "PRESENCE_SERVER_URL"=> get_presence_url(),
                                                      "ALERTS_SERVER_URL"=>APPLICATION[Rails.env]["alerts_server_url"],
                                                      "HB_INTERVAL"=>ln.try(:hb_freq).to_i || 5,
                                                      "PRESENCE" => get_presence(),
                                                      "RELAY_SERVER"=>self.dhcp_relay,
                                                      "NAS_NAME"=>(self.name || self.mac_id.gsub(":","-")),
                                                      "GRE_SERVER"=>self.gre,
                                                      "PCI"=>self.enable_pci? ? 1 : 0,
							"CONSUME_ID"=>consume_id},
                                  "SSID_CONFIG" => ln.blank? ? "": ssids,
                                  "SNMP_CONFIG" => snmp_config,
                                  "SQM_CFG" => sqm,
                                  "RADIO_CONFIG" => {"CHANNEL" => self.channel.blank? ? "6": self.channel,
                                                   "TXPOWER"=>self.power.blank? ? "20": self.power},
                                  "PORTS_CONFIG" => {"CUSTOM" => wired_config_object.try(:custom_port?) ? wired_config_object.try(:custom_port) : 0,
                                                     "PORT_LIST" => wired_config_object.try(:port_configs),
                                                     "QOS" => {"BW_ENABLE" => wired_config_object.try(:enable_ssid_qos?) ? 1 : 0, "BW"=> "#{wired_config_object.try(:ssid_qos).to_i}"},
                                                     },
                                  "VLAN_CONFIG" =>  vlan_wired,
                                  "LAN_CONFIG" => {"PROTO"=>self.ip_type.blank? ? "dhcp" : self.ip_type,
                                                   "IPADDR"=>self.ip,
                                                   "NETMASK"=>self.subnet_mask,
                                                   "GATEWAY"=>self.gateway,
                                                   "PRI_DNS"=>self.primary_dns,
                                                   "SEC_DNS"=>self.secondary_dns,
                                                   "RANGE_START"=>self.dhcp_start_range,
                                                   "RANGE_END"=>self.dhcp_end_range,
                                                   "GRE"=>self.enable_gre_on_lan,
                                                   "DHCP_RELAY"=>self.enable_dhcp_on_lan},
                                  "UPLINK_CONFIG" => uplink_configs,
                                  "PORT_FWD_CONFIG" => pfg,
                                  "ACL_CONFIG" => acl,
                                  "ACL_MISC" => {"LOG_TYPE"=>"4"},
                                  "ACL_CONFIG_L7" => acll7,
                                  "STATIC_ROUTING_CONFIG" => routes,
                                  "COMMANDS" => cmds,
                                  "NETWORK_ID" => ln.blank? ? "" : "lnsocket#{ln.id}",
                                  "NTP_CONFIG" => ntp,
                                  "RADIO_PROFILES"=> radio_profile,
				  "ADV_RADIO" => adv_option,
                                  "PRESENCE_CONFIG" => {"ENABLE" => get_presence(), "TAG" => "#{self.mac_id}"},
                                  "WIRED_CONFIG" => wired_config.blank? ? "" : "wc#{wired_config}",
                                  "FIREWALL" => {"CL_COMM" => (firewall_config || []).compact},
                                  "MISC_CONFIG" => {"CALEA_CONFIG" => calea_hash,"EVENT_LOG" => event_hash,"SYSLOG_CFG"=>syslog_hash},
                                  "VPN_CFG" => vpn_config_hash}.to_json
      self.update_router_config if stat
    else
      redis_del "#{self.mac_id}"
    end
    set_ap_profile(self)
  end
  
  def get_presence_url()
      if self.presence_url.present?
         presence_url = self.presence_url
      else
        network = self.location_network
        presence_url = (network.present? && network.presence_url.present?) ?  network.presence_url :  APPLICATION[Rails.env]["presence_url"]
      end
      return presence_url
  end 

  def get_presence()
    if self.presence 
      presence = self.presence ? 1 : 0
    else
      network = self.location_network
      presence = (network.present? && network.presence) ? 1 : 0
    end
    return presence
  end
  
  def self.set_configuration_data
    location_networks = LocationNetwork.all.includes(:network_ssids)
    unless location_networks.blank?
      location_networks.each do |x|
        a = []; vlan = [];
        network_ssids = x.network_ssids
        next if network_ssids.blank?
        network_ssids.each do |ssid|
          logger.info("in ssid #{ssid.id}")
          radius_auth_server = RadiusConfiguration.find_by_id(ssid.auth_radius_id)
          radius = {"AUTH_TYPE"=> (ssid.security_mode.blank? ? 'none' : ssid.security_mode) ,"PASS_PHRASE"=> ssid.wpa_key}
          unless radius_auth_server.blank?
            logger.info("in radius_auth_server #{ssid.id}")
            radius["AUTH_SERVER"] = radius_auth_server.radius_ip
            radius["AUTH_PORT"] = radius_auth_server.radius_port
            radius["AUTH_SECRET"] = radius_auth_server.radius_secret
          end
          radius_auth_server = RadiusConfiguration.find_by_id(ssid.acc_radius_id)
          unless radius_auth_server.blank?
            logger.info("in radius_acc_server #{ssid.id}")
            radius["ACCT_SERVER"] = radius_auth_server.radius_ip
            radius["ACCT_PORT"] = radius_auth_server.radius_port
            radius["ACCT_SECRET"] = radius_auth_server.radius_secret
          end
          vlanid = VLan.find_by_id(ssid.vlan_id)
          vlan << "vl#{vlanid.id}" unless vlanid.blank?
          vlanid = vlanid.v_lan_id unless vlanid.blank?

          redis_set "ns#{ssid.id}", { "SSID_UNIQ_ID"=> ssid.id.to_s,
                                      "MODE_ROUTER"=> ssid.ssid_mode.to_i,
                                      "NAT" => ssid.nat.to_i,
                                      "WNA" => ssid.wna.to_i,
                                      "SSID"=> ssid.ssid_name,
                                      "DISABLE"=> (ssid.is_enabled ? 0 : 1) ,
                                      "HIDDEN" => (ssid.is_hidden ? 1 : 0) ,
                                      "ISOLATE" => (ssid.is_isolate ? 1 : 0) ,
                                      "PROTO"=> "static",
                                      "VLANID"=>vlanid,
                                      "IPADDR"=> ssid.ip_address,
                                      "NETMASK"=> ssid.subnet_mask,
                                      "ACL_MAC"=> { "MAC_FILTER_ENABLE" => (ssid.acl_mac).to_i,
                                                    "MAC_FILTER_POLICY" => ssid.mac_filter_policy.to_i,
                                                    "ACL_MAC_LIST" => (ssid.acl_mac_list.blank? ? [] : ssid.acl_mac_list.split(",")) },
                                      "QOS" => {"BW_ENABLE" => (ssid.enable_ssid_qos? ? 1 : 0),
                                                "BW"=> "#{ssid.ssid_qos.to_i}"},
                                      "SECURITY" => radius,
                                      "DHCP"=>{ "LEASE_TIME"=>ssid.dhcp_lease_time,
                                                "DHCP_ENABLE"=> ssid.dhcp_relay_server,
                                                "RANGE_START"=>(["1","3"].include?self.dhcp_relay_server) ? "" : self.dhcp_range_start,
                                                "RANGE_END"=>ssid.dhcp_range_end,
                                                "MAPPINGS" => ssid.dhcp_mappings,
                                                "RANGES" => ssid.dhcp_ranges},
                                      "CAPTIVE_PORTAL" => { "PORTAL_ENABLE"=>(ssid.captive_portal.to_i),
                                                            "PORTAL_REDIR_URL"=>ssid.splash_url,
                                                            "WL_ENABLE" =>(ssid.wallgarden).to_i,
                                                            "WL_CONFIG" => (ssid.walled_garden_range.blank? ? [] : ssid.walled_garden_range.split(",")),
                                                            "QOS" => {"BW_ENABLE" => (ssid.per_user_qos.to_i == 0 ? 0 : 1),
                                                                      "BW"=> "#{ssid.per_user_qos.to_i}"},
                                                                      "DEF_INT_UPDATE_INTV" => self.default_interim_time,"DEF_IDLE_TO" => self.default_idle_timeout
                                                                      },
                                      "BAND" => ssid.get_radio_band,
                                      "MAX_ASSOC" => "#{ssid.max_association}",
                                      "DEVICE_5GHZ" => (ssid.radio_bands.size == 1 && ssid.radio_bands.include?('5')) ? 1 : 0,
                                      "WDS" => ssid.wds_enabled? ? 1 : 0,
                                      "DNS" => {"MODE" => ssid.dns_mode,
                                                "PRI_DNS" => ssid.dns_primary.to_s,
                                                "SEC_DNS" => ssid.dns_secondary.to_s}
                                    }.to_json
          logger.info("ssid in redis #{ssid.id}")
          a << "ns#{ssid.id}"
          logger.info("ssid in array #{ssid.id}")
        end
        redis_set "ln#{x.id}", a.to_json
        inventorys = x.router_inventories

        ntp = x.ntp_server
        ntp = ntp.blank? ? {} : {"ENABLE" => ntp.is_enabled? ? 1 : 0, "NTP_LIST" => ntp.urls.split(',')}
        unless inventorys.blank?
          inventorys.each do |inv|
            #Redis for snmp config
            #snmp_config = SnmpConfig.find_by_id(inv.snmp_config_id)
            snmp_config = inv.associated_snmp_configurations.last
            snmp_config = inv.location_network.associated_snmp_configurations.last unless snmp_config.present?
            snmp_config = SnmpConfig.joins(:config_mappings).where(:config_mappings => { :resourceable_type => 'ActsAsTaggableOn::Tag',:resourceable_id.in => inv.tags.pluck(:id)}).last unless snmp_config.present?
            snmp_config = snmp_config.blank? ? {} : snmp_config.get_redis_hash
            #Redis for sqm
            sqm = inv.associated_sqms.last
            sqm = inv.location_network.associated_sqms.last unless sqm.present?
            sqm = Sqm.joins(:config_mappings).where(:config_mappings => { :resourceable_type => 'ActsAsTaggableOn::Tag',:resourceable_id.in => inv.tags.pluck(:id)}).last unless sqm.present?
            sqm = sqm.blank? ? {} : sqm.get_redis_hash
            #Redis for pfg config
            pfg = []
            (inv.associated_portforwarding_groups || []).each{|x| pfg << "portfw#{x.id}"}
            (inv.location_network.associated_portforwarding_groups || []).each{|x| pfg << "portfw#{x.id}"}
            (PortforwardingGroup.joins(:config_mappings).where(:config_mappings => { :resourceable_type => 'ActsAsTaggableOn::Tag',:resourceable_id.in => inv.tags.pluck(:id)}) || []).each{|x| pfg << "portfw#{x.id}"}
            pfg = pfg.uniq
            #Redis for commands
             cmds = []; (inv.commands.find_all_by_status("pending") || []).each{|x| cmds << { "CMD_ID" => x.id,"CMD"=>x.commands}.to_json}
            #Redis for acl
            acl = []
            client_devices = $redis.scard("LN:#{self.location_network.id}:BLOCKED:CLIENTS:LIST")
            acl << "LN:#{self.location_network.id}:ACL:BLOCK:CLIENTS" if client_devices > 0
            (inv.location_network.associated_acl_groups || []).each{|x| acl << "acl#{x.id}"}
            (AclGroup.joins(:config_mappings).where(:config_mappings => { :resourceable_type => 'ActsAsTaggableOn::Tag',:resourceable_id.in => inv.tags.pluck(:id)}) || []).each{|x| acl << "acl#{x.id}"}
            acl = acl.uniq

            #Redis for Static Route
            routes = self.associated_static_routes.last
            routes = self.location_network.associated_static_routes.last unless routes.present?
            routes = StaticRoute.joins(:config_mappings).where(:config_mappings => { :resourceable_type => 'ActsAsTaggableOn::Tag',:resourceable_id.in => self.tags.pluck(:id)}).last unless routes.present?
            routes = routes.blank? ? {} : routes.get_redis_hash
            #Redis for Static Route
      	    # routes = []
      	    # (self.associated_static_routes || []).each{|x| routes << "route#{x.id}"}
      	    # (self.location_network.associated_static_routes || []).each{|x| routes << "route#{x.id}"}
      	    # (AclGroup.joins(:config_mappings).where(:config_mappings => { :resourceable_type => 'ActsAsTaggableOn::Tag',:resourceable_id.in => self.tags.pluck(:id)}) || []).each{|x| routes << "route#{x.id}"}
      	    # routes = routes.uniq

            #find all associated netwok ssids from network, self, tags
            ssids = Set.new
            ssids += inv.associated_network_ssids
            ri_tags = inv.tags.pluck(:id)
            ssids += x.network_ssids.joins(:config_mappings).where("resourceable_type = 'ActsAsTaggableOn::Tag' AND resourceable_id IN (?)", ri_tags) unless ri_tags.blank?
            ssids += x.network_ssids.joins(:config_mappings).where("resourceable_type = 'LocationNetwork' AND resourceable_id = ?", x.id)
            ssids += x.network_ssids.joins(:config_mappings).where("resourceable_type = 'HardwareCategory' AND resourceable_id = ?", inv.hardware_part.hardware_category.id) unless inv.hardware_part_id.blank?
            radios = []
            radio_profile = inv.associated_radio_profile
            radio_profile = inv.location_network.associated_radio_profile unless radio_profile.present?
	    adv_option = {"ART" => "-75",  "KSR"=> "-78"}
            unless radio_profile.blank?
	      rm = radio_profile.radio_management
	      adv_option = {"ART"=>rm.required_probe_snr.present? ? rm.required_probe_snr : "-65",  "KSR" =>  rm.required_roam_snr.present? ? rm.required_roam_snr : "-78"} if !rm.blank?
              radios << "radio#{radio_profile.id}"
            else
              radios << "default_radio"
            end

            wds_ssid_config = {}
            if ["2","3"].include? inv.uplink_type
              wds_ssid = NetworkSsid.find_by_id inv.wl_ssid_uniqe_id.to_i
              if wds_ssid.blank?
                wds_ssid_config = { "SSID" => inv.wl_ssid_name,
                                    "SECURITY" => {"AUTH_TYPE"=> inv.wl_association, "PASS_PHRASE" => inv.wl_wpa_key},
                                    "BAND" => inv.wl_band.eql?("5") ? "2" : "1",
                                    "WDS" => inv.wds_enabled? ? 1 : 0 }
              else
                wds_ssid_config = { "SSID" => wds_ssid.ssid_name,
                                    "SECURITY" => {"AUTH_TYPE"=> wds_ssid.security_mode,"PASS_PHRASE"=> wds_ssid.wpa_key},
                                    "BAND" => (wds_ssid.radio_bands.size == 1 && wds_ssid.radio_bands.include?("5")) ? "2" : "1",
                                    "WDS" => wds_ssid.wds_enabled? ? 1 : 0 }
                ssids.delete(wds_ssid)
              end
            end

            mobile_config = {}
            if inv.uplink_type == "4"
              mobile_config = { "SERVICE" => '1',
                                "APN" => inv.mo_apn,
                                "DEVICE" => inv.mo_is_advanced? ? inv.mo_device : '',
                                "PROTO" => inv.mo_is_advanced? ? inv.mo_proto_key : '',
                                "USERNAME" => inv.mo_username,
                                "PASSWORD" => inv.mo_password }
            end

            wired_config = inv.device_wired_config(x)
            #Redis for firewall config
            firewall_config = self.associated_firewall_configs.last
            firewall_config = self.location_network.associated_firewall_configs.last unless firewall_config.present?
            if firewall_config.present?
              firewall_config = firewall_config.client_communications.order('priority asc').map do |f|
                rule = set_firewall_rules(f.source_interface,f.destination_interface, wired_config, ssids.map(&:id))
                next if rule[0].blank? || rule[1].blank?
                {"SRC_UNIQ_ID" => rule[0],"DST_UNIQ_ID" => rule[1] ,"POLICY" => f.policy}
              end
            else
              {"SRC_UNIQ_ID"=>0,"DST_UNIQ_ID"=>0,"POLICY"=>"1"}
            end
            #Set array of ssid config
            ssids = ssids.map {|s| "ns#{s.id}"}

            redis_set "#{inv.mac_id}", {"BASIC_CONFIG" => {"HB_SERVER_URL"=>inv.location_network.try(:heartbeat_url) || inv.organisation.try(:heartbeat_url) || APPLICATION[Rails.env]["heartbeat_url"],
                                                           "PRESENCE_SERVER_URL"=>inv.presence_url.blank? ? APPLICATION[Rails.env]["presence_url"] : inv.presence_url,
                                                           "ALERTS_SERVER_URL"=>APPLICATION[Rails.env]["alerts_server_url"],
                                                           "HB_INTERVAL"=> inv.location_network.try(:hb_freq).to_i || 5,
                                                           "PRESENCE" => inv.presence? ? 1 : 0,
                                                           "RELAY_SERVER"=>inv.dhcp_relay,
                                                           "GRE_SERVER"=>inv.gre,
                                                           "CONSUME_ID"=>Time.now.to_i.to_s},
                                        "SSID_CONFIG" => ssids,
                                        "SNMP_CONFIG" => snmp_config,
                                        "SQM_CFG" => sqm,
                                        "RADIO_CONFIG" => {"CHANNEL"=>inv.channel.blank? ? "6" : inv.channel ,
                                                           "TXPOWER"=>inv.power.blank? ? "20": inv.power },
                                        "VLAN_CONFIG" => vlan,
                                        "LAN_CONFIG" => {"PROTO"=>inv.ip_type.blank? ? "dhcp" : inv.ip_type,
                                                        "IPADDR"=>inv.ip,
                                                        "NETMASK"=>inv.subnet_mask,
                                                        "GATEWAY"=>inv.gateway,
                                                        "PRI_DNS"=>inv.primary_dns,
                                                        "SEC_DNS"=>inv.secondary_dns,
                                                        "RANGE_START"=>inv.dhcp_start_range,
                                                        "RANGE_END"=>inv.dhcp_end_range,
                                                        "GRE"=>inv.enable_gre_on_lan,
                                                        "DHCP_RELAY"=>inv.enable_dhcp_on_lan},
                                        "UPLINK_CONFIG" => [{"TYPE" => inv.uplink_type.blank? ? "1" : inv.uplink_type,
                                                            "PROTO"=>inv.ip_type.blank? ? "dhcp" : inv.ip_type,
                                                            "IPADDR"=>inv.ip,
                                                            "NETMASK"=>inv.subnet_mask,
                                                            "GATEWAY"=>inv.gateway,
                                                            "PRI_DNS"=>inv.primary_dns,
                                                            "SEC_DNS"=>inv.secondary_dns,
                                                            "RANGE_START"=>inv.dhcp_start_range,
                                                            "RANGE_END"=>inv.dhcp_end_range,
                                                            "GRE"=>inv.enable_gre_on_lan,
                                                            "DHCP_RELAY"=>inv.enable_dhcp_on_lan,
                                                            "SSID_CONFIG" => wds_ssid_config,
                                                            "MOBILE_CONFIG" => mobile_config}],
                                        "PORT_FWD_CONFIG" => pfg,
                                        "ACL_CONFIG" => acl,
                                        "STATIC_ROUTING_CONFIG" => routes,
                                        "COMMANDS" => cmds,
                                        "NETWORK_ID" => "lnsocket#{x.id}",
                                        "NTP_CONFIG" => ntp,
                                        "RADIO_PROFILES" => radios.uniq,
					"ADV_RADIO" => adv_option,
                                        "PRESENCE_CONFIG" => {"ENABLE" => inv.presence? ? "1" : "0", "TAG" => "#{inv.mac_id}"},
                                        "WIRED_CONFIG" => wired_config.blank? ? "" : "wc#{wired_config}","FIREWALL" => {"CL_COMM"=> (firewall_config || []).compact}}.to_json
            logger.info("added inventory to redis #{inv.mac_id}")
          end
        end
      end
    end
    #Set VLAN Config
    VLan.all.each do |vlan|
      vlan.set_redis
    end
    #Set Radio Profile Config
    RadioProfile.set_default_radio
    RadioProfile.all.each do |r|
      r.set_redis
    end
    acl_group = AclGroup.all.includes(:access_control_lists)
    unless acl_group.blank?
      acl_group.each do |aclg|
        next if  aclg.access_control_lists.blank?
        acl = []
        aclg.access_control_lists.each do |x|
          acl << {"PROTO"=> x.protocol,"SRC_IPADDR"=>x.src_ip,"SRC_MAC"=>x.src_mac,"SRC_BITMASK"=>x.scr_bitmask,"SRC_PORT"=>x.src_port,"DST_IPADDR"=>x.dst_ip,"DST_BITMASK"=>x.dst_bitmask,"DST_PORT"=>x.dst_port,"POLICY"=>x.policy.to_i}.to_json
        end
        redis_set "acl#{aclg.id}", acl.to_json
      end
    end
    #Set Static Routing Lists
     static_routes = StaticRoute.all.includes(:static_routing_lists)
    unless static_routes.blank?
      static_routes.each do |aclg|
        next if  aclg.static_routing_lists.blank?
        acl = []
        aclg.static_routing_lists.each do |x|
          acl << {"NETWORK"=>x.network,"BITMASK"=>x.bitmask,"GATEWAY"=>x.gateway}.to_json
        end
        redis_set "route#{aclg.id}", acl.to_json
      end
    end
    #Set Port Forwarding Group
    acl_group = PortforwardingGroup.all.includes(:port_forwardings)
    unless acl_group.blank?
      acl_group.each do |aclg|
        next if  aclg.port_forwardings.blank?
        acl = []
        aclg.port_forwardings.each do |x|
          acl << {"PROTO"=> x.protocol,"ORIG_IP"=>x.ip_address,"ORIG_PORT"=>x.external_port,"FWD_IP"=>x.ip_address,"FWD_PORT"=>x.internal_port}.to_json
        end
        redis_set "portfw#{aclg.id}", acl.to_json
      end
    end
    snmp_configs = SnmpConfig.all
    unless snmp_configs.blank?
      snmp_configs.each do |snmp|
        redis_set "snmp#{snmp.id}", {"SERVER_IP"=> snmp.server_ip,"SERVER_PORT"=>snmp.server_port,"SERVER_COMMUNITY"=>snmp.server_community,"RO_COMMUNITY"=>snmp.ro_community,"RW_COMMUNITY"=>snmp.rw_community}.to_json
      end
    end
    sqms = Sqm.all
    unless sqms.blank?
      sqms.each do |sqm|
        redis_set "sqm#{sqm.id}", {"ENABLE"=> sqm.is_enabled,"ULT"=>sqm.uplink,"DL_BW"=>sqm.download_speed,"UL_BW"=>sqm.upload_speed,"QD"=>sqm.queuing_disciplines,"Q_S"=>sqm.queue_setup_script}.to_json
      end
    end
    ntp_configs = NtpServer.all
    unless ntp_configs.blank?
      ntp_configs.each do |ntp|
        redis_set "ntp#{ntp.id}", {"ENABLE"=> ntp.is_enabled? ? 1 : 0, "NTP_LIST" => ntp.urls.split(",")}.to_json
      end
    end

    redis_set "default",{"BASIC_CONFIG"=>{"HB_SERVER_URL"=>APPLICATION[Rails.env]["heartbeat_url"],
                                          "PRESENCE_SERVER_URL"=>APPLICATION[Rails.env]["presence_url"],
                                          "ALERTS_SERVER_URL"=>APPLICATION[Rails.env]["alerts_server_url"],
                                          "HB_INTERVAL"=>10,
                                          "RELAY_SERVER"=>nil,
                                          "GRE_SERVER"=>nil,
                                          "CONSUME_ID"=>"1401291805805"},
                        "SSID_CONFIG"=>[{"SSID_UNIQ_ID"=>0.to_s,
                                        "MODE_ROUTER"=>"0".to_i,
                                        "NAT"=>"0".to_i,
                                        "WNA" => ssid.wna.to_i,
                                        "SSID"=>"PCC Wireless",
                                        "DISABLE"=>0,
                                        "HIDDEN"=>0,
                                        "ISOLATE"=>0,
                                        "PROTO"=>"dhcp",
                                        "VLANID"=>"0",
                                        "IPADDR"=>nil,
                                        "NETMASK"=>nil,
                                        "ACL_MAC"=>{"MAC_FILTER_ENABLE"=>0,
                                                    "MAC_FILTER_POLICY"=>1,
                                                    "ACL_MAC_LIST"=>[].to_json},
                                        "SECURITY"=>{"AUTH_TYPE"=>"none",
                                                    "PASS_PHRASE"=>"",
                                                    "AUTH_SERVER"=>"",
                                                    "AUTH_PORT"=>"",
                                                    "AUTH_SECRET"=>""},
                                        "DHCP"=>{"LEASE_TIME"=>0,
                                                "DHCP_ENABLE"=>1,
                                                "RANGE_START"=>"",
                                                "RANGE_END"=>"",
                                                "GATEWAY"=>"",
                                                "MAPPINGS" => []},
                                        "CAPTIVE_PORTAL"=>{"PORTAL_ENABLE"=>0,
                                                          "PORTAL_REDIR_URL"=>"",
                                                          "WL_ENABLE"=>0,
                                                          "WL_CONFIG"=>[].to_json,
                                                          "QOS" => {"BW_ENABLE" => 0, "BW"=> "0"},
                                                          "DEF_INT_UPDATE_INTV" => self.default_interim_time,"DEF_IDLE_TO" => self.default_idle_timeout},
                                                          "BAND" => "1",
                                                          "MAX_ASSOC" => 0}],
                        "SNMP_CONFIG"=>{},
                        "RADIO_CONFIG"=>{"CHANNEL"=>"6","TXPOWER"=>"20"},
                        "VLAN_CONFIG"=>[],
                        "LAN_CONFIG"=>{"PROTO"=>"dhcp",
                                      "IPADDR"=>nil,
                                      "NETMASK"=>nil,
                                      "GATEWAY"=>nil,
                                      "PRI_DNS"=>nil,
                                      "SEC_DNS"=>nil,
                                      "GRE"=>nil,
                                      "DHCP_RELAY"=>nil},
                        "UPLINK_CONFIG"=>[{"TYPE" => "1",
                                      "PROTO"=>"dhcp",
                                      "IPADDR"=>nil,
                                      "NETMASK"=>nil,
                                      "GATEWAY"=>nil,
                                      "PRI_DNS"=>nil,
                                      "SEC_DNS"=>nil,
                                      "GRE"=>nil,
                                      "UID" => "0",
                                      "DHCP_RELAY"=>nil}],
                        "PORT_FWD_CONFIG"=>nil,
                        "ACL_CONFIG"=>nil,
                        "COMMANDS"=>[].to_json,
                        "NETWORK_ID"=>"",
                        "NTP_CONFIG" => {},
                        "RADIO_PROFILES" => [RadioProfile.default_radio],
                        "PRESENCE_CONFIG" => {"ENABLE" => "0", "TAG" => "default"},
                        "WIRED_CONFIG" => {}}.to_json
  end

  def self.get_all_based_on_tag(id)
    RouterInventory.tagged_with(id)
  end
  
  def update_router_config
    r = redis_get(self.mac_id)
    unless r.blank?
      t = JSON.parse(r)
      t["BASIC_CONFIG"]["CONSUME_ID"] = Time.now.to_i.to_s
      redis_set self.mac_id, t.to_json
    end
  end  

  def self.find_up_list router_inventories, threshold = nil
    threshold = APPLICATION['defaults']['on_or_off'] if threshold.nil?
    swmac = ["D0:77:CE:3E:7B:44", "D0:77:CE:BD:63:F8", "D0:77:CE:BD:63:D8", "D0:77:CE:BD:64:F8", "90:2D:77:70:11:86", "D0:77:CE:BD:63:08", "D0:77:CE:BD:64:08", "D0:77:CE:BD:65:78", "D0:77:CE:BD:63:C8", "D0:77:CE:BD:63:88", "D0:77:CE:BD:62:98", "D0:77:CE:BD:63:78", "D0:77:CE:BD:62:68", "D0:77:CE:BD:64:E8", "D0:77:CE:BD:64:58", "D0:77:CE:BD:62:C8", "D0:77:CE:BD:64:98", "D0:77:CE:BD:65:58", "D0:77:CE:BD:63:E8", "D0:77:CE:BD:65:48", "D0:77:CE:BD:63:68", "00:0C:66:12:12:34", "E4:9D:73:21:DD:D1", "E0:01:A6:BA:08:D0", "E4:9D:73:21:EA:A1"]
    threshold_time = Time.zone.now - threshold.to_i.seconds
    # aps_up = MonitoringDataCapped.collection.aggregate( {'$match' => {'info.NASID' => {'$in' => router_inventories},
                                                                      # 'created_at' => {'$gte' => threshold_time}}},
                                                        # {'$group' => {'_id' => '$info.NASID',
                                                                      # 'recent_date' => {'$max' => '$created_at'}}} )

     aps_up=router_inventories.select {|ri| hb=$redis.hget("AP:#{ri}", "last_hb"); hb && hb.to_i >= (swmac.include?(ri) ? (Time.zone.now - 12.minutes.to_i.seconds).to_i : threshold_time.to_i)}#router_inventories.select {|ri| hb = $redis.hget("AP:#{ri.mac_id}", "last_hb"); hb;}
     #aps_up=router_inventories.select {|ri| hb=$redis.hget("AP:#{ri}", "last_hb"); hb && hb.to_i >= (swmac.include?(ri) ? (Time.zone.now - 12.minutes.to_i.seconds) : threshold_time.to_i)}#router_inventories.select {|ri| hb = $redis.hget("AP:#{ri.mac_id}", "last_hb"); hb;}
     # aps_up.map {|ap| ap["_id"]}

  end

  def get_public_ip
    ip = $redis.hget "AP:#{self.mac_id}", "pub_ip"
    #TODO: We made this false because of performance issue on monitoring dashboard.
    if false#ip.blank?
      monitoring = MonitoringDataCapped.where("info.NASID" => self.mac_id).order_by(["created_at", :desc]).first
      ip = monitoring.s_info["PUBLIC_IP"] rescue nil
    end

    ip
  end

  def self.find_up_clients router_inventories, threshold = nil
    threshold = APPLICATION['defaults']['on_or_off'] if threshold.nil?
    threshold_time = Time.zone.now - threshold.seconds
    clients_up = MonitoringDataCapped.collection.aggregate( {'$match' => {'info.NASID' => {'$in' => router_inventories},
                                                                     'created_at' => {'$gte' => threshold_time}}},
                                                       {"$project" => {"mac" => '$info.NASID',
                                                                       "clients.MAC" => 1,
                                                                       "clients.BAND" => 1,
                                                                       "clients.BD" => 1,
                                                                       "present_date" => '$created_at'}},
                                                       {"$group" => {'_id' => "$mac", "clients" => {"$last" => "$clients"}}},
                                                       {'$unwind' => '$clients'},
                                                       {'$group' => {'_id' => {'ap' => '$_id', 'band' => {"$ifNull" => ["$clients.BAND", "$clients.BD"] }},                                                                              'clients_list' => {'$addToSet' => "$clients.MAC"}}},
                                                       {'$project' => {'count' => {'$size' => '$clients_list'}}})

    #NOTE:1 = 2.4GHz; 2 = 5GHz
    clients_up.inject({}) {|h, e|
      if h[e['_id']['ap']]
        h[e['_id']['ap']][e['_id']['band']] = e['count']
      else
        h[e["_id"]['ap']] = {e['_id']['band'] => e["count"]}
      end
      h
    }
  end

  def find_last_hb
    hs = {"hb" => 0, "version" => '-'}
    redis_data = $redis.hgetall "AP:#{self.mac_id}"
    if redis_data.blank?
      #TODO Find out Alternate way to get last hb
      mc = nil#MonitoringChild.where("info.NASID" => self.mac_id).order({"created_at" => -1}).first
      unless mc.blank?
        hs["hb"] = mc["created_at"].to_i
        hs["version"] = mc["info"]["PIAP_VERSION"]
      end
    else
      hs["hb"] = redis_data["last_hb"] || 0
      hs["version"] = redis_data['version'] || '-'
    end

    hs
  end

  def past_history(query)
    tz = self.location_network.try(:timezone) || 'UTC'
    zet = Time.now.in_time_zone(tz).beginning_of_hour
    et = zet.utc
    offset = zet.utc_offset * 1000
    case query
    when "24h"
      st = et - 24.hours
      #fs = "%d-%m-%Y %H:00"
      fs = {"h" => {"$hour" => "$ts"}}
    when "2d"
      st = et - 2.days
      #fs = "%d-%m-%Y %H:00"
      fs = {"h" => {"$hour" => "$ts"}, "d" => {"$dayOfMonth" => "$ts"}}
    when "7d"
      st = et - 7.days
      #fs = "%d-%m-%Y %H:00"
      fs = {"h" => {"$hour" => "$ts"}, "d" => {"$dayOfMonth" => "$ts"}}
    when "30d"
      st = et - 30.days
      #fs = "%d-%m-%Y %H:00"
      fs = {"h" => {"$hour" => "$ts"}, "d" => {"$dayOfMonth" => "$ts"}}
    when "week"
      st = et - 1.week
      #fs = "%d-%m-%Y"
      fs = {"h" => {"$hour" => "$ts"}, "d" => {"$dayOfMonth" => "$ts"}}
    when "month"
      st = et - 1.month
      #fs = "%d-%m-%Y"
      fs = {"d" => {"$dayOfMonth" => "$ts"}}
    when "year"
      st = et - 1.year
      #fs = "%m-%Y"
      fs = {"m" => {"$month" => "$ts"}}
    else
      st = et - 12.hours
      fs = {"h" => {"$hour" => "$ts"}}
    end

    result = {}

    #result = MonitoringChild.collection.aggregate( {'$match' => {'info.NASID' => mac_id, 'created_at' => {'$gte' => st.to_i, '$lt' => et.to_i}}}, {"$project" => {"VOC" => '$monitoring_data.SENSORS_DATA.AIR_DATA.VOC', "ts" => {'$add' => ['$created_at', offset]}}}, {'$group' => {'_id' => fs, 'avg' => {'$avg' => "$VOC"}, 'min' => {'$min' => "$VOC"}, 'max' => {'$max' => "$VOC"}, 't' => {'$first' => '$ts'}}}, {"$sort" => {'t' => 1}}, {"$group" => {'_id' => nil, 'min_ts' => {'$first' => '$t'}, 'max_ts' => {'$last' => '$t'}, 'avg' => {'$push' => '$avg'}, 'min' => {'$push' => '$min'}, 'max' => {'$push' => '$max'}}} ).first
    result = MonitoringChild.collection.aggregate( {'$match' => {'info.NASID' => mac_id, 'created_at' => {'$gte' => st, '$lt' => et}}}, {"$project" => {"VOC" => '$sensor_data.AIR_DATA.VOC', "ts" => {'$add' => ['$created_at', offset]}}}, {'$group' => {'_id' => fs, 'avg' => {'$avg' => "$VOC"}, 'min' => {'$min' => "$VOC"}, 'max' => {'$max' => "$VOC"}, 't' => {'$first' => '$ts'}}}, {"$sort" => {'t' => 1}} )
=begin    unless result.blank?
      result['min_ts'] = ActiveSupport::TimeZone.new('Kolkata').parse(result['min_ts'].strftime("%Y-%m-%d %H:%M")).beginning_of_hour.to_i * 1000
      result['max_ts'] = ActiveSupport::TimeZone.new('Kolkata').parse(result['max_ts'].strftime("%Y-%m-%d %H:%M")).beginning_of_hour.to_i * 1000
    end
=end
    result = result.inject({})  do |h, res|
                h.merge!({ActiveSupport::TimeZone.new(tz).parse(res["t"].strftime("%Y-%m-%d %H:%M")).beginning_of_hour.to_i => {avg: res['avg'].round, min: res['min'], max: res['max']}})
             end
    result.merge!({st: st.to_i, et: et.to_i})

    result
  end

  def set_hw_part_no part_number
    hw_part_no = part_number.gsub('"', '')
    hw_part = HardwarePart.where part_number: hw_part_no
    #hw_part = HardwarePart.where name: hw_part_no unless hw_part.present?
    if hw_part.present?
      $redis.hset "AP:#{self.mac_id}", "hw_part_no", hw_part.first.part_number
      self.update_column :hardware_part_id, hw_part.first.id
    end
  end

  def formatted_address
    inv = self
    country = ISO3166::Country[inv.country] unless inv.country.present?
    address = ""
    address << inv.address unless inv.address.blank?
    address << ", #{inv.address2}" unless inv.address2.blank?
    address << ", #{inv.city}" unless inv.city.blank?
    address << ", #{country.states[inv.state]['name']}" unless country.blank? || inv.state.blank?
    address << " - #{inv.zipcode}" unless inv.zipcode.blank?
    address << ", #{country.name}" unless country.blank? || inv.country.blank?

    address
  end

  def total_down_time criteria, down_time_list
    ap_details = $redis.hgetall "AP:#{self.mac_id}"
    hb_freq = ap_details['hb_freq'] || 5
    downtime_secs = 0
    if ap_details['last_hb'].present?
      ap_details['last_hb'] = Time.zone.at(ap_details['last_hb'].to_i)
      st = criteria[:st]
      et = criteria[:et]
      downtime_details = {}
      interval = RouterInventory.get_hb_intreval(hb_freq)
      if ap_details['last_hb'].to_i > st.to_i && ap_details['last_hb'].to_i <= et.to_i && (et.to_i - ap_details['last_hb'].to_i) >  interval
        downtime_secs += et.to_i - ap_details['last_hb'].to_i
        downtime_details['st'] = st
        downtime_details['et'] = et
        downtime_details['est'] = ap_details['last_hb']
        downtime_details['eet'] = et
        downtime_details['down_secs'] = downtime_secs
      elsif ap_details['last_hb'].to_i < st.to_i
        downtime_secs += et.to_i - st.to_i
        downtime_details['st'] = st
        downtime_details['et'] = et
        downtime_details['est'] = st
        downtime_details['eet'] = et
        downtime_details['down_secs'] = downtime_secs
        downtime_details['entire_period'] = 1
      end
      down_time_list << downtime_details unless downtime_details.blank?
    end
    return down_time_list
  end

  def set_ap_profile(ri)
    $redis.hset "AP:#{ri.mac_id}", "AP", ri.name.to_s
    $redis.hset "AP:#{ri.mac_id}", "ID", ri.id
    $redis.hset "AP:#{ri.mac_id}", "Tags", ri.tags.map(&:name).join(',') unless ri.tags.blank?
    $redis.hset "AP:#{ri.mac_id}", "HW", ri.hardware_part.try(:name).to_s
    $redis.hset "AP:#{ri.mac_id}", "hw_type", ri.hardware_part.try(:hardware_category).try(:name).to_s
    $redis.hset "AP:#{ri.mac_id}", "vendor_type", ri.vendor_type
    $redis.hset "AP:#{ri.mac_id}", "org_id", ri.organisation_id
    ln = ri.location_network
    $redis.hset "AP:#{ri.mac_id}", "Network", ln.try(:network_name).to_s
    $redis.hset "AP:#{ri.mac_id}", "ln_id", ln.try(:id).to_s
    $redis.hset "AP:#{ri.mac_id}", "hb_freq", ln.try(:hb_freq).to_s
    is_presence_enabled = ri.get_presence.to_s
    $redis.hset "AP:#{ri.mac_id}", "presence", is_presence_enabled
    $redis.hset "AP:#{ri.mac_id}", "presence_url", ri.get_presence_url.to_s
    $redis.hset "AP:#{ri.mac_id}", "telemetry_format", "lbs" if is_presence_enabled == '1' && ln.id == 593 #NOTE: we need to remove this
    $redis.hset "AP:#{ri.mac_id}", "lbs_url", "https://uslive.wavespot.net/data" if is_presence_enabled == '1'
    $redis.hset "AP:#{self.mac_id}", "wired_uid", ri.uplinks.where(uplink_type: "1").first.try(:id).to_s
    unless ln.blank?
      ssids = self.get_all_associated_ssids ln
      $redis.hset "AP:#{self.mac_id}", "ssids", ssids.inject({}) {|h, s| h[s.ssid_name] = s.id;h}.to_json
      event_logging = Logging.where(:location_network_id => ln.id,logging_type: 'event_logging').first
      $redis.hset "AP:#{self.mac_id}", "EVENT_LOG", event_logging.is_enabled.to_s if event_logging.present?
    end
  end

  def set_firewall_old_rules(src_id, dst_id, wired_config, ssids)
    hash = {}
    s_id =''
    d_id = ''
    wired_config = WiredConfig.where(:id => wired_config).first
    count = ([src_id.to_i, dst_id.to_i] - ssids).count
    if (src_id == '0' && dst_id == '0') ||  count == 0
      s_id = src_id
      d_id = dst_id
    elsif (src_id == '-1' || dst_id == '-1') && wired_config.present? && (src_id == '0' || dst_id == '0')
       s_id = src_id == '-1' ? wired_config.uniq_identifier : src_id
       d_id = dst_id == '-1' ? wired_config.uniq_identifier : dst_id
    elsif (src_id == '0' || dst_id == '0') && count > 0
        s_id = src_id == '0' ? src_id : (ssids.include?(src_id.to_i) ? src_id : '')
        d_id = dst_id == '0' ? dst_id : (ssids.include?(dst_id.to_i) ? dst_id : '')
    elsif (src_id == '-1' || dst_id == '-1') && wired_config.present? && count > 0
        s_id = src_id == '-1' ? wired_config.uniq_identifier : (ssids.include?(src_id.to_i) ? src_id : '')
        d_id = dst_id == '-1' ? wired_config.uniq_identifier : (ssids.include?(dst_id.to_i) ? dst_id : '')
    end
    return [s_id,d_id]
  end

  def set_firewall_rules(src_id, dst_id, wired_config, ssids)
    hash = {}
    s_id =''
    d_id = ''
    #wired_config = WiredConfig.where(:id => wired_config).first
    #v_lan = VLan.where(:id => wired_config).first
    count = ([src_id.to_i, dst_id.to_i] - ssids).count
    if (src_id == '0' && dst_id == '0') ||  count == 0
      s_id = src_id
      d_id = dst_id
    elsif (src_id.match(/^VL/).present? || dst_id.match(/^VL/).present?) && (src_id == '0' || dst_id == '0')
      s_id = src_id#.match(/^VL/).present? ? wired_config.uniq_identifier : src_id
      d_id = dst_id#.match(/^VL/).present? ? wired_config.uniq_identifier : dst_id
    elsif (src_id == '0' || dst_id == '0') && count > 0
      s_id = src_id == '0' ? src_id : (ssids.include?(src_id.to_i) ? src_id : '')
      d_id = dst_id == '0' ? dst_id : (ssids.include?(dst_id.to_i) ? dst_id : '')
    elsif (src_id.match(/^VL/).present? || dst_id.match(/^VL/).present?) && count > 0
      s_id = src_id.match(/^VL/).present? ? src_id : (ssids.include?(src_id.to_i) ? src_id : '')
      d_id = dst_id.match(/^VL/).present? ? dst_id : (ssids.include?(dst_id.to_i) ? dst_id : '')
    end
    return [s_id,d_id]
  end

  def device_wired_config(ln)
    wired_config = self.associated_wired_config.try(:id)
    wired_config = ln.associated_wired_config.try(:id) unless wired_config.present?
    return wired_config
  end

  def get_associated_network_ssids
    ssids = Set.new
    ssids += self.associated_network_ssids
    ri_tags = self.tags.pluck(:id)
    ln = self.location_network
    return {} if ln.blank?
    ssids += ln.network_ssids.joins(:config_mappings).where("resourceable_type = 'ActsAsTaggableOn::Tag' AND resourceable_id IN (?)", ri_tags) unless ri_tags.blank?
    ssids += ln.network_ssids.joins(:config_mappings).where("resourceable_type = 'LocationNetwork' AND resourceable_id = ?", ln.id) unless ln.network_ssids.blank?
    ssids += ln.network_ssids.joins(:config_mappings).where("resourceable_type = 'HardwareCategory' AND resourceable_id = ?", self.hardware_part.hardware_category.id) unless self.hardware_part_id.blank?
    return ssids
  end

  def self.get_hb_intreval(hb_freq)
    interval = hb_freq.to_i.seconds > 2.minutes ? hb_freq.to_i.seconds * 2 : 4.minutes
    return interval
  end


  def self.search(search)
    if search
      self.where(name: search)
      @ris = self.includes(:location_network, :organisation => [:users]).where("mac_id LIKE ? OR users.email LIKE ? OR organisations.organisation_name LIKE ? OR network_name LIKE ?", "%#{search}%", "%#{search}%", "%#{search}%","%#{search}%").references(:organisation)
    else
      self.all.desc(:created_at)
    end

  end

  def get_bands
    radio_profiles = self.associated_radio_profile
    if radio_profiles.present?
       return radio_profiles
    else    
      location_network_rp = self.location_network.try(:associated_radio_profile) 
      if location_network_rp.present?
          return location_network_rp
      end 
    end     
  end  

  def self.non_provisioning_api
    non_provision_aps = $redis.keys "NP:AP*"
    non_provision_aps = non_provision_aps - RouterInventory.all.pluck(:mac_id).map{|r_i| "NP:AP:#{r_i}"}
    val = non_provision_aps.map { |nap| JSON.parse($redis.get(nap)) }
  end
# Post.joins(:tags).where("posts.caption LIKE :search OR tags.name LIKE :search", search: "%#{search}%" )

  def get_all_associated_ssids ln=nil
    ssids = Set.new
    ssids += self.associated_network_ssids
    ln = self.location_network unless ln.present?
    p ln
    unless ln.nil?
      ri_tags = self.tags.pluck(:id)
      ssids += ln.network_ssids.joins(:config_mappings).where("resourceable_type = 'ActsAsTaggableOn::Tag' AND resourceable_id IN (?)", ri_tags) unless ri_tags.blank?
      ssids += ln.network_ssids.joins(:config_mappings).where("resourceable_type = 'LocationNetwork' AND resourceable_id = ?", ln.id)
      ssids += ln.network_ssids.joins(:config_mappings).where("resourceable_type = 'HardwareCategory' AND resourceable_id = ?", self.hardware_part.hardware_category.id) unless self.hardware_part_id.blank?
    end

    ssids
  end

  def get_all_associated_wired_config
    #Redis for Wired Config
    wired_config = self.associated_wired_config
    unless wired_config.present?
      ln = self.location_network
      wired_config = ln.try(:associated_wired_config)
    end

    wired_config
  end

  def get_associated_radio_profile ln=nil
    ln = self.location_network unless ln.present?

    radio_profile = self.associated_radio_profile
    radio_profile = ln.associated_radio_profile if radio_profile.blank? && ln.present?

    radio_profile
  end

  def get_associated_switch_configuration ln=nil
    ln = self.location_network unless ln.present?

    switch_config = self.associated_switch_configuration
    switch_config = ln.associated_switch_configurations.filter_by_hw_part(self.hardware_part_id).last if switch_config.blank? && ln.present?

    switch_config
  end

  def check_multivendor_tag(tags)
      Meraki::Platform::ConfigurationService.new(nil, self.organisation).update_device_attributes(self.router_serial_number,self.tag_list,"tag") if self.vendor_type == "3"
  end


  def remove_meraki_device_from_network
   begin
    Meraki::Platform::ConfigurationService.new(self.location_network).remove_network_device(self.router_serial_number)
   rescue
   end
  end

  def claim_device_in_network(serials)
     Meraki::Platform::ConfigurationService.new(self.location_network).claim_network_device serials  if self.vendor_type == "3"
     Ruckus::ConfigurationService.new(self.location_network).move_network_device self if self.vendor_type == "5"
  end

  def enable_telemetry
    timespan = self.get_presence ? 15552000 : 10
    Rails.logger.info "[OPENWIFI-#{self.mac_id}] Calling Telemetry API"
    OpenWifi::ProvisioningService.new(self.location_network, self.organisation, self).enable_telemetry_config(self, timespan)
  end

  def get_ports_last_status from_time
    last_rec = MonitoringChild.where("info.NASID" => self.mac_id, :created_at.gt => from_time).sort(:created_at => 1).last
    
    last_rec.try(:sw_prt) || []
  end
  
  def switch?
    return false if self.hardware_part_id.blank?
    return self.hardware_part && self.hardware_part.switch? 
  end

  def force_config int_type=nil
    flag = $redis.hget "AP:#{self.mac_id}", "force_config"
    flag
  end

end
