# import the required packages
from tg import expose, url, redirect, validate, flash
from pylons import tmpl_context, request
from tw.api import WidgetsList
from tw.forms import TableForm, TextField, SingleSelectField, Spacer, CalendarDatePicker, validators

# FancyValidator to process the Credit Card using the authorize package
class ProcessCard(validators.FancyValidator):
    def _to_python(self, value, state):
        from authorize import aim as aim_api
        
        # Setup the aim Api object.
        aim = aim_api.Api(AUTHNET_LOGIN, AUTHNET_KEY, is_test=False)
        
        # Create a transaction against a credit card
        result_dict = aim.transaction(
            amount=u"16.00",
            card_num=unicode(value['card_number']),
            exp_date=unicode(value['card_expiry']),
            # ...and others...
            )
        
        if result_dict['code'] == '1':
            # success
            return value
        else:
            # failure
            raise validators.Invalid(result_dict['reason_text'], value, state)

# The actual form class
class AuthnetForm(TableForm):
    # Change the submit button text
    submit_text='Process Card'
    
    # Specify form validators
    validator = validators.Schema(
        chained_validators = [
            validators.CreditCardValidator('card_type','card_number'),
            validators.CreditCardSecurityCode('card_type','card_cvv'),
            # you could also add an expiry validator, but authnet will handle this for you
            ProcessCard()
        ]
    )
    
    # Specify form fields
    class fields(WidgetsList):
        name = TextField(validator=validators.String(not_empty=True))
        # ...and others like address, city, state, zip...
        spacer = Spacer(suppress_label=True)
        card_type = SingleSelectField(options=[('visa', 'Visa'), ('mastercard', 'Master Card'), ('discover', 'Discover'), ('amex', 'American Express')], validator=validators.NotEmpty)
        card_expiry = CalendarDatePicker(date_format="%m/%Y", validator=validators.NotEmpty)
        card_number = TextField(label_text='Card #', validator=validators.NotEmpty)
        card_cvv = TextField(label_text='CVV Code', validator=validators.NotEmpty)

# Assign the form to authnet_form
authnet_form = AuthnetForm('authnet_form', action=url('/authnet/process/'))

class AuthnetController(BaseController):
    @expose('authnet.templates.index')
    def index(self, **kw):
        if '_the_form' in tmpl_context.form_errors:
            # if we have top-level form errors, use flash() to display them
            flash(tmpl_context.form_errors['_the_form'], 'error')
        # Use ${form()} to print the form in your template
        return dict(form=authnet_form)
    
    
    @validate(authnet_form, error_handler=index)
    @expose()
    def process(self, **kw):
        # if validation passes, this method will run (specified by form action)
        return 'Card was successfully charged!'

