contract BankToken is StandardToken, Ownable {

    using SafeMath for uint256;

    // Constants
    string  public constant name = "Bank Token";
    string  public constant symbol = "BANK";
    uint8   public constant decimals = 0;
    uint256 public constant INITIAL_SUPPLY      = 10000000000;
    uint256 public constant CROWDSALE_ALLOWANCE = 3000000000;
    uint256 public constant ADMIN_ALLOWANCE     = 7000000000;

    // Properties
    uint256 public crowdSaleAllowance;      // the number of tokens available for crowdsales
    uint256 public adminAllowance;          // the number of tokens available for the administrator
    address public crowdSaleAddr;           // the address of crowdsale currently selling this token
    address public adminAddr;               // the address of admin account holding the token
    bool    public transferEnabled = false; // indicates if transferring tokens is enabled or not

    // Events
    event LogTransfer(address indexed beneficiary, uint amount);

    // Modifiers
    modifier onlyWhenTransferEnabled() {
        if (!transferEnabled) {
            require(msg.sender == adminAddr || msg.sender == crowdSaleAddr);
        }
        _;
    }

    /**
     * The listed addresses are not valid recipients of tokens.
     *
     * 0x0           - the zero address is not valid
     * this          - the contract itself should not receive tokens
     * owner         - the owner has all the initial tokens, but cannot receive any back
     * adminAddr     - the admin has an allowance of tokens to transfer, but does not receive any
     * crowdSaleAddr - the crowdsale has an allowance of tokens to transfer, but does not receive any
    */
    modifier validDestination(address _to) {
        require(_to != address(0x0));
        require(_to != address(this));
        require(_to != owner);
        require(_to != address(adminAddr));
        require(_to != address(crowdSaleAddr));
        _;
    }

    /**
     * Constructor - instantiates token supply and allocates balanace of
     * to the owner (msg.sender).
     */
    constructor (address admin) public {
        // the owner is a custodian of tokens that can give an allowance of tokens for crowdsales
        // or to the admin, but cannot itself transfer tokens; hence, this requirement
        require(admin != address(0x0));

        totalSupply = INITIAL_SUPPLY;
        crowdSaleAllowance = CROWDSALE_ALLOWANCE;
        adminAllowance = ADMIN_ALLOWANCE;

        // mint all tokens
        balances[msg.sender] = totalSupply;
        emit LogTransfer(msg.sender, totalSupply);

        adminAddr = admin;
        approve(adminAddr, adminAllowance);
      
    }

    /**
     * Associates this token with a current crowdsale, giving the crowdsale
     * an allowance of tokens from the crowdsale supply. This gives the
     * crowdsale the ability to call transferFrom to transfer tokens to
     * whomever has purchased them.
     *
     * Note that if _amountForSale is 0, then it is assumed that the full
     * remaining crowdsale supply is made available to the crowdsale.
     *
     * @param _crowdSaleAddr The address of a crowdsale contract that will sell this token
     * @param _amountForSale The supply of tokens provided to the crowdsale
     */
    function setCrowdsale(address _crowdSaleAddr, uint256 _amountForSale) public onlyOwner {
        require(!transferEnabled);
        require(_amountForSale <= crowdSaleAllowance);

        // if 0, then full available crowdsale supply is assumed
        uint amount = (_amountForSale == 0) ? crowdSaleAllowance : _amountForSale;

        // Clear allowance of old values, set allowance using new ones
        approve(crowdSaleAddr, 0);
        approve(_crowdSaleAddr, amount);
        crowdSaleAddr = _crowdSaleAddr;
    }

    /**
     * Overrides ERC20 transfer function with modifier that prevents
     * ability to transfer tokens until after transfers have been enabled.
     */
    function transfer(address _to, uint256 _value) public onlyWhenTransferEnabled validDestination(_to) returns (bool) {
        //require(msg.sender==owner,'only owner can send funds');
        emit LogTransfer(_to, _value);
        return  super.transfer(_to, _value);
        //return bool;
    }

    /**
     * Overrides ERC20 transferFrom function with modifier that prevents the
     * ability to transfer tokens until after transfers have been enabled.
     * function transferFrom(address _from, address _to, uint256 _value) public onlyWhenTransferEnabled validDestination(_to) returns (bool) {
    */
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
        bool result = super.transferFrom(_from, _to, _value);
        if (result) {
            if (msg.sender == crowdSaleAddr)
                crowdSaleAllowance = crowdSaleAllowance.sub(_value);
            if (msg.sender == adminAddr)
                adminAllowance = adminAllowance.sub(_value);
        }
        return true;
    }

    function enableTransfer() public onlyOwner {
        transferEnabled = true;
    }
    
    function crowdSaleAllowance() public view returns (uint) {
        return crowdSaleAllowance;
    }



}
/**
 * The Bank Token (BANK) has a fixed supply and restricts the ability
 * to transfer tokens until the owner has called the enableTransfer()
 * function.
 *
 * The owner can associate the token with a token sale contract. In that
 * case, the token balance is moved to the token sale contract, which
 * in turn can transfer its tokens to contributors to the sale.
 */
function transfer(address _to, uint256 _value) public onlyWhenTransferEnabled validDestination(_to) returns (bool) {
        //require(msg.sender==owner,'only owner can send funds');
        emit LogTransfer(_to, _value);
        return  super.transfer(_to, _value);
        //return bool;
    }
/**
 * Overrides ERC20 transfer function with modifier that prevents
 * ability to transfer tokens until after transfers have been enabled.
 */