module JamRuby
  class MaxMindIsp < ActiveRecord::Base

    self.table_name = 'max_mind_isp'

    def self.import_from_max_mind(file)

      # File Geo-142
      # Format:
      # "beginIp","endIp","countryCode","ISP"

      MaxMindIsp.transaction do
        MaxMindIsp.delete_all
        File.open(file, 'r:ISO-8859-1') do |io|
          io.gets  # eat the copyright line. gah, why do they have that in their file??
          MaxMindIsp.pg_copy_from io, :map => { 'beginIp' => 'ip_bottom', 'endIp' => 'ip_top', 'countryCode' => 'country', 'ISP' => 'isp'}, :columns => [:beginIp, :endIp, :countryCode, :ISP] do |row|
            row[0] = ip_address_to_int(strip_quotes(row[0]))
            row[1] = ip_address_to_int(strip_quotes(row[1]))
            row[2] = row[2]
            row[3] = row[3..-1].join(',')   # this is because the parser just cuts on any ',' and ignores double quotes.  essentially postgres-copy isn't a great csv parser -- or I need to configure it better
            while row.length > 4
              row.delete_at(4)
            end

          end
        end
      end
    end

    # Make an IP address fit in a signed int. Just divide it by 2, as the least significant part
    # just can't possibly matter. We can verify this if needed. My guess is the entire bottom octet is
    # actually irrelevant
    def self.ip_address_to_int(ip)
      ip.split('.').inject(0) {|total,value| (total << 8 ) + value.to_i} / 2
    end

    private

    def self.strip_quotes str
      return nil if str.nil?

      if str.chr == '"'
        str = str[1..-1]
      end

      if str.rindex('"') == str.length - 1
        str = str.chop
      end

      return str
    end

    def self.escape str
      str.gsub(/\"/, '""')
    end
  end
end