require 'carmen'

module Effective
  class Address < ActiveRecord::Base
    self.table_name = EffectiveAddresses.addresses_table_name.to_s

    belongs_to :addressable, :polymorphic => true, :touch => true

    structure do
      category        :string, :validates => [:presence, :inclusion => { :in => %w(billing shipping primary secondary address)}]

      full_name       :string, :validates => [:presence]
      address1        :string, :validates => [:presence]
      address2        :string
      city            :string, :validates => [:presence]
      state_code      :string, :validates => [:presence]
      country_code    :string, :validates => [:presence]
      postal_code     :string, :validates => [:presence]
      timestamps
    end

    default_scope order(:updated_at)

    scope :billing_addresses, -> { where(:category => 'billing') }
    scope :shipping_addresses, -> { where(:category => 'shipping') }

    def first_name
      full_name.split(' ').first rescue full_name
    end

    def last_name
      full_name.gsub(first_name, '').strip rescue full_name
    end

    def country
      Carmen::Country.coded(country_code).name rescue ''
    end

    def state
      Carmen::Country.coded(country_code).subregions.coded(state_code).name rescue ''
    end

    def province
      Carmen::Country.coded(country_code).subregions.coded(state_code).name rescue ''
    end

    def country=(country_string)
      value = Carmen::Country.named(country_string) || Carmen::Country.coded(country_string.try(:upcase))
      self.country_code = value.code if value.present?
    end

    def state=(state_string)
      if country.present?
        value = Carmen::Country.coded(country_code).subregions.named(state_string) || Carmen::Country.coded(country_code).subregions.coded(state_string.try(:upcase))
        self.state_code = value.code if value.present?
      else
        Rails.logger.info 'No country set.  Try calling country= before state='
        puts 'No country set.  Try calling country= before state='
      end
    end

    def postal_code_looks_canadian?
      postal_code.gsub(/ /, '').strip.match(/^\D{1}\d{1}\D{1}\-?\d{1}\D{1}\d{1}$/).present? rescue false # Matches T5T2T1 or T5T-2T1
    end

    def ==(other_address)
      self_attrs = self.attributes
      other_attrs = other_address.respond_to?(:attributes) ? other_address.attributes : {}

      [self_attrs, other_attrs].each { |attrs| attrs.except!('id', 'created_at', 'updated_at', 'addressable_type', 'addressable_id', 'address2') }

      self_attrs == other_attrs
    end

    # An address may be set with a category but nothing else
    # This is considered empty
    def empty?
      !full_name.present? and !address1.present? and !address2.present? and !city.present? and !state_code.present? and !country_code.present? and !postal_code.present?
    end

    def to_s
      output = "#{full_name}\n"
      output += "#{address1}\n"
      output += "#{address2}\n" if address2.present?
      output += "#{city}, #{state}\n"
      output += "#{country}, #{postal_code}"
    end

    def to_html
      to_s.gsub(/\n/, '<br>').html_safe
    end
  end
end