require File.dirname(__FILE__) + '/payflow/payflow_common_api'
require File.dirname(__FILE__) + '/payflow/payflow_express_response'

module ActiveMerchant #:nodoc:
  module Billing #:nodoc:
    class PayflowExpressGateway < Gateway
      include PayflowCommonAPI
      
      LIVE_REDIRECT_URL = 'https://www.paypal.com/cgibin/webscr?cmd=_express-checkout&token='
      TEST_REDIRECT_URL = 'https://test-expresscheckout.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token='
      
      def redirect_url
        test? ? TEST_REDIRECT_URL : LIVE_REDIRECT_URL
      end
      
      def redirect_url_for(token)
        "#{redirect_url}#{token}"
      end
      
      def authorize(money, options = {})
        requires!(options, :token, :payer_id)
        request = build_sale_or_authorization_request('Authorization', money, options)
        commit(request)
      end
      
      def purchase(money, options = {})        
        requires!(options, :token, :payer_id)
        request = build_sale_or_authorization_request('Sale', money, options)
        commit(request)
      end                       
    
      def setup_authorization(money, options = {})
        requires!(options, :return_url, :cancel_return_url)
        
        request = build_setup_express_sale_or_authorization_request('Authorization', money, options)
        commit(request)
      end
      
      def setup_purchase(money, options = {})
        requires!(options, :return_url, :cancel_return_url)
        
        request = build_setup_express_sale_or_authorization_request('Sale', money, options)
        commit(request)
      end
      
      def details_for(token)
        request = build_get_express_details_request(token)
        commit(request)
      end         
      
      private
      def build_get_express_details_request(token)
        xml = Builder::XmlMarkup.new :indent => 2  
        xml.tag! 'GetExpressCheckout' do
          xml.tag! 'Authorization' do
            xml.tag! 'PayData' do  
              xml.tag! 'Tender' do
                xml.tag! 'PayPal' do
                  xml.tag! 'Token', token
                end
              end
            end
          end
        end
        xml.target!
      end
      
      def build_setup_express_sale_or_authorization_request(action, money, options = {})
        xml = Builder::XmlMarkup.new :indent => 2
        xml.tag! 'SetExpressCheckout' do
          xml.tag! action do
            xml.tag! 'PayData' do
              xml.tag! 'Invoice' do
                xml.tag! 'CustIP', options[:ip] unless options[:ip].blank?
                xml.tag! 'InvNum', options[:order_id] unless options[:order_id].blank?
                xml.tag! 'Description', options[:description] unless options[:description].blank?
            
                billing_address = options[:billing_address] || options[:address]
                shipping_address = options[:shipping_address] || billing_address
            
                add_address(xml, 'BillTo', billing_address, options)
                add_address(xml, 'ShipTo', shipping_address, options)
                
                xml.tag! 'TotalAmt', amount(money), 'Currency' => currency(money)
              end
              
              xml.tag! 'Tender' do
                add_paypal_details(xml, options)
              end
            end
          end
        end
        xml.target!
      end
      
      def build_sale_or_authorization_request(action, money, options) 
        xml = Builder::XmlMarkup.new :indent => 2
        xml.tag! 'DoExpressCheckout' do
          xml.tag! action do
            xml.tag! 'PayData' do
              xml.tag! 'Invoice' do 
                xml.tag! 'TotalAmt', amount(money), 'Currency' => currency(money)
              end
              xml.tag! 'Tender' do
                xml.tag! 'PayPal' do
                  xml.tag! 'Token', options[:token]
                  xml.tag! 'PayerID', options[:payer_id]
                  xml.tag! 'NotifyURL', options[:notify_url]
                end
              end
            end
          end
        end
        xml.target!
      end
      
      def build_response(success, message, response, options = {})
        PayflowExpressResponse.new(success, message, response, options)
      end
    end
  end
end