#
# Payment subclasses should not involve Artful.ly classes in the internals of ActiveMerchant.  
# Errors should be commincated to callers with the errors Array
#
class Payment 
  include ActiveModel::Validations
  
  attr_accessor :amount, :user_agreement, :transaction_id
  
  #This is named customer as it analogizes the "customer" record on a remote payment
  # system (Braintree, for instance).  It is just a Person object.
  attr_accessor :customer
  
  validates :amount, :numericality => { :greater_than_or_equal_to => 0 }

  #
  # Subclasses should call payment_method :type to get hooked up to the factory
  #
  # For example, a subclass called WonkaPayment can call payment_method :wonka
  # Then callers can instantiate a WonkaPayment by calling Payment.create :wonka
  #
  # This will also define an instance method called "payment_method" on the subclass
  # which will return a stringification of the symbol
  #
  @@payment_methods = HashWithIndifferentAccess.new
  
  def self.payment_method names
    names = Array.wrap(names)
    names.each do |name|
      @@payment_methods[name] = self
    end
    
    self.class_eval(<<-EOS, __FILE__, __LINE__)
      def payment_method
        "#{names[0].to_s.gsub('_',' ').capitalize}"
      end
      
      def self.payment_method
        "#{names[0].to_s.gsub('_',' ').capitalize}"
      end
    EOS
  end

  #
  # Call this method to create sub-classes of Payment.  params will be passed through to the child class
  #
  def self.create(type, params = {})
    type = type.parameterize.underscore.to_sym if type.is_a? String
    c = @@payment_methods[type]
    if c 
      c.new(params)
    else
      raise "No payment method registered for [#{type}], did you call payment_method in the subclass?"
    end
  end
  
  #
  # Subclasses that need to actually process something should override this method
  #
  def purchase(options = {})
  end

  #
  # Likewise with payments that need to refund
  #
  def refundable?
    true
  end

  def refund(refund_amount, transaction_id, options = {})
    true
  end
  
  def requires_authorization?
    false
  end

  def requires_settlement?
    false
  end
  
  def payment_phone_number
    nil
  end
  
  def reduce_amount_by(amount_in_cents)
    self.amount= self.amount - amount_in_cents
  end
  
  def per_item_processing_charge
    lambda { |item| item.realized_price * 0.035 }
  end
  
  #
  # This is quite a hack and should only be needed for development
  # The Payment subclasses need to be loaded so that their payment_method stuff can run and be injected
  # before the interpreter gets around to loading them
  #
  if Rails.env.development?
    Rails.configuration.payment_model_paths.each do |model|
      require_dependency model
    end
  end
end