class SwitchConfiguration < ActiveRecord::Base
  include AssociatedResource #ConfigMapping Association and its methods (app/models/concerns/associated_resource.rb)
  has_many :switch_port_configurations
  belongs_to :location_network
  belongs_to :hardware_part
  belongs_to :organisation
  serialize :sw_mac_oui, Array
  include PublicActivity::Model

  tracked owner: ->(controller, model) { controller && controller.tracked_current_user },params: { :attributes => proc {|controller, model_instance| {"SwitchConfiguration(#{model_instance.hardware_part.name} - (#{model_instance.location_network.network_name}))" => 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}

  scope :filter_by_hw_part, ->(hw_part_id) { where(hardware_part_id: hw_part_id).limit(1) }

  def self.grouped_collection_of_aps location_network, hardware_part_ids=nil, switch_configuration_id=nil
    existing_switch_config_resources = location_network.switch_configurations.filter_by_hw_part(hardware_part_ids).where.not(id: switch_configuration_id).map {|sc| sc.associated_resources }.flatten.uniq
    hash = {}
    hash["Network"] = [[location_network.network_name, "network:#{location_network.id}"]] unless existing_switch_config_resources.include?("network:#{location_network.id}")
    hash["Switch inventory"] = location_network.router_inventories.switches(hardware_part_ids).map {|ri| existing_switch_config_resources.include?("AP:#{ri.id}") ? nil : ["#{ri.name.present? ? (ri.name + " (#{ri.mac_id.last(8)})") : ri.mac_id}", "AP:#{ri.id}"]}.compact
    
    hash
  end

  def configured_switch_ports
    self.switch_port_configurations.where("port_number <= ?", self.hardware_part.port_count)
  end

  def interface_attributes vlan_mapping
    interface_vlan = []
     vlan_mapping.each do |k,v|
        selectedeth =[]
        v.each do |x|
          z= {"select-ports"=> ["Ethernet#{(x[0]-1).to_s}"], "vlan-tag" => x[1].eql?("trunk") ? "tagged" : ((x[1].eql?("hybrid") && x[2]) || x[1].eql?("access")) ? "un-tagged" : "tagged"}
          selectedeth << z.deep_dup if (x[1].eql?("hybrid") && x[2])
          z["pvid"] = true if x[2]
          selectedeth << z
        end
      intf_vlan = { "ethernet"=> selectedeth, "vlan"=>{"id" => k.to_i},"name"=>"VLAN#{k}","enabled"=> true}
      intf_vlan.merge!({"ipv4"=>{"addressing" => "dynamic"}}) if k.to_i == 1
      interface_vlan << intf_vlan #{ "ethernet"=> selectedeth, "vlan"=>{"id" => k.to_i},"name"=>"VLAN#{k}", "ipv4"=>{"addressing" => "dynamic"},"enabled"=> true}
    end
    return interface_vlan
  end

  def json_build
    ports = []
    self.switch_port_configurations.each do |port|
      ports << port.json_build
    end
    {id: self.id, organisation_id: self.organisation_id, device_model: self.hardware_part.try(:name), associated_resources: self.associated_resources, switch_port_configurations: ports}
  end

  def update_redis
    # router = self.router_inventories + RouterInventory.tagged_with(self.tags) + self.location_networks.map{|x| x.router_inventories.switches(self.hardware_part_id)}.flatten
    ris = self.router_inventories
    lns = self.location_networks
    router = (RouterInventory.where(location_network_id: lns.pluck(:id)).all + ris.all + RouterInventory.switches(self.hardware_part_id).tagged_with(self.tags).where(location_network_id: self.location_network_id).all).flatten

    #remove previous config association
    cms = ConfigMapping.arel_table
    ConfigMapping.where( configurable_type: "SwitchConfiguration", resourceable_type: 'RouterInventory', resourceable_id: ris.pluck(:id) ).where(cms[:configurable_id].not_eq(self.id)).each(&:destroy)
    ConfigMapping.where( configurable_type: "SwitchConfiguration", resourceable_type: 'LocationNetwork', resourceable_id: lns.pluck(:id) ).where(cms[:configurable_id].not_eq(self.id)).each(&:destroy)

    (router.uniq||[]).each do |y|
      y.update_redis(true, true) unless y.blank?
    end
  end

  after_update do |ssid|
    ssid.update_redis
  end

  after_create do |x|
    x.update_redis
  end

  after_destroy do |x|
    x.update_redis
  end

  def get_mac_vlan 
#    return nil if self.sw_mac_oui.empty?
    return self.sw_mac_oui
  end

  def get_mac_based_vlan
    mac_based_vlan = []
    self.sw_mac_oui.each do |sw|
      next if (sw["macaddress"].blank? ||  (["1", "3", "5", "7", "9", "B", "D", "F"].include?(sw["macaddress"].upcase[1])))
      h = {"mac" => sw["macaddress"].gsub(":","-"), "mask" => sw["mask"].blank? ? "ff-ff-ff-ff-ff-ff" : sw["mask"].gsub(":","-"), "vid" => sw["vlanid"].to_i}
      h["priority"] = sw["priority"].to_i unless sw["priority"].blank?
      mac_based_vlan << h
    end
    return mac_based_vlan
  end
end
