class MonitoringController < ApplicationController
  before_action :authenticate_user!
  before_action :dashboard_topbar#, :except => [:intelligence]
  before_action :topbar_stats, :only => [:dashboard_refresh]

  def query
    query_for = params[:query_for]
    query_type = params[:query_type]
    query_filters = params[:filters]
    return render json: {status: 400, message: "Please provide start & end timestamp."} if params[:filters].blank? || params[:filters][:start_time].blank? || params[:filters][:end_time].blank?
    case query_for
    when "client"
      res_data = LiveAggregateDataQuery.new(query_type, query_filters, @current_user).search_clients
    end 

    if res_data[:data].present?
      render json: res_data.merge({status: 200}), status: 200
    else
      render json: res_data.merge({status: 400}), status: 400
    end
  end

  def dashboard
    if current_user.role.name == 'inventory'
      redirect_to access_points_access_point_path
    end
      find_ssid_for_dashbaord
  end

  def find_ssid_for_dashbaord
    @network_ssids = @current_network.blank? ? [] : @current_network.network_ssids
  end

  def dashboard_refresh
    if @current_network.present?
      router_inventories_macids = @router_inventories.reload.map(&:mac_id)
      if params[:history_date_range].present?
        from_time = Time.zone.parse(params[:history_date_range].split('|')[0]).to_i
        end_time = Time.zone.parse(params[:history_date_range].split('|')[1]).to_i
      else
        from_time = params[:last_refresh_at].present? ? params[:last_refresh_at].to_i : (Time.zone.now - @current_network.hb_freq * 20).to_i #1401467874
        end_time = params[:ends_at].to_i#Time.zone.now.to_i #1401689380
      end

      up_aps = RouterInventory.find_up_list(router_inventories_macids, RouterInventory.get_hb_intreval(@current_network.hb_freq))

      total_aps = router_inventories_macids.count
      aps_up_count = up_aps.count
      aps_down_count =  total_aps - aps_up_count
      notification_count = @current_network.network_unread_notifications.count
      # total_unread_notification_count = current_user.total_unread_notifications.count(:id)
      top_clients_usage = @current_network.top_clients_usage(router_inventories_macids, from_time, end_time)
      clients_device = top_clients_usage.group_by {|c| c["device"]}.map {|k,v| [k.to_s, v.count]}.sort_by {|c| c[0]}

      if params[:only_top_stats] == "true"
        output = {:from_time => from_time, :end_time => end_time, :total_aps => total_aps, :aps_up_count => aps_up_count, :aps_down_count => aps_down_count, :total_clients => top_clients_usage.count, :total_notification_count => notification_count}
      else
        top_aps_usage = @current_network.top_aps_usage(router_inventories_macids, from_time, end_time)
        aps_up = top_aps_usage.map {|a| a["_id"]}
        throughput = {}
        if params[:history_date_range].blank?
          if params[:last_refresh_at].blank?
            from = from_time
            while from <= end_time
              to = from + (@current_network.hb_freq * 2)
              throughput[to] = @current_network.network_throughput_for_interval(aps_up, from, to)
              from = to
            end
          else
            throughput[end_time] = @current_network.network_throughput_for_interval(aps_up, from_time, end_time)
          end

        else
          from = from_time
          while from <= end_time
            to = from + 1.days.seconds.to_i
            throughput[from] = @current_network.network_throughput_for_interval(aps_up, from, to, "$avg")
            from = to
          end
        end
        total_clients_per_ssid = @current_network.no_of_clients_count_per_ssids(aps_up, from_time, end_time)
        clients_mac_per_ap = @current_network.clients_per_aps(aps_up, from_time, end_time)
        clients_mac_per_ap = clients_mac_per_ap.inject({}) {|h, c| h.merge(c["_id"] => c["macs"])}
        total_clients_per_ssid = total_clients_per_ssid.inject({}) {|h, e| h.merge(e["_id"]["SSID"] => e["macs"].count)}

        # aps_list = @router_inventories.reload.inject({}) {|h, e| h.merge(e.mac_id => {"name" => e.name, "address" => e.formatted_address, "active" => up_aps.include?(e.mac_id), "public_ip" => e.get_public_ip, "clients_list" => clients_mac_per_ap[e.mac_id] || [], "url" => inventory_path(e.id), "lat" => e.latitude, "lng" => e.longitude})}
        h={}
        @router_inventories.reload.each do |e|
          h[e.mac_id] = {"name" => e.name, "address" => e.formatted_address, "active" => up_aps.include?(e.mac_id), "public_ip" => "", "clients_list" => clients_mac_per_ap[e.mac_id] || [], "url" => inventory_path(e.id), "lat" => e.latitude, "lng" => e.longitude}
        end
        aps_list = h
        output = {:top_aps => top_aps_usage[0,5], :top_clients => top_clients_usage[0,5], :from_time => from_time, :end_time => end_time, :total_aps => total_aps, :aps_up_count => aps_up_count, :aps_down_count => aps_down_count, :throughput => throughput, :total_clients => top_clients_usage.count, :aps_list => aps_list, :total_clients_per_ssid => total_clients_per_ssid, :total_notification_count => notification_count, :clients_device => clients_device}
      end
    else
      output = {}
    end
    render :json => output.to_json
  end

  def change_network
    network = current_user.location_networks.find_by_id(params[:id])
    unless network.present?
    network = current_user.location_networks.first
    flash[:notice] = "Your network has been changed to #{network.network_name}"
    end
    current_user.current_network = network.id
    @current_network = current_user.current_network
    logger.info("Current Network in show <<<<<<#{@current_network.id}") unless @current_network.blank?
    find_ssid_for_dashbaord
    redirect_to root_path
  end

  def fetch_history_data
    query = params[:history_date_range].split('|')
    if params[:ap_mac].present?
      ris = [params[:ap_mac]]
      lns = [RouterInventory.find_by_mac_id(params[:ap_mac]).location_network_id]
    else
      @current_network = LocationNetwork.where(id: params[:network_id]).last unless params[:network_id].blank?
      render status: 404, json: {:success => false, :message => "Network not found."} and return if @current_network.blank?

      ris = @current_network.router_inventories.pluck(:mac_id)
      lns = [@current_network.id]
    end
    aggregate_query = AggregateDataQuery.new(query, ris, lns)
    output = {from: Time.parse(aggregate_query.criteria[:st].to_s).to_i, to: Time.parse(aggregate_query.criteria[:et].to_s).to_i }
    
    params[:query_for] = params[:query_for].split(',') if params[:query_for].is_a?(String)

    if params[:query_for].include? "ap-thro"
      throughput = aggregate_query.aps_throughput
      output["ap-t"] = throughput.inject({}) {|h, v| h[v["_id"]["d"].to_i + (v["_id"]["h"] || 0) * 3600] = {"tx" => v["tx"].round(2), "rx" => v["rx"].round(2)};h}
      output["ap-u"] = throughput.inject({}) {|h, v| h[v["_id"]["d"].to_i + (v["_id"]["h"] || 0) * 3600] = {"tx_u" => v["tx_u"].round(2), "rx_u" => v["rx_u"].round(2)};h}
    end

    if params[:query_for].include? "cli-thro"
      if params[:client_mac].present?
        throughput = aggregate_query.client_throughput params[:client_mac]
      else
        throughput = aggregate_query.clients_throughput
      end
      output["cli-t"] = throughput.inject({}) {|h, v| h[v["_id"]["d"].to_i + (v["_id"]["h"] || 0) * 3600] = {"tx" => v["tx"].round(2), "rx" => v["rx"].round(2)};h}
    end

    if params[:query_for].include? "ap-usage"
      top_aps_usage = aggregate_query.aps_total_usage 0, 5
      output["ap-u"] = top_aps_usage.map {|ap| [ap['_id'], ap['tx'], ap['rx']]}.transpose
    end

    if params[:query_for].include? "cli-usage"
       hsh = {}
       val = ClientDevice.all.pluck(:mac, :nick_name, :original_name)
       val.each {|i| hsh[i[0]] = (i[1] || i[2].to_s)}
      if params[:query_from] == 'connected_clients'
        top_clients_usage = aggregate_query.clients_total_usage (params[:offset].to_i - 1) * 25, 25
        output["cli-u"] = top_clients_usage.map {|c| [c['_id'], c['tx'], c['rx'], c['ip'], (c['l_time'].present? ? Time.parse(c['l_time'].to_s).to_i * 1000 : ""), (hsh[c['_id']]) || (c['hostname'])]}
      else
        top_clients_usage = aggregate_query.clients_total_usage 0, 5
        output["cli-u"] = top_clients_usage.map {|c| [c['_id'], c['tx'], c['rx'], c['ip'], (c['l_time'].present? ? Time.parse(c['l_time'].to_s).to_i * 1000 : ""), (hsh[c['_id']]) || (c['hostname'])]}.transpose
      end
    end

    if params[:query_for].include? "con-clis"
      connected_clients = aggregate_query.clients_count
      output["con-clis"] = connected_clients.inject({}) {|h, v| h[v["_id"]["d"].to_i + (v["_id"]["h"] || 0) * 3600] = v["count"];h}
    end

    if params[:query_for].include? "ssid-clis"
      ssids_clients = aggregate_query.clients_count_per_ssids
      output["ssid-clis"] = ssids_clients.inject({}) {|h, v| h[v["_id"].to_i] = v["count"];h}
    end

    if params[:query_for].include? "clis-count"
      if params[:ap_mac].present?
        output["clis-count"] = aggregate_query.distinct_clients_count_for_ap params[:ap_mac]
      else
        output["clis-count"] = aggregate_query.distinct_clients_count
      end
    end

    if params[:query_for].include? "clis-device"
      output["clis-device"] = aggregate_query.clients_devices_count
      output["clis-device"] = output["clis-device"].map {|c| [c['_id'], c['count']]}
    end

    if params[:query_for].include? "general"
      total_macs = LocationNetwork.includes(:router_inventories).where(:id => aggregate_query.lns).map {|ln| ln.router_inventories.pluck :mac_id }.flatten.uniq
      output["total_aps"] = total_macs.count
      output["up_aps"] = (total_macs & aggregate_query.up_aps).count
      #output["total_aps"] = LocationNetwork.includes(:router_inventories).where(:id => aggregate_query.lns).map {|ln| ln.router_inventories.pluck :mac_id }.flatten.uniq.count
      #output["up_aps"] = aggregate_query.up_aps.count
      output["total_clients"] = aggregate_query.distinct_clients_count
      #output["ssid_details"] = LocationNetwork.includes(:network_ssids).where(aggregate_query.lns).map { |ssid| [ ssid.id, ssid.ssid_name, ssid.security_mode ] }
    end

    render :json => output.to_json
  end

  def intelligence
    @orgs_dashboard = JSON.parse($redis.hget("AIOPS:DASHBOARD:MAP", current_user.organisation_id.to_s) || '{}')
    if current_user.email == "ankur@wavespot.net" 
      @ns = "wavespot"
    else
      @ns = "#{current_user.organisation_id}#{current_user.organisation.organisation_name.downcase.gsub(/[&|-|_| ]/, "")}"
    end
  end
    
  def fetch_realtime_throughput_data
    time_now = Time.zone.now
    end_time = time_now.to_i
    output = {}
    if params[:query_for].include? "cli-real-thro"
      from_time = (time_now - @current_network.hb_freq * 10).to_i #1401467874
      output = {from: from_time, to: end_time}
      throughput = {}
      from = from_time
      clients = {}
      ris = @current_network.router_inventories.pluck(:mac_id)
      while from < end_time
        to = from + (@current_network.hb_freq)
        clients = @current_network.clients_throughput_for_interval(ris, Time.at(from), Time.at(to), nil, params[:client_mac])
        throughput[to] = {rx: clients['rx'], tx: clients['tx']}
        clients = clients['clients']

        from = to
      end
      output["cli-t"] = throughput
      output["last_seen_clients"] = clients
    end

    if params[:query_for].include? "ap-real-thro"
      throughput = {}
      clients = []
      ris = []
      ri = @current_organisation.router_inventories.where(:mac_id => params[:ap_mac]).first
      if ri.present? && ri.location_network_id.present?
        ln = ri.location_network
        from_time = (time_now - (ln.try(:hb_freq) || 5) * 10).to_i #1401467874
        from = from_time
        output = {from: from_time, to: end_time}
        if(ri.switch?)
          ports_last_status = []
          ports_last_status = ri.get_ports_last_status Time.at(from_time)
        end
        #ln = ri.location_network
        while from < end_time
          to = from + ln.hb_freq
          ap_thro = ln.uplinks_throughput_for_interval([ri.mac_id], Time.at(from), Time.at(to))
          throughput[to] = ap_thro['uplinks']
          clients = ap_thro['clients']

          from = to
        end

        output["ap-t"] = throughput
        output["last_seen_clients"] = clients
        output["ports_last_status"] = ports_last_status unless ports_last_status.blank?
      end
    end
    render :json => output.to_json
  end

  private

  def topbar_stats
    @current_network = LocationNetwork.where(id: params[:network_id]).last unless params[:network_id].blank?
    @router_inventories = @current_network.blank? ? [] : @current_network.router_inventories
  end
end
