# Copyright 2011 Marc Hedlund <marc@precipice.org>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# report.rb - basic tool for building up reports.

require 'chronic'

module Report
  class Item
    attr_accessor :time

    def initialize(time)
      @time = time
    end

    def between?(start_time, end_time)
      time >= start_time and time < end_time
    end

    def off_hours?
      # Outside normal work hours - 6p to 8a (localtime)
      time.hour >= 18 or graveyard?
    end

    def graveyard?
      # Worst of the worst - midnight to 8am (localtime)
      time.hour < 8
    end
  end

  class Summary
    attr_accessor :current_start, :current_end, :previous_start, :previous_end

    def initialize(current_start, current_end, previous_start, previous_end)
      @current_start  = current_start
      @current_end    = current_end
      @previous_start = previous_start
      @previous_end   = previous_end
      @items          = []
    end

    def <<(item)
      @items << item
    end

    def current_items
      select_between?(current_start, current_end)
    end

    def previous_items
      select_between?(previous_start, previous_end)
    end

    def current_count(&selector)
      count_from(current_items, &selector)
    end

    def previous_count(&selector)
      count_from(previous_items, &selector)
    end

    def current_summary(&selector)
      summarize(current_items, &selector)
    end

    def previous_summary(&selector)
      summarize(previous_items, &selector)
    end

    def pct_change(&selector)
      old_value = previous_count(&selector)
      new_value = current_count(&selector)
      Report.pct_change old_value, new_value
    end

    private

    def summarize(collection)
      summary = Hash.new(0)

      collection.each do |item|
        yield item, summary
      end

      return summary.sort {|a, b| b[1] <=> a[1] }
    end

    def count_from(collection)
      if block_given?
        return collection.count {|item| yield item }
      else
        return collection.count
      end
    end

    def select_between?(a, b)
      @items.select {|item| item.between?(a, b) }
    end
  end

  def self.pct_change(old_value, new_value)
    if old_value == 0
      return "no occurrences last week"
    else
      change = (((new_value.to_f - old_value.to_f) / old_value.to_f) * 100).to_i

      if change == 0
        return "no change vs. last week"
      elsif change < 0
        return "#{change}% vs. last week"
      else
        return "+#{change}% vs. last week"
      end
    end
  end
end