require File.expand_path('../../lib/gov_kit-ca', __FILE__)

# The following file maps 629,605 postal codes to electoral districts:
# https://github.com/danielharan/canadian-postal-code-to-electoral-districts/raw/master/pc_edid.yml
# However, it contains invalid postal codes, such as M5V1L6, and doesn't contain
# every electoral district, such as 35061 (postal code L1H1X8).
#
# http://www.digital-copyright.ca/pcfrf/pcfrf.tgz contains
# postal-code-for-districts.csv, "which is 308 postal codes that should map to
# each of the 308 different electoral districts." However, six of them do not
# exist (G0A2C0, J8M1R8, J0W1B0, J0B1H0, L0J1B0, N2A1A3), 14 are duplicate, and
# the remaining 294 map to 246 electoral districts.
#
# The included tasks/postal-code-for-districts.csv covers 275 electoral
# districts at the time of writing.
desc "Picks the set cover for postal codes to electoral districts"
task :trim_postal_codes, :file do |t,args|
  abort "Usage: rake #{t.name}[postal-code-for-districts.csv]" unless args[:file]

  # Get the electoral districts that each postal code covers
  postal_to_edid = {}
  File.read(args[:file]).split("\n").uniq.each do |postal_code| # Remove duplicate postal codes
    postal_to_edid[postal_code] = GovKit::CA::PostalCode.find_electoral_districts_by_postal_code(postal_code)
  end

  size = postal_to_edid.values.flatten.uniq.size
  if size < 308
    puts "Postal codes cover #{size} of 308 electoral districts."
  end

  # Get the minimum number of postal codes to cover all electoral districts.
  # This is an instance of the set cover problem, which is NP-complete. Use the
  # greedy algorithm, which is the best-possible polynomial time approximation
  # algorithm for set cover. http://en.wikipedia.org/wiki/Set_cover_problem
  postal_codes = []
  until postal_to_edid.empty?
    postal_code, edids = postal_to_edid.max{|_,v| v.size}
    postal_to_edid.each{|k,v| postal_to_edid[k] -= edids}
    postal_to_edid.reject!{|k,v| v.empty?}
    postal_codes << postal_code
  end

  puts postal_codes.sort
end

desc "Generate RSpec fixtures"
task :generate_rspec_fixtures do |t,args|
  require 'gov_kit-ca/postal_code/strategy/conservative_ca'
  require 'gov_kit-ca/postal_code/strategy/digital-copyright_ca'
  require 'gov_kit-ca/postal_code/strategy/liberal_ca'
  require 'gov_kit-ca/postal_code/strategy/parl_gc_ca'

  { 'CBCCa'              => 'cbc_ca',
    'ConservativeCa'     => 'conservative_ca',
    'DigitalCopyrightCa' => 'digital-copyright_ca',
    'ElectionsCa'        => 'elections_ca',
    'GreenPartyCa'       => 'greenparty_ca',
    'LiberalCa'          => 'liberal_ca',
    'NDPCa'              => 'ndp_ca',
    'ParlGcCa'           => 'parl_gc_ca',
  }.each do |const,path|
    %w(A1A1A1 G0C2Y0 T5S2B9 K0A1K0 H0H0H0 X1B1B1).each do |postal_code|
      File.open(File.expand_path("../../spec/fixtures/#{path}/#{postal_code}.response", __FILE__), 'w') do |f|
        response = GovKit::CA::PostalCode::Strategy.const_get(const).new(postal_code).send(:response)
        f.write "HTTP/#{response.http_version} #{response.code} #{response.message}\n"
        response.headers.each_capitalized do |name,value|
          f.write "#{name}: #{value}\n"
        end
        f.write "\n#{response.body}"
      end
    end
  end
end