# -----------------------------------------------------------------------------
# Name:        account
# Purpose:     contains the class definitions for bank accounts
#
# Author:      Rula Khayrallah
#
# Created:     10/04/2013
# -----------------------------------------------------------------------------
"""
Module to describe and manipulate bank accounts.
 
"""


class Account(object):
    """
    Represent a bank account.
 
    Argument:
    account_holder (string): account holder's name.
 
    Attributes:
    holder (string): account holder's name.
    balance (float): account balance in dollars.
    """

    #def __init__(self,  account_holder):
    #    self.holder = account_holder
    #    super().__setattr__('balance', 0)

    def __init__(self,  account_holder):
        self.holder = account_holder
        self._balance = 0

    def __str__(self):
        return self.holder + ': $' + str(self.balance)

    def __setattr__(self, name, value):
        if name == 'balance':
            print('This is a read-only attribute')
        else:
            super().__setattr__(name, value)

    #def deposit(self, amount):
    #    """
    #    deposit amount to the account
    #    Parameter:
    #    amount (float): the amount to be deposited in dollars.
    #    Returns:
    #    the updated account object
    #    """
    #    super().__setattr__('balance', self.balance + amount)
    #    return self

    def deposit(self, amount):
        """
        deposit amount to the account
        Parameter:
        amount (float): the amount to be deposited in dollars.
        Returns:
        the updated account object
        """
        self._balance += amount
        return self



    def withdraw(self, amount):
        """
        withdraw the amount from the account if possible.
 
        Parameter:
        amount (float): the amount to be withdrawn in dollars.
        Returns:
        boolean: True if the withdrawal is successful
                 False otherwise
        """
        if self.balance >= amount:
            self.balance = self.balance - amount
            return True
        else:
            return False

    @property
    def balance(self):
        """ return the current balance (float)"""
        return self._balance



class SavingsAccount(Account):
    """
    Represent a savings bank account with a withdrawal fee

    Argument:
    account_holder (str): account holder's name.

    Attributes:
    holder (str): account holder's name.
    balance (float): account balance in dollars.
    """

    fee = 1

    def withdraw(self, amount):
        """
        withdraw the amount and the fee from the account if possible.

        Parameter:
        amount (float): the amount to be withdrawn in dollars.
        Returns:
        boolean: True if the withdrawal is successful
                 False otherwise
        """
        if self.balance >= amount + self.fee:
            self.balance = self.balance - amount - self.fee
            return True
        else:
            return False


class PremiumAccount(Account):
    """
    Represent a premium interest bearing bank account.

    Argument:
    account_holder (str): account holder's name.
    rate (float): interest rate

    Attributes:
    holder (str): account holder's name.
    balance (float): account balance in dollars.
    interest_rate (float): interest rate
    """

    def __init__(self, account_holder, rate):
        self.interest_rate = rate
        super().__init__(account_holder)


class PremiumSavingsAccount(PremiumAccount, SavingsAccount):
    """
    Represent a premium interest bearing bank account with a withdrawal fee
    """
