require 'all_seeing_eye'
require 'sinatra/base'
require 'erb'
require 'cgi'

class AllSeeingEye
  class Server < Sinatra::Base
    dir = File.dirname(File.expand_path(__FILE__))

    set :views,  "#{dir}/server/views"
    set :public, "#{dir}/server/public"
    set :static, true

    helpers do
      include Rack::Utils
      alias_method :h, :escape_html

      def current_section
        url_path request.path_info.sub('/','').split('/')[0].downcase
      end

      def current_page
        url_path request.path_info.sub('/','')
      end

      def url_path(*path_parts)
        path_parts = path_parts.collect{|p| p.to_s.gsub(path_prefix, '')}
        path = [ path_prefix, path_parts ].compact.join("/")
        ('/' + path).squeeze('/')
      end
      alias_method :u, :url_path
      
      def path_prefix
        ENV['PATH_PREFIX'] || ''
      end

      def class_if_current(path = '')
        'class="current"' if current_page.split('/').any?{|p| p == path}
      end

      def tab(name, prefix = nil)
        dname = name.to_s.downcase
        path = url_path("#{prefix.nil? ? '' : "#{prefix}/"}" + dname)
        "<li #{class_if_current(dname)}><a href='#{path}'>#{humanize name}</a></li>"
      end

      def round(float, n = 2)
        (float * (10.0 ** n)).round * (10.0 ** (-n))
      end
      
      def humanize(string)
        string.split('_').collect(&:capitalize).join(' ')
      end

      def partial?
        @partial
      end

      def partial(template, local_vars = {})
        @partial = true
        erb(template.to_sym, {:layout => false}, local_vars)
      ensure
        @partial = false
      end

    end

    def show(page, layout = true)
      response["Cache-Control"] = "max-age=0, private, must-revalidate"
      erb page.to_sym, {:layout => layout}
    end

    get "/?" do
      redirect url_path(:total)
    end
    
    get '/total' do
      @counts = AllSeeingEye::Request.list_by_field('created_at', :start => (DateTime.now - 2.days).to_i, :stop => DateTime.now.to_i)
      show :total
    end
    
    get '/search' do
      AllSeeingEye.configuration[:models].each do |m|
        results = m.search(params[:query])
        if !results.nil? && !results.empty?
          redirect url_path("/search/#{m.model_name}/#{CGI::escape(params[:query])}")
          break
        end
      end
      show :total
    end
    
    AllSeeingEye.configuration[:models].each do |model|
    
      get "/#{model.model_name}" do
        @model = model
        redirect url_path("/#{model.model_name}/#{model.field_keys.first}")
      end

      AllSeeingEye::Request.field_keys.each do |field|
        get "/#{model.model_name}/#{field}" do
          @model = model
          @page = params[:page].blank? ? 1 : params[:page].to_i
          @field = field
          @count = model.count
          @requests = model.list_by_field(@field, :page => @page)
          show :field
        end
      
        get %r{/search/#{model.model_name}/(.*?)/#{field}$} do
          @model = model
          @page = params[:page].blank? ? 1 : params[:page].to_i
          @field = field
          @query = params[:captures].first
          @requests = model.search(@query)
          counts = Hash.new(0)
          @requests.each {|r| next if r.send(@field.to_sym).nil?; counts[r.send(@field.to_sym)] += 1}
          @requests = counts.sort {|a, b| b.last <=> a.last}
          show :field
        end

        (AllSeeingEye::Request.field_keys - [field]).each do |f|
          get %r{/#{model.model_name}/#{field}/(.*?)/#{f}$} do
            @model = model
            @page = params[:page].blank? ? 1 : params[:page].to_i
            @field = field
            @id = params[:captures].first
            @view = f
            @requests = model.find_by_field(@field, :value => @id)
            counts = Hash.new(0)
            @requests.each {|r| next if r.send(@view.to_sym).nil?; counts[r.send(@view.to_sym)] += 1}
            @requests = counts.sort {|a, b| b.last <=> a.last}
            show :field
          end
        end
      
        get %r{/#{model.model_name}/#{field}/(.*)$} do
          @model = model
          @field = field
          @id = params[:captures].first
          @counts = model.list_by_field(@field, :value => @id)
          show :total
        end
      end
    
      get %r{/search/#{model.model_name}/(.*?)$} do
        @model = model
        @field = 'total'
        @query = params[:captures].first
        @counts = model.search(@query, :count => true)
        show :total
      end
    end
  end
end