module BackendClient
  class Application
    module Utilization

      def utilization(metrics_list)
        response = get("/utilization.xml")
        extract_utilization_xml(response.body, metrics_list)
      rescue
        System::ErrorReporting.report_error($!)
        Collection.error($!)
      end

      class Collection < Array
        attr_accessor :exception

        def self.error(exception)
          new.tap do |collection|
            collection.exception = exception
          end
        end

        def error?
          !!@exception
        end
      end

      private

      def extract_utilization_xml(xml_body, metrics_list)

        doc = Nokogiri::XML(xml_body)
        name2friendlyname = {}
        utilization = []
        infinity_list = []

        metrics_list.each do |metric|
          name2friendlyname[metric.name] = metric.friendly_name
        end

        doc.search("usage_report").each do |item|
          inifinity = false
          if item["max_value"].to_f > 0.0
            value = (item["current_value"].to_f / item["max_value"].to_f)*100.0
            value = (value * 100).to_i / 100.0
          else
            value = 0.0
            infinity = true if item["current_value"].to_f > 0.0
          end

          tmp = {
            :period => item["period"],
            :system_name => item["metric_name"],
            :max_value => item["max_value"],
            :current_value => item["current_value"],
            :percentage => value,
            :friendly_name => name2friendlyname[item[:metric_name]]
          }

          if !infinity
            utilization << tmp
          else
            infinity_list << tmp
          end
        end

        ## now, sort it and merge to infinity list so that it goes first
        result = Collection.new

        utilization = utilization.sort_by { |item| -item[:percentage]}
        infinity_list.each do |item|
          result << UtilizationRecord.new(item)
        end
        utilization.each do |item|
          result << UtilizationRecord.new(item)
        end

        result
      end

    end
  end
end
