/***
 * Excerpted from "Domain-Driven Design Using Naked Objects",
 * published by The Pragmatic Bookshelf.
 * Copyrights apply to this code. It may not be used to create training material, 
 * courses, books, articles, and the like. Contact us if you are in doubt.
 * We make no guarantees that this code is fit for any purpose. 
 * Visit http://www.pragmaticprogrammer.com/titles/dhnako for more book information.
***/
package com.pragprog.dhnako.carserv.fixture.customer;

import org.nakedobjects.applib.Filter;
import org.nakedobjects.applib.fixtures.AbstractFixture;

import com.pragprog.dhnako.carserv.dom.customer.Account;
import com.pragprog.dhnako.carserv.dom.customer.Cash;
import com.pragprog.dhnako.carserv.dom.customer.CreditCard;
import com.pragprog.dhnako.carserv.dom.customer.Customer;
import com.pragprog.dhnako.carserv.dom.customer.CustomerRepository;
import com.pragprog.dhnako.carserv.dom.payment.PaymentMethod;
import com.pragprog.dhnako.carserv.dom.payment.PaymentMethodType;
import com.pragprog.dhnako.carserv.dom.person.Person;
import com.pragprog.dhnako.carserv.dom.person.Title;

public abstract class AbstractCustomerFixture extends AbstractFixture {

    public abstract void install();
    
    protected Person createCustomer(
    		final String titleName, 
    		final String lastName, final String firstName) {
    	Person customer = customerRepository.newCustomer();
        customer.getName().setTitle(findTitle(titleName));
        customer.getName().setLastName(lastName);
        customer.getName().setFirstName(firstName);
        
        @SuppressWarnings("unused")
		Customer customerRole = customer.getRole(Customer.class);
        // setup customer role if required.
        
        persist(customer);
        return customer;
    }

	protected Title findTitle(final String titleName) {
		return firstMatch(Title.class, new Filter<Title>() {
			public boolean accept(Title title) {
				return title.getName().equals(titleName);
			}
        });
	}
	
	protected void newCashPaymentMethod(Customer customer, String name) {
    	Cash cash = (Cash) customer.newPaymentMethod(findPaymentMethodType(Cash.class));
    	cash.setName(name);
		persist(cash);
	}
    
	protected void newAccountPaymentMethod(Customer customer, String name, int limit) {
		Account account = (Account) customer.newPaymentMethod(findPaymentMethodType(Account.class));
    	account.setName(name);
		account.setBalance(0);
		account.setLimit(limit);
		persist(account);
	}
    
	protected void newCreditCardPaymentMethod(Customer customer, String name, String cardNumber, String expiryDate) {
		CreditCard creditCard = (CreditCard) customer.newPaymentMethod(findPaymentMethodType(CreditCard.class));
		creditCard.setName(name);
		creditCard.setCardNumber(cardNumber);
		creditCard.setExpiryDate(expiryDate);
		persist(creditCard);
	}
    
    protected PaymentMethodType findPaymentMethodType(final Class<? extends PaymentMethod> paymentMethodClass) {
    	return firstMatch(PaymentMethodType.class, new Filter<PaymentMethodType>() {
			public boolean accept(PaymentMethodType paymentMethodType) {
				return paymentMethodType.paymentMethodSubclass() == paymentMethodClass;
			}
    	});
    }


	
	// {{ injected: CustomerRepository
	private CustomerRepository customerRepository;

	public void setCustomerRepository(final CustomerRepository customerRepository) {
		this.customerRepository = customerRepository;
	}
	// }}


}
