require 'uri'

module NginxTail
  module HttpReferer

    #
    # to easily identify external referers, for filtering and formatting purposes
    #
    # e.g. Regexp.compile('^http(s)?://(www\.)?MY_WEBSITE_NAME\.com')
    #

    UNKNOWN_REFERER = "-".freeze # the 'default' nginx value for $http_referer variable

    def self.included(base) # :nodoc:
      base.class_eval do

        @@internal_referers = []

        # mainly (solely?) for testing purposes...
        def self.reset_internal_referers()
          while !@@internal_referers.empty? ; @@internal_referers.pop ; end
        end
        
        # mainly (solely?) for testing purposes...
        def self.internal_referers()
          @@internal_referers.dup
        end
        
        def self.add_internal_referer(internal_referer)
          raise "Cannot add unkown HTTP referer" if self.unknown_referer? internal_referer
          (@@internal_referers << internal_referer).uniq!
        end

        def self.unknown_referer?(http_referer)
          http_referer == UNKNOWN_REFERER
        end
        
        def self.internal_referer?(http_referer)
          !self.unknown_referer?(http_referer) && !@@internal_referers.detect { |referer| referer.match(http_referer) }.nil?
        end
        
        def self.external_referer?(http_referer)
          !self.unknown_referer?(http_referer) && !self.internal_referer?(http_referer)
        end

        def self.to_referer_s(http_referer)
          if self.unknown_referer? http_referer
            http_referer
          else begin
              # try to parse it as a URI, but with default value if un-parsable
              URI.parse(http_referer).host || http_referer
            rescue URI::InvalidURIError
              http_referer
            end
          end
        end

        # this ensures the below module methods actually make sense...
        raise "Class #{base.name} should implement instance method 'http_referer'" unless base.instance_methods.map(&:to_s).include? 'http_referer'

      end
    end

    def unknown_referer?
      self.class.unknown_referer?(self.http_referer)
    end
    
    def internal_referer?
      self.class.internal_referer?(self.http_referer)
    end
    
    def external_referer?
      self.class.external_referer?(self.http_referer)
    end
    
    def to_referer_s
      self.class.to_referer_s(self.http_referer)
    end

  end
end