class InventoryController < ApplicationController
  include ChangeNetwork

  skip_before_action :verify_authenticity_token, only: :update, if: Proc.new {|c| c.request.format.json?}
  before_action :authenticate_user!, except: :ap_details
  before_action :dashboard_topbar, except: :ap_details
  before_action :router_inventories_parms, only: [:update]
  before_action :set_router_inventory_group, only: [:eathernet_traffic,:update,:show,:edit,:show_enable_disable, :get_ssids, :reboot]
  load_and_authorize_resource :class => RouterInventory ,:except => [:showing_tag, :create_update_vpn, :ap_details]
  skip_load_and_authorize_resource :only => [:eathernet_traffic, :showing_tag, :show_enable_disable]
  skip_load_resource :only => [:create,:vpn_config,:enable_disable_vpn,:change_network, :uptime_slots]

  def index
    permitted_networks = current_user.is_admin? || current_user.is_super_admin ? current_user.organisation : current_user
    @routers = permitted_networks.router_inventories.includes(:location_network).order("router_inventories.created_at desc")
    #@routers = current_user.router_inventories_full.includes(:location_network).order("router_inventories.created_at desc")
    @full_access_network = current_user.networks_with_full_access
    @hw_parts = HardwarePart.where(vendor_type: 4)
    @ssidds = [["NO","no"],["SSID","ssid"]]
    @inventory = RouterInventory.new
    @exisitng_router = params[:exisitng_router].split(",") unless params[:exisitng_router].blank?
    # @inventory_up_list = RouterInventory.find_up_list(@routers.pluck(:mac_id), RouterInventory.get_hb_intreval(@current_network.try(:hb_freq)))
    @hardware_parts = HardwarePart.all.inject({}) {|h, v| h[v.id] = v.name; h }
    @init_templates = current_user.init_templates + InitTemplate.where(is_default: true)
  end

  def edit
    render :partial=>"form"
  end

  def update
    already_uplink_module_exists = false
    previous_uplink_module = 0
    (params[:router_inventories][:uplinks_attributes]||[]).each do |a| 
      if a.last.present? && a.last[:uplink_type] == "4"
        @inventory.uplinks.each do |uplink| 
          if (uplink.uplink_type == "4" && a.last[:uplink_module] == uplink.uplink_module && a.last[:id] != uplink.id.to_s)
            already_uplink_module_exists = true
          end
        end
        already_uplink_module_exists = true if previous_uplink_module == a.last[:uplink_module]
        previous_uplink_module = a.last[:uplink_module] if a.last[:uplink_module].present?
      end
    end
    status = 200
    data = {}
    if already_uplink_module_exists == false
      if @inventory.update(router_inventories_parms)
        data = {id: @inventory.id, name: @inventory.name}
        msg = "Successfully updated Device"
        flash[:success] = msg
      else
        status = 422
        msg = @inventory.errors.full_messages.blank? ? "Oops! there was some problem in updating Device" : @inventory.errors.full_messages
        flash[:error] = msg
        Rails.logger.warn "#{@inventory.errors.full_messages}"
      end
    else
      status = 422
      msg = "Error in updating uplink module"
      flash[:error] = msg
    end
    @inventory.tag_list.add(params["router_inventories"]["tag_list"], parse: true)
    if request.format.json?
      render json: {status: status, data: data, message: msg}
    else
      redirect_to inventory_path(@inventory)
    end
  end

  def client_details
    org_id = current_user.organisation.id
    values = ClientDevice.get_all org_id
    hsh = {}
    values.each {|i| hsh[i[:mac]] = {:name => i[:nick_name], :original_name=> i[:original_name], :mac => i[:mac]}}
    hsh
  end  

  def show
    @vlan = @inventory.location_network.v_lans.present? ? Hash[@inventory.location_network.v_lans.map {|s| ["VL#{s.id}", s.v_lan_id]}].to_json : "{}" unless @inventory.location_network.blank?
    @status = @inventory.is_up?
    @uplink_module_types = [["SIM 1","1"],["SIM 2","2"]]
    @hw = HardwarePart.where(:id => @inventory.hardware_part_id).first  if !(@inventory.hardware_part_id).nil?
    @port_count = @hw.port_count if !@hw.nil?
    wired_count = Uplink.where("router_inventory_id" => @inventory.id,"uplink_type" => "1").count
    @wans = wired_count# / 2
    @default_radio = RouterInventory.default_radio
    @last_hb = @inventory.find_last_hb
    wds_cond = ''
    wds_cond = 'AND wds_enabled is TRUE' if @inventory.uplink_type == '2'
    @ssids = @inventory.location_network.network_ssids.where("security_mode IN (?) " + wds_cond,['none', 'psk2']).map{|v| {"id"=>v.id, "text"=> "#{v.ssid_name} (#{v.radio_band} GHz)"}} rescue []
    @ssids.push({"id"=>@inventory.wl_ssid_name, "text"=>@inventory.wl_ssid_name}) if @inventory.wl_ssid_uniqe_id == 0
    @enabled_ssids = enabled_disabled(@inventory,"enabled").length rescue 0
    @disabled_ssids = enabled_disabled(@inventory,"disabled").length rescue 0
    @states = []
    @client_details = (client_details.present? ? client_details.to_json : "{}")
    @states = ISO3166::Country.new(@inventory.country).states.map {|s| [s[1]["name"], s[0]]} unless @inventory.country.blank?
    @uplink_types = RouterInventory::UPLINK_TYPE.deep_dup
    @operator_names = [["AT&T LTE","AT&T LTE"],["SPRINT LTE","SPRINT LTE"],["T-MOBILE LTE","T-MOBILE LTE"],["VERIZON LTE","VERIZON LTE"],["OTHERS","OTHERS"]]
    unless @inventory.hardware_part.blank?
      if ["5","6","34"].include?(@inventory.hardware_part.try(:part_number))
        @uplink_types.delete_if {|u| u == "2"}
      elsif !@inventory.hardware_part.wifi_uplink?
        @uplink_types.delete_if {|u| u == "2" || u == "3"}
      end
      @uplink_types.delete("4") unless @inventory.hardware_part.usb?
    end
    @network_radio_profile = @current_network.try(:associated_radio_profile)

    if @hw.present? && @hw.switch?
      @switch_configuration = @inventory.get_associated_switch_configuration
      @ports_configured = []
      @ports_configured = @switch_configuration.switch_port_configurations unless @switch_configuration.blank?
      @port_configurations = @ports_configured.map {|d| [d.port_number, d]}.inject({}) {|h,d| h[d[0]] = d[1];h}

      render :show_switch
    end
  end

  def eathernet_traffic
    render :json=>Monitoring.get_last_details(@inventory.mac_id)
  end

  def showing_tag
    @ris = RouterInventory.get_all_based_on_tag(params[:id])
  end

  def network_show
    @location_network = LocationNetwork.find(params[:id])
  end

  def enabled_disabled(obj,type)
    ssids = obj.get_associated_network_ssids
    condition = "disabled".eql?(type) ? false : true
    ssid_arr = ssids.map{|a| [a.ssid_name,a.radio_bands,a.ssid_mode,a.is_enabled] if a.is_enabled == condition}.compact
    return ssid_arr
  end

  def create
    params[:router_inventories] = params[:inventory] unless params[:router_inventories].present?
    vendor_type = params[:router_inventories][:vendor_type] || "1"
    hw_part = (vendor_type == "4" && params[:router_inventories]["hardware_part_id"].present?) ? params[:router_inventories]["hardware_part_id"].to_i : nil
    hw_part = HardwarePart.switch_hardware_parts.try(:last).try(:id) if vendor_type == "6"
    inventory = ((vendor_type == "3"  || vendor_type == "2") ? (params[:router_inventories][:serial]) : (params[:router_inventories][:mac_id]) )
    serial = nil#params[:router_inventories][:serial]
    meraki_non_succ = nil
    ln = current_user.organisation.location_networks.where(:network_name => params["network_name"]).first
    loc_vendor_id = ln.try(:vendor_network_id)
    serials = inventory.split(",").map(&:strip)
    if vendor_type == "5"
      if loc_vendor_id.present?
        ruckus_zones = Ruckus::ConfigurationService.new(ln).get_zone_devices
        ruckus_inventory = ((ruckus_zones || {})['list'] || []).select{|mer| serials.include?(mer["mac"]) }
        if ruckus_inventory.present?
          Ruckus::ConfigurationService.new(ln).move_multiple_aps ruckus_inventory.map {|mer| mer["mac"]}
        else
          val = Ruckus::ConfigurationService.new(ln).claim_zone_device serials
        end
        ruckus_zones = Ruckus::ConfigurationService.new(ln).get_zone_devices loc_vendor_id
      else
        #TODO: claim device into the organisation
        #TODO: get all devices
      end
      ruckus_inventory = ((ruckus_zones || {})['list'] || []).select{|mer| serials.include?(mer["mac"]) }
      ruckus_non_succ = serials - ruckus_inventory.map {|mer| mer["mac"]}
      if ruckus_non_succ.present?
        flash[:notice] = "Following mac_ids <b> #{ruckus_non_succ.map{|i| i.to_s}}</b> are invalid or already provisioned. Please check your macids"
      end  
    end
    if vendor_type == "3"
      org_id = current_user.organisation.id
      arr = []
      if loc_vendor_id.present?
        val = Meraki::Platform::ConfigurationService.new(ln).claim_network_device serials
        meraki_networks = Meraki::Platform::ConfigurationService.new(ln).get_network_devices
      else
        val = Meraki::Platform::ConfigurationService.claim_device_into_organization current_user.organisation, serials
        meraki_networks = Meraki::Platform::ConfigurationService.get_all_devices current_user.organisation, serials
      end      
      # serials.each do |ser|
      #   # arr = RouterInventory.claim_meraki org_id, loc_vendor_id, serial
      #   hsh = {}
      #   # hsh["networkId"] = nw_id
      #   hsh["serial"] = ser
      #   if loc_vendor_id.present?
      #     val =  MerakiApiWrapper::Meraki.new.claim_device org_id, loc_vendor_id, hsh        
      #   else
      #     val =  MerakiApiWrapper::Meraki.new.claim_device_org org_id, hsh 
      #   end
      #   arr << val
      # end
      # non_succ, succ = arr.partition{|i| i[1][:msg] == "err"}
      # arr = arr.reject {|i|  i[1] == "err" }
      # inventory = succ.map {|i| i[0]["serial"]}
      # meraki_non_succ = non_succ.map {|i| p i[1][:data]}
      meraki_inventory = meraki_networks.select{|mer| serials.include?(mer["serial"]) }
      meraki_non_succ = serials - meraki_inventory.map {|mer| mer["serial"]}
      if meraki_non_succ.present?
        flash[:notice] = "Following mac_ids <b> #{meraki_non_succ.map{|i| i.to_s}}</b> are invalid or already provisioned. Please check your macids"
      end
    # elsif vendor_type == "2"
    #   serials = inventory.split(",").map(&:strip)
    #   org_id = current_user.organisation.id
    #   loc_vendor_id = ln.try(:vendor_network_id)   
    #   arr = []
    #   serials.each do |ser|
    #     if loc_vendor_id.present?
    #       hsh = { :group => loc_vendor_id, :serials => [ser] }
    #       val =  ArubaApiWrapper::Aruba.new(org_id).move_device hsh        
    #     else
    #       hsh = { :group => "default", :serials => [ser] }
    #       val =  ArubaApiWrapper::Aruba.new(org_id).move_device hsh
    #     end
    #     arr << val
    #   end  
    #   non_succ, succ = arr.partition{|i| i[1][:msg] == "err"}
    #   arr = arr.reject {|i|  i[1] == "err" }
    #   inventory = succ.map {|i| i[0][:serials]}
    #   inventory = inventory.flatten
    #   aruba_non_succ = non_succ.map {|i| p i[1][:data]}
    #   aruba_aps = ArubaApiWrapper::Aruba.new(org_id).get_all_aps["aps"]
    #   aruba_inventory = aruba_aps.select{|aru| inventory.include?(aru["serial"]) }
    #   if aruba_non_succ.present?
    #     flash[:notice] = "Following mac_ids <b> #{aruba_non_succ.map{|i| i.to_s}}</b> of devices were not been added"
    #   end             
    end

    is_auto_provisioned = params[:router_inventories][:is_auto_provisioned] ? true : false
    unless params[:router_inventories][:inventory_file].blank?
      status,count,tot_count = RouterInventory.import(params[:router_inventories][:inventory_file],current_user,is_auto_provisioned, vendor_type, hw_part)
      org = current_user.organisation
      @limit = org.router_inventories.count.to_i
      msg = "Devices were added Successfully to inventory"
      msg = "Out of #{tot_count} devices #{count} devices were not added to inventory" unless status
      msg = "Out of #{tot_count}  devices #{count} devices were not added  since you have reached the maximum limit of #{@limit} devices to add inventory" if @limit >= org.no_of_aps.to_i
      flash[:success] = msg
    end
    already_exists = []
    unless inventory.blank?
      # inventory = ((vendor_type == "3" || vendor_type == "2" ) ? inventory : inventory.split(",").map(&:strip))
      inventory = ((vendor_type == "3") ? inventory : inventory.split(",").map(&:strip))
      if vendor_type == "3"
        meraki_inventory.each do |router|
          mac = router["mac"].upcase
          mac, status = RouterInventory.meraki_routers_activation([mac,ln.try(:id),ln.try(:organisation_id), vendor_type], router)
          already_exists << mac unless status
        end
      elsif vendor_type == "5"
        ruckus_inventory.each do |router|
          mac = router["mac"].upcase
          mac, status = RouterInventory.ruckus_routers_activation([mac,ln.try(:id),ln.try(:organisation_id), vendor_type], router)
          already_exists << mac unless status
        end
      # elsif vendor_type == "2"
      #   aruba_inventory.each do |router|
      #     mac = router["macaddr"]
      #     mac, status = RouterInventory.aruba_routers_activation([mac,ln.try(:id),ln.try(:organisation_id), vendor_type], router)
      #     already_exists << mac unless status
      #   end          
      else
        inventory.each do |router|
          router = router.try(:upcase).gsub(/(.{2})/,'\1:').slice(0,17) if router.length == 12
          router, status = RouterInventory.router_activation([router,params[:network_name], vendor_type, hw_part],current_user,is_auto_provisioned)
          already_exists << router unless status
        end
      end
      unless already_exists.present?
        flash[:success] = "Successfully created new Devices"
      else
        flash[:notice] = "Following mac_ids <b> #{already_exists.join(",")}</b> are invalid or already provisioned. Please check your macids"
      end
    end
    if request.format.json?
      exisiting_aps = current_user.organisation.router_inventories.where(mac_id: inventory.map(&:upcase))
      render json: {data: {devices: exisiting_aps.map(&:json_build), msg: inventory.count == exisiting_aps.count ? "Successfully added to inventory." : "Following macids #{(inventory.map(&:upcase) - exisiting_aps.map(&:mac_id)).join(", ")} are invalid or already provisioned. Please check your macids"}}, status: 200
    else
      redirect_to :action => :index
    end  end

  def show_enable_disable
    @ssids = enabled_disabled(@inventory,params[:type])
    render :partial=>"inventory_details"
  end

  def clients_upload_download
    @network_id = @current_network.id
  end

  def bulk_update
    @ids = []
    unless params[:router].blank?
      case params[:button]
      when "remove"
        routers = RouterInventory.where(:id => params[:router])
        if params[:bulk_update_type].eql? "remove_from_network"
          no_network = nil
          has_network = nil
          routers.each do |router|
            if router.location_network.blank?
              @ids << router.mac_id
              no_network = true
            else
              router.location_network_id = nil
              @ids << router.mac_id unless router.save
              has_network = true
            end
          end
          if no_network && has_network
            @result = status_message(@ids.count,'no_network_with_some_device')
          elsif no_network
            @result = status_message(@ids.count,'no_network_with_any_device')
          elsif has_network
            @result = status_message(@ids.count,'remove_from_network')
          end
        elsif params[:bulk_update_type].eql? "remove"
          routers.each do |router|
            @ids << router.mac_id unless router.destroy
            #MonitoringChild.where("info.NASID" => router.mac_id).delete
          end
          @result = status_message(@ids.count,'remove')
        end
      when "change_network"
        if "new_network".eql?(params[:network_configuration])
          organisation = current_user.organisation
          new_network_id = "0".eql?(params[:new_network_id]) ? "" : params[:new_network_id]
          network = organisation.location_networks.create({:network_name=>params[:network_name],:network_configuration=>new_network_id.blank? ? "default": "clone",:cloned_network_id=>new_network_id})
          #current_user.unities.create(:location_network_id=>network.id,:role_id=>Role.find_by_name('admin').id)
          @ids = RouterInventory.change_network(params[:router],network,params[:network_ssid_configuration])
          @result = status_message(@ids.count || [],'new_network')
        end
        if "existing_network".eql?(params[:network_configuration])
          @network = LocationNetwork.find_by_id(params[:existing_network_id])
          @ids = RouterInventory.change_network(params[:router],@network,params[:network_ssid_configuration]) unless @network.blank?
          @result = status_message(@ids.count || [],'existing_network')
        end
      when "add_tag"
        unless params[:tag][:add].blank?
          routers = RouterInventory.where(:id => params[:router])
          routers.each do |router|
            prev_tag = router.tag_list.deep_dup
            router.tag_list.add(params[:tag][:add].split(','))
            @ids << router.mac_id unless router.save
            router.check_multivendor_tag(params[:tag][:add].split(','))
            PublicActivity::Activity.create(trackable_id: current_user.id, trackable_type: "RouterInventory", owner_id: current_user.id, owner_type: "User", key: "router_inventory.update", organisation_id: current_user.organisation_id, location_network_id: current_user.location_networks.present? ? current_user.location_networks.first.id : nil, parameters: {:associated_attributes=>[{"tags(#{router.tag_list})"=>{"name"=>[prev_tag, router.tag_list]}}]}, assumed_by: session[:assume_user])
          end
          @result =status_message(@ids.count,'add_tag')
        else
          @result = :error,'Tag name cannot be blank'
        end
      when "remove_tag"
        unless params[:tag][:remove].blank?
          routers = RouterInventory.where(:id => params[:router])
          routers.each do |router|
            router.tag_list.remove(params[:tag][:remove])
            @ids << router.mac_id unless router.save
            router.check_multivendor_tag(params[:tag][:add].split(','))
            PublicActivity::Activity.create(trackable_id: current_user.id, trackable_type: "RouterInventory", owner_id: current_user.id, owner_type: "User", key: "router_inventory.destroy", organisation_id: current_user.organisation_id, location_network_id: current_user.location_networks.present? ? current_user.location_networks.first.id : nil, parameters: {:attributes => {"tags(#{params[:tag][:remove]})" => {}}}, assumed_by: session[:assume_user])
          end
          @result = status_message(@ids.count,'remove_tag')
        else
          @result = :error,'Tag name cannot be blank'
        end
      when "add_init_template"
        if params[:init_template_id].present?
          routers = RouterInventory.where(:id => params[:router])
          routers.each do |router|
            router.uplinks.update_all(is_deleted: true)
            uplink_details = InitTemplate.where(id: params[:init_template_id]).first.details
            uplink_details.each do |uplink_detail| 
              if uplink_detail["uplink_type"] == "1"
                router.uplinks.build(uplink_detail)
              elsif uplink_detail["uplink_type"] == "2" || uplink_detail["uplink_type"] == "3"
                router.uplinks.build(uplink_detail) if router.hardware_part.blank? || router.hardware_part.try(:wifi_uplink) == true
              elsif uplink_detail["uplink_type"] == "4"
                router.uplinks.build(uplink_detail) if router.hardware_part.blank? || router.hardware_part.try(:usb) == true
              end
            end
            @ids << router.mac_id unless router.save
          end
          @result = status_message(@ids.count,'add_init_template')
        else
          @result = :error,'Select Init Template'
        end
      end
      flash[@result[0]] = @result[1]
    end
    redirect_to :action=> :index
  end

  def past_report
    permitted_networks = current_user.is_admin? || current_user.is_super_admin ? current_user.organisation : current_user
    ri = permitted_networks.router_inventories.where(["mac_id = ? OR id = ?", params[:id],params[:id]]).first
    res =[]
    unless ri.blank?
      res = ri.past_history(params[:q])
    end
    render :json => res.to_json
  end

  def save_lat_lng
    permitted_networks = current_user.is_admin? || current_user.is_super_admin ? current_user.organisation : current_user
    ri = permitted_networks.router_inventories.where(["router_inventories.mac_id = ? OR router_inventories.id = ?", params[:id],params[:id]]).first
    unless ri.blank?
      if params[:address].present? || params[:country].present?
        ri.update_attributes(latitude: params[:latitude], longitude: params[:longitude], address: params[:address], address2: params[:address2], city: params[:city], country: params[:country], state: params[:state], zipcode: params[:zipcode]) unless ri.blank?
      else
        ri.update_attributes(latitude: params[:latitude], longitude: params[:longitude])
      end
      states = ISO3166::Country.new(ri.country).states.map {|s| [s[0], s[1]["name"]]} unless ri.country.blank?
    end
    render :json => {message: 'success', states: states || []}
  end

  def get_states
    states = ISO3166::Country.new(params[:country]).states.map {|s| [s[0], s[1]["name"]]} unless params[:country].blank?

    render :json => (states || []).to_json
  end

  def reboot
    if @inventory.vendor_type == "3"
      render :json => {:status => @inventory.reboot_meraki_device}
    elsif @inventory.vendor_type == "4"
      response = OpenWifi::ProvisioningService.new(@inventory.location_network, nil, @inventory).service_command @inventory, "reboot"
      render :json => {:status => response["status"]}
    elsif @inventory.vendor_type == "5"
      response = Ruckus::ConfigurationService.new(@inventory.location_network).reboot_device @inventory.mac_id
      render :json => {:status => response || responce["status"]}
    else
      router = @inventory.id.to_s + '--inventory--' + @inventory.mac_id
      cmd = @inventory.commands.create({:aps => router, :commands => Command::REBOOT, :status => "pending"})
      cmd.set_redis(@inventory) unless cmd.blank?
      render :json => {:status => cmd.present?, message: cmd.present? ? "Reboot is initiated." : "Reboot is not initiated. Please try again."}
    end
  end

  def get_ssids
    if params[:mode].blank?
      wds_cond = ''
      wds_cond = 'AND wds_enabled is TRUE AND ssid_mode="0"' if params[:uplink_type] == '2'
      @ssids = @inventory.location_network.network_ssids.where("security_mode IN (?) " + wds_cond,['none', 'psk2']).map{|v| {"id"=>v.id, "text"=> "#{v.ssid_name} (#{v.radio_band} GHz)"}} rescue []
      @ssids.push({"id"=>@inventory.wl_ssid_name, "text"=>@inventory.wl_ssid_name}) if @inventory.wl_ssid_uniqe_id == 0
      render :json => @ssids.to_json
    elsif params[:mode] == 'router'
      hash = {}
      ssids = @inventory.get_associated_network_ssids
      hash["SSID"] = ssids.map { |a| [a.id,a.ssid_name] if "1".eql?(a.ssid_mode) }
      hash["SSID"] = hash["SSID"].compact
      wired_config = @inventory.associated_wired_config
      wired_config = @inventory.location_network.associated_wired_config if wired_config.blank? && @inventory.location_network.present?
      hash["WIRED"] = [[wired_config.uniq_identifier,wired_config.name]] if wired_config.present?
      hash["VLAN"] = VLan.where(id: wired_config.try(:get_configured_vlans)).map{|vlan| [vlan.uniq_identifier,vlan.v_lan_id]}
      render :json => hash
    elsif params[:mode] == "DHCP"
      hash = {}
      ssids = @inventory.get_associated_network_ssids.select {|d| d.dhcp_relay_server == "2"} 
      hash["SSID"] = ssids.map {|d| d.attributes.slice("id", "ssid_name","ssid_mode","security_mode","ip_address", "subnet_mask", "dhcp_mappings", "dhcp_ranges", "dhcp_options", "dhcp_lease_time")}
      wired_config = @inventory.associated_wired_config
      wired_config = @inventory.location_network.associated_wired_config if wired_config.blank? && @inventory.location_network.present?
      hash["VLAN"] = VLan.where(id: wired_config.try(:get_configured_vlans), dhcp_relay_server: "2").map{|vlan| vlan.attributes.slice("id","v_lan_id","ip_address", "net_mask","dhcp_mappings", "dhcp_ranges", "dhcp_options", "dhcp_lease_time")}

      render :json => hash
    end
  end

  def device_details
    @mac = params[:mac_id]
    if params[:type] == 'string'
      @ap = $redis.hgetall "AP:#{params[:mac_id]}"
      render :json => {:ap => @ap,:mac => @mac}
    else
      mac_datas = {}
      (params[:mac_ids].split(',') || []).each do |mac|
        mac_datas[mac] = $redis.hgetall "AP:#{mac}"
      end
      render :json => {:datas => mac_datas}
    end
  end

  def clone_vpn
    vpn = VpnConfig.where(:id => params["vpn_id"]).first
    new_config = vpn.deep_dup
    new_config.name = new_config.name + " (copy)"
    new_config.is_enabled = "0"
    
    if new_config.save
      flash[:success] = 'VPN Config cloned Successfully'
    else
      flash[:notice] = 'Oops, Problem cloning VPN Config ,Please try after some time'
    end
      redirect_to vpn_config_inventory_index_path
  end

  def vpn_config
    unless @current_network.blank?
      permitted_networks = current_user.is_admin? || current_user.is_super_admin ? current_user.organisation : current_user
      @aps_collection = @current_network.grouped_collection_of_ap
      @routers = @current_network.router_inventories.includes(:location_network).order("router_inventories.created_at desc")
      @inventory_up_list = RouterInventory.find_up_list(@routers.pluck(:mac_id), RouterInventory.get_hb_intreval(@current_network.hb_freq))
       @mac = []
       @routers.each do |ri|
         r = $redis.hgetall "AP:#{ri.mac_id}"
         version = r['version'].present? ? r["version"].split('.').join() : '0'
        if ri.name.present?
          @mac << ["#{(@inventory_up_list.include?(ri.mac_id) ? '<i class=fa fa-arrow-up text-success>' : '<i class=fa fa-arrow-down text-danger>')} </i>".html_safe + "#{ri.name}(#{ri.mac_id.split(':').last(3).join(':')})","AP:#{ri.id}",version,ri.mac_id]
        else
          @mac << [ri.mac_id,"AP:#{ri.id}",version,ri.mac_id]
        end
      end
     if params[:id].blank?
       @vpn = VpnConfig.new
     else
       @vpn = VpnConfig.find_by_id(params[:id])
       @vpn_p1 = @vpn.ike.split('-')
       @vpn_p2 = @vpn.esp.split('-')
     end
   @vpn_list = @current_network.vpn_configs.includes(:config_mappings)
   end
  end

  def create_update_vpn
   
    if params[:vpn].present? && params[:vpn][:id].blank?
      customized_params = vpn_config_params
      customized_params["server_peer"] = vpn_config_params["server_peer"].delete_if { |h| h["public_key"] == "" && h["psk"] == "" && h["ips"]} if customized_params["server_peer"].present?
      @vpn = @current_network.vpn_configs.new(customized_params)
      if @vpn.save(customized_params)
        flash[:success] = 'VPN Config has been created Successfully'
      else
        flash[:notice] = 'Oops, Problem creating VPN Config ,Please try after some time'
      end
    else
      if params[:vpn].blank?
        @vpn = @current_network.vpn_configs.find_by_id(params[:id])
        if @vpn.destroy
          flash[:success] = 'VPN Config has been deleted Successfully'
        else
          flash[:notice] = 'Oops, Problem deleting VPN Config ,Please try after some time'
        end
      elsif params[:vpn].present?
        customized_params = vpn_config_params
        customized_params["server_peer"] = vpn_config_params["server_peer"].delete_if { |h| h["public_key"] == "" && h["psk"] == "" && h["ips"]} if customized_params["server_peer"].present?
        @vpn = @current_network.vpn_configs.find_by_id(params[:vpn][:id])
        if customized_params[:enable_server_client].nil?
          customized_params[:enable_server_client] = false
          customized_params[:enable_gateway] = false
        end
        if customized_params[:enable_gateway].nil?
          customized_params[:enable_gateway] = false
        end
        if customized_params[:enable_nat].nil?
          customized_params[:enable_nat] = false
        end
        if @vpn.update(customized_params)
          flash[:success] = 'VPN Config has been updated Successfully'
        else
          flash[:notice] = 'Oops, Problem updating VPN Config ,Please try after some time'
        end
      end
    end
    redirect_to vpn_config_inventory_index_path
  end

  def enable_disable_vpn
  @vpn = @current_network.vpn_configs.find_by_id(params[:id])
  msg = status = ''
  if @vpn.present?
    state = params[:is_enabled] == 'true' ? '1' : '0'
    @vpn.update_attributes({is_enabled: state})
    msg = "VPN has been #{state == '1' ? 'enabled' : 'disabled'} Successfully."
    status= :success
  else
    msg = 'Requested VPN not found in this network'
    status = :notice
  end
  render :json => {:msg => msg,:status => status}
  end

  def change_network
    change_user_network
  end

  def uptime_slots
    if((params["st"]) && (params["et"]) && (params["mac"])).present?
      st = Time.parse(params["st"])
      et = Time.parse(params["et"])
      mac = params["mac"]
      message = "Available slots" 
      status = 200
      success = true
      data = ApDowntime.where(:mac => mac, :st.lt => et, :et.gte => st).sort({:st => 1})
      slots = []
        data.each do |row|     
          down = {}
            up = {}
          if((row.st <= st) && (row.et >= et))
            down[:sl_st] = st
            down[:sl_et] = et
            down[:status] = "down"
            message = "NO uptime slots"
            slots.push(down)
          elsif((row.st <= st) && (row.et <= et))
            hash = {:sl_st => st, :sl_et => row.et, :status => "down"}
            slots.push(hash)
          elsif((row.st > st) && (row.et <= et))
            if((slots.last).present?)
              up_st = slots.last[:sl_et]
            else
              up_st = st
            end
            slots.push({:sl_st => up_st, :sl_et => row.st, :status => "up"})
            slots.push({:sl_st => row.st, :sl_et => row.et, :status => "down"})
          elsif((row.st > st) && (row.et > et))
            if((slots.last).present?)
              up_st = slots.last[:sl_et]
            else
              up_st = st
            end
            slots.push({:sl_st => up_st, :sl_et => row.st, :status => "up"})
            slots.push({:sl_st => row.st, :sl_et => et, :status => "down"})
          end
        end  
        if slots.last.present? 
          last_slot_et = slots.last[:sl_et]
        else
          last_slot_et = st
        end
        if last_slot_et != et
          hb = $redis.hget("AP:#{mac}", "last_hb")
          if !(hb.nil?)
            last_hb_at = Time.at(hb.to_i)    
            if(last_hb_at >= et)
              slots.push({:sl_st => last_slot_et, :sl_et => et, :status => "up"})
            elsif last_hb_at < et
              hb_freq = $redis.hget("AP:#{mac}", "hb_freq")
              threshold = RouterInventory.get_hb_intreval(hb_freq.nil? ? 5 : hb_freq.to_i)
              threshold_time = Time.zone.now - threshold.seconds
              if last_hb_at.to_i >= threshold_time.to_i
                slots.push({:sl_st => last_slot_et, :sl_et => et, :status => "up"})
              else
                if last_hb_at < last_slot_et
                  slots.push({:sl_st => last_slot_et, :sl_et => et, :status => "down"})
                else
                  slots.push({:sl_st => last_slot_et, :sl_et => last_hb_at, :status => "up"})
                  slots.push({:sl_st => last_hb_at, :sl_et => et, :status => "down"})
                end
              end
            end
          else
            slots.push({:sl_st => last_slot_et, :sl_et => et, :status => "down"})
          end
        end
        #if slots.empty?
        #  slots.push({:sl_st => st, :sl_et => et, :status => "up"})
        #end
      # else
      #   slots.push({:sl_st => st, :sl_et => et, :status => "up"})
      # end
    else
      message = "please send required params"
      status = 400
      success = false
    end
    render status: status, json: {:success => success, :message => message, :data => slots} 
  end

  def ap_details
    query_string = []
    query_string += params["iccid"].split(",").map {|i| "uplinks.last_mobile_status LIKE '%ICCID: #{i}%'"} if params["iccid"].present?
    query_string += params["imsi"].split(",").map {|i| "uplinks.last_mobile_status LIKE '%IMSI: #{i}%'"}  if params["imsi"].present?
    query_string << "uplinks.eid IN (#{params["eid"].split(",").map {|d| "'#{d}'"}.join(',')})" if params["eid"].present?
    render status: 400, json: {:success => false, :message => "data not found", :data => []} and return if query_string.empty?
    ap_details = Uplink.joins(:router_inventory).where("uplinks.uplink_type = ? AND (#{query_string.join(" OR ")})", 4).select("router_inventories.name, mac_id, location_network_id, uplinks.last_mobile_status AS ms, uplinks.eid AS eid")
    response_data = []
    ap_details.each do |x|
      redis_doc = $redis.hgetall "AP:#{x.mac_id}"
      network_name = x.location_network_id.blank? ? "" : LocationNetwork.where(:id=>x.location_network_id).last.try(:network_name)
      ap_hash = {:mac_id => x.mac_id, :name=>x.name, :eid=> x.eid.blank? ? "" : x.eid, :last_hb=> (redis_doc.present? ? redis_doc["last_hb"] : nil), :network_name=>network_name}
      unless x.ms.blank?
        ap_hash[:iccid] = imsi_iccid x.ms, "ICCID" 
        ap_hash[:imsi] = imsi_iccid x.ms, "IMSI"
      end
      response_data.push(ap_hash)
    end
    render status: 200, json: {:success => true, :data => response_data} and return if ap_details.present?
    render status: 404, json: {:success => false, :message => "data not found", :data => response_data}
  end
  def imsi_iccid x, key
      x.split("|").select {|d| d.match(key)}.first.strip.gsub("#{key}: ","")
  end     
  
  private

  def router_inventories_parms
    params.require(:router_inventories).permit(:name,:address,:notes,:tag_list, :channel,:power,:gre,:dhcp_relay, :ip_type, :ip,:subnet_mask,:gateway,:primary_dns,:secondary_dns,:enable_dhcp_on_lan,:enable_gre_on_lan, :latitude, :longitude, :retry_count, :retry_interval, :retry_ip1, :retry_ip2, :wl_ssid_name, :wl_ssid_uniqe_id, :wl_wpa_key, :wl_wpa_algorithm, :wl_association, :wl_band, :wds_enabled, :enable_lb,:enable_pci, :ttl, :operator, :operator_band, :uplink_type, :nt, :cid, :mm, :lac, :city, :country, :state, :zipcode, :address2, :mo_service, :mo_apn, :mo_device, :mo_username, :mo_password,uplinks_attributes: [:router_inventory_id, :mo_service, :mo_apn, :uplink_module, :mo_device, :mo_username, :mo_password, :mo_is_advanced, :mo_proto_key, :ip_type, :ip, :subnet_mask, :gateway, :primary_dns, :secondary_dns, :load_balance_percentage, :wds_enabled, :wl_wpa_key, :wl_association, :wl_band, :wl_ssid_name, :ttl, :operator, :operator_band, :uplink_type, :nt, :mm, :cid, :lac, :id,:dns_mode,:_destroy,:uplink_name, :is_primary,:wl_ssid_uniqe_id,:pppoe_username,:pppoe_password, :hb_type, :hb_interval, mwan3_cfg: [:up_count, :down_count, :quality_check, :failure_latency, :recovery_latency]])
  end

  def set_router_inventory_group
    @inventory = current_user.organisation.router_inventories.find_by(:mac_id => params[:id]) || current_user.organisation.router_inventories.find_by(:id => params[:id])
    unless @inventory.present?
      if request.format.json?
        render json: {message: "Requested accespoint is not found in your Inventory", error_code: 1011}, status: 404
      else
        flash[:notice] = "Requested accespoint is not found in your Inventory"
        redirect_to inventory_index_path
      end
    else
      unless @inventory.is_up?
        if request.format.json?
          render json: {message: "Device is offline", error_code: 1009, status: false}
        end
      end
      @wired_count = @inventory.hardware_part.present? ? @inventory.hardware_part.wired_count : 1
      version = $redis.hget "AP:#{@inventory.mac_id}","version"
      @wired_count = 1 if version.blank? || version.gsub('.',"").to_i < 20225
    end
  end

  def status_message count,type
    status = msg = ''
    if count.to_i == 0
      status = :success
      if type == 'remove_from_network'
        msg = "Successfully removed the selected devices from network"
      elsif type == 'remove'
        msg = "Successfully removed selected devices"
      elsif type == 'new_network'
       msg = "Successfully created new network:<b>#{params[:network_name]}</b> and assigned selected device to network"
      elsif type == 'existing_network'
        msg = "Successfully assigned the selected device to network <b>#{@network.network_name}</b>"
      elsif type == 'add_tag'
        msg = "Successfully added tags to selected devices"
      elsif type == 'remove_tag'
        msg = "Successfully removed tags from selected devices"
      elsif type == 'add_init_template'
        msg = "Successfully added uplink config to selected devices"
      end
    else
      status = :error
      if type == 'remove_from_network'
        msg = "Oops! Following mac_ids <b>#{@ids}</b> of devices were not been removed from network"
      elsif type == 'remove'
        msg = "Oops! Following mac_ids <b>#{@ids}</b> of devices were not removed"
      elsif type == 'new_network'
       msg = "Oops! Following mac_ids <b>#{@ids}</b> of devices were not assigned to network </b>#{params[:network_name]} </b>"
      elsif type == 'existing_network'
        msg = "Oops! Following mac_ids <b>#{@ids}</b> of devices were not assigned to network #{@network.network_name}"
      elsif type == 'add_tag'
        msg = "Oops! For the following mac_ids <b>#{@ids}</b> of devices tags were not added"
      elsif type == 'remove_tag'
        msg = "Oops! For the following mac_ids <b>#{@ids}</b> of devices tags were not removed"
      elsif type == 'add_init_template'
        msg = "Oops! For the following mac_ids <b>#{@ids}</b> of devices uplink config not applied"
      end
      status = :warning
      if type == 'no_network_with_any_device'
        msg = "Devices are not associated with any of the network."
      elsif type == 'no_network_with_some_device'
        msg = "Some Devices are not associated with any of the network, Some devices Successfully removed from network"
      end
    end
    return status,msg
  end

  def vpn_config_params
    params.require(:vpn).permit(:name,:wireguard,:protocol,:listener_port,:mtu,:wireguard_enable_gateway,:wireguard_gateway_ip,:wireguard_enable_nat,:psk,:end_point_ip,:end_point_port,:wireguard_passthrough,:server_p_allowed_ips,:ike_time,:l_subnet, :remote_ip, :remote_nw_ip,:remote_nw_subnet, :pre_shared_key , :tunnel_connection, :ike, :esp,:location_network_id, :is_enabled, :is_server, :pass_through, :enable_gateway, :gateway_ip, :enable_nat, :enable_server_client, :id, :public_key, :address, :peer_public_key, :private_key, :allowed_ips, associated_resources: [], server_peer: ["public_key","psk" ,"ips"])

  end
end
