require 'csv'

module JamRuby
  class MaxMindGeo < ActiveRecord::Base

    self.table_name = 'max_mind_geo'

    @@log = Logging.logger[MaxMindGeo]

    def self.import_from_max_mind(options)

      file = options[:file]
      use_copy = options[:use_copy]

      # File Geo-139
      # Format:
      # startIpNum,endIpNum,country,region,city,postalCode,latitude,longitude,dmaCode,areaCode

      start = Time.now

      MaxMindGeo.delete_all

      if use_copy
        Database.copy(MaxMindGeo.table_name, file)
      else
        File.open(file, 'r:ISO-8859-1') do |io|
          s = io.gets.strip # eat the headers line
          unless s.eql? 'startIpNum,endIpNum,country,region,city,postalCode,latitude,longitude,dmaCode,areaCode'
            puts s
            puts 'startIpNum,endIpNum,country,region,city,postalCode,latitude,longitude,dmaCode,areaCode'
            raise 'file does not start with expected header (line 1): startIpNum,endIpNum,country,region,city,postalCode,latitude,longitude,dmaCode,areaCode'
          end

          saved_level = ActiveRecord::Base.logger ? ActiveRecord::Base.logger.level : 0
          count = 0

          stmt = "insert into #{MaxMindGeo.table_name} (country,region,city,lat,lng,ip_start,ip_end) values"

          vals = ''
          sep = ''
          i = 0
          n = 20 # going from 20 to 40 only changed things a little bit

          csv = ::CSV.new(io, {encoding: 'ISO-8859-1', headers: false})
          csv.each do |row|
            raise "file does not have expected number of columns (10): #{row.length}" unless row.length == 10

            ip_start = ip_address_to_int(strip_quotes(row[0]))
            ip_end = ip_address_to_int(strip_quotes(row[1]))
            country = row[2]
            region = row[3]
            city = row[4]
            #postalcode = row[5]
            lat = row[6]
            lng = row[7]
            #dmacode = row[8]
            #areacode = row[9]

            vals = vals+sep+"(#{quote_value(country, nil)},#{quote_value(region, nil)},#{quote_value(city, nil)},#{lat},#{lng},#{ip_start},#{ip_end})"
            sep = ','
            i += 1

            if count == 0 or i >= n then
              MaxMindGeo.connection.execute stmt+vals
              count += i
              vals = ''
              sep = ''
              i = 0

              if ActiveRecord::Base.logger and ActiveRecord::Base.logger.level > 1 then
                ActiveRecord::Base.logger.debug "... logging inserts into #{MaxMindGeo.table_name} suspended ..."
                ActiveRecord::Base.logger.level = 1
              end

              if ActiveRecord::Base.logger and count%10000 < n then
                ActiveRecord::Base.logger.level = saved_level
                ActiveRecord::Base.logger.debug "... inserted #{count} into #{MaxMindGeo.table_name} ..."
                ActiveRecord::Base.logger.level = 1
              end
            end
          end

          if i > 0 then
            MaxMindGeo.connection.execute stmt+vals
            count += i
          end

          if ActiveRecord::Base.logger then
            ActiveRecord::Base.logger.level = saved_level
            ActiveRecord::Base.logger.debug "loaded #{count} records into #{MaxMindGeo.table_name}"
          end
        end
      end


      # User.find_each { |usr| usr.update_lat_lng }
      # THIS DOESNT ACTUALLY DO ANYTHING BECAUSE IT NEVER SAVES
      Band.find_each { |bnd| bnd.update_lat_lng }

      elapsed = Time.now - start
      @@log.debug("#{MaxMindGeo.table_name} import took #{elapsed} seconds")
    end

    def self.where_latlng(relation, params, current_user=nil)
      # this is only valid to call when relation is about bands
      distance = params[:distance].to_i
      if distance > 0
        latlng = nil
        location_city = params[:city]
        location_state = params[:state]
        location_country = params[:country]
        remote_ip = params[:remote_ip]

        if location_city and location_state and location_country
          geo = self.where(city: location_city, region: location_state, countrycode: location_country).limit(1).first
          if geo and geo.lat and geo.lng and (geo.lat != 0 or geo.lng != 0)
            # it isn't reasonable for both to be 0...
            latlng = [geo.lat, geo.lng]
          end
        elsif current_user and current_user.locidispid and current_user.locidispid != 0
          location = GeoIpLocations.find_by_locid(current_user.locidispid/1000000)
          if location and location.latitude and location.longitude and (location.latitude != 0 or location.longitude != 0)
            # it isn't reasonable for both to be 0...
            latlng = [location.latitude, location.longitude]
          end
        elsif remote_ip
          geo = self.ip_lookup(remote_ip)
          if geo and geo.lat and geo.lng and (geo.lat != 0 or geo.lng != 0)
            # it isn't reasonable for both to be 0...
            latlng = [geo.lat, geo.lng]
          end
        end

        if latlng
          relation = relation.where(['lat IS NOT NULL AND lng IS NOT NULL']).within(distance, origin: latlng)
        end
      end
      relation
    end

  end

end
