require 'open-uri' require 'csv'

namespace :zipcodes do

desc "Update states table"
task :update_states => :environment do
  puts ">>> Begin update of states table..."
  url = "https://github.com/midwire/free_zipcode_data/raw/master/all_us_states.csv"
  data = open(url)
  file = nil
  if data.is_a? StringIO
    file = Tempfile.new('all_us_states.csv')
    file.write(data.read)
    file.flush
    file.close
  else
    file = data
  end
  CSV.foreach(file.path, :headers => true) do |row|
    puts "Updating state: [#{row['name']}]"
    state = State.where(abbr: row['abbr']).first_or_initialize
    state.update_attribute(:name, row['name'])
  end
  data.close
  puts ">>> End update of states table..."
end

desc "Update counties table"
task :update_counties => :update_states do
  puts ">>> Begin update of counties table..."
  url = "https://github.com/midwire/free_zipcode_data/raw/master/all_us_counties.csv"
  data = open(url)
  file = nil
  if data.is_a? StringIO
    file = Tempfile.new('all_us_counties.csv')
    file.write(data.read)
    file.flush
    file.close
  else
    file = data
  end
  CSV.foreach(file.path, :headers => true) do |row|
    puts "Updating county: [#{row['name']}]"
    # lookup state
    state = State.find_by_abbr!(row['state'])
    county = County.where(name: row['name'], state_id: state.to_param).first_or_initialize
    county.update_attribute(:county_seat, row['county_seat'])
  end
  data.close
  puts ">>> End update of counties table..."
end

desc "Update zipcodes table"
task :update_zipcodes => :update_counties do
  puts ">>> Begin update of zipcodes table..."
  url = "https://github.com/midwire/free_zipcode_data/raw/master/all_us_zipcodes.csv"
  data = open(url)
  file = nil
  if data.is_a? StringIO
    file = Tempfile.new('all_us_zipcodes.csv')
    file.write(data.read)
    file.flush
    file.close
  else
    file = data
  end
  CSV.foreach(file.path, :headers => true) do |row|
    puts "Updating zipcode: [#{row['code']}], '#{row['city']}, #{row['state']}, #{row['county']}"
    # lookup state
    state = State.find_by_abbr!(row['state'])
    begin
      county = County.find_by_name_and_state_id!(row['county'], state.to_param)
    rescue Exception => e
      puts ">>> e: [#{e}]"
      puts ">>>> No county found for zipcode: [#{row['code']}], '#{row['city']}, #{row['state']}, #{row['county']}... SKIPPING..."
      next
    end
    zipcode = Zipcode.where(code: row['code']).first_or_initialize
    zipcode.update_attributes!(
      :city => row['city'].titleize,
      :state_id => state.to_param,
      :county_id => county.to_param,
      :lat => row['lat'],
      :lon => row['lon']
    )
  end
  data.close
  puts ">>> End update of zipcodes table..."
end

desc "Populate or update the zipcodes related tables"
task :update => :environment do
  Rake::Task['zipcodes:update_zipcodes'].invoke
end

desc "Export US States to a .csv file"
task :export_states => :environment do
  @states = State.order("name ASC")
  csv_string = CSV.generate do |csv|
    csv << ["abbr", "name"]
    @states.each do |state|
      csv << [
        state.abbr,
        state.name
        ]
    end
  end
  filename = "all_us_states.csv"
  open("#{Rails.root}/db/#{filename}", 'w') do |f|
    f.write(csv_string)
  end
end

desc "Export all US Counties to a .csv file"
task :export_counties => :environment do
  @counties = County.order("name ASC")
  csv_string = CSV.generate do |csv|
    csv << ["name", "state", "county_seat"]
    @counties.each do |county|
      csv << [
        county.name,
        county.state.abbr,
        county.county_seat
        ]
    end
  end
  filename = "all_us_counties.csv"
  open("#{Rails.root}/db/#{filename}", 'w') do |f|
    f.write(csv_string)
  end
end

desc "Export the zipcodes with county and state data"
task :export_zipcodes => :environment do
  @zipcodes = Zipcode.order("code ASC")
  csv_string = CSV.generate do |csv|
    csv << ["code", "city", "state", "county", "area_code", "lat", "lon"]
    @zipcodes.each do |zip|
      csv << [
        zip.code,
        zip.city,
        zip.state.abbr,
        zip.county.nil? ? '' : zip.county.name,
        zip.area_code,
        zip.lat,
        zip.lon
        ]
    end
  end
  filename = "all_us_zipcodes.csv"
  open("#{Rails.root}/db/#{filename}", 'w') do |f|
    f.write(csv_string)
  end
end

desc "Export zipcodes, states and counties tables"
task :export => :environment do
  Rake::Task['zipcodes:export_states'].invoke
  Rake::Task['zipcodes:export_counties'].invoke
  Rake::Task['zipcodes:export_zipcodes'].invoke
end

end