package extractcommand.step10;

import extractcommand.step00.*;
import extractcommand.AtmCommand;

public class AtmSession {

    AccountService accountService;
    Logger logger;

    public AtmSession(AccountService accountService, Logger logger) {
        this.accountService = accountService;
        this.logger = logger;
    }

    public User checkOwner(final int accountNumber) throws SessionException {
        return new CheckOwner(logger, accountService, accountNumber).execute();
    }

    public Money checkBalance(final int accountNumber) throws SessionException {
        return new CheckBalance(accountNumber, logger, accountService).execute();
    }

    public Money deposit(final int accountNumber, final Money amount) throws SessionException {
        return new Deposit(accountNumber, amount, logger, accountService).execute();
    }

    public Money withdraw(final int accountNumber, final Money amount) throws SessionException {
        return new Withdraw(accountNumber, amount, logger, accountService).execute();
    }

    // * Since transfer has a void return value, don't declare RETURN, and
    // add "return VOID" at end of method
    public void transfer(final int fromAccountNumber, final int toAccountNumber, final Money amount) throws SessionException {
        new AtmCommand(logger) {
            protected Object doExecute() throws AccountServiceException, SessionException {
                foo(fromAccountNumber, toAccountNumber, amount);
                return VOID;
            }
        }.execute();
    }

    private void foo(int fromAccountNumber, int toAccountNumber, Money amount) throws AccountServiceException, SessionException {
        Account fromAccount = accountService.findAccount(fromAccountNumber);
        Account toAccount = accountService.findAccount(toAccountNumber);
        verifyBalance(fromAccount, amount);
        fromAccount.withdraw(amount);
        toAccount.deposit(amount);
    }

    static void verifyBalance(Account account, Money amount) throws SessionException {
        Money balance = account.getBalance();
        if (balance.subtract(amount).isNegative()) {
            throw new SessionException("Insufficient funds");
        }
    }

}

