contract JarvisExchange {
    using SafeMath for uint256;

    constructor(address _escrow) public {
        require(_escrow != address(0));
        escrow = _escrow;
        
        // init token
        // DAI
        TokenAddress[1] = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
    }

    // escrow has exclusive priveleges to call administrative
    // functions on this contract.
    address public escrow;
    uint public minWithdraw = 1 * 10**16;
    uint public maxWithdraw = 1000000 * 10**18;
    
    // Token Address
    mapping(uint256 => address) public TokenAddress;


    /**
    * list setting function
    */
    mapping(address => bool) public isController;

    /**
     * List event
     */
    event Withdraw(address indexed user, uint amount, uint timeWithdraw, uint tokenIndex);

    modifier onlyEscrow() {
        require(msg.sender == escrow);
        _;
    }

    modifier onlyController {
        require(isController[msg.sender] == true);
        _;
    }

    
    /**
     * Admin function
     */
    function() external payable {}
    function changeEscrow(address _escrow) public
    onlyEscrow
    {
        require(_escrow != address(0));
        escrow = _escrow;
    }

    function changeMinWithdraw(uint _minWithdraw) public
    onlyEscrow
    {
        require(_minWithdraw != 0);
        minWithdraw = _minWithdraw;
    }

    function changeMaxWithdraw(uint _maxNac) public
    onlyEscrow
    {
        require(_maxNac != 0);
        maxWithdraw = _maxNac;
    }

    /// @dev withdraw ether, only escrow can call
    /// @param _amount value ether in wei to withdraw
    function withdrawEther(uint _amount, address payable _to) public
    onlyEscrow
    {
        require(_to != address(0x0));
        // Available at any phase.
        if (address(this).balance > 0) {
            _to.transfer(_amount);
        }
    }

    /**
     * make new controller
     * require input address is not a controller
     * execute any time in sc state
     */
    function setController(address _controller)
    public
    onlyEscrow
    {
        require(!isController[_controller]);
        isController[_controller] = true;
    }

    /**
     * remove controller
     * require input address is a controller
     * execute any time in sc state
     */
    function removeController(address _controller)
    public
    onlyEscrow
    {
        require(isController[_controller]);
        isController[_controller] = false;
    }
    
    /**
     * update token address
     */
    function updateTokenAddress(address payable _tokenAddress, uint _tokenIndex) public
    onlyEscrow
    {
        require(_tokenAddress != address(0));
        TokenAddress[_tokenIndex] = _tokenAddress;
    }


    function withdrawToken(address _account, uint _amount, uint _tokenIndex) public
    onlyController
    {
        require(_account != address(0x0) && _amount != 0);
        require(_amount >= minWithdraw && _amount <= maxWithdraw);
        
        // check valid token index
        require(TokenAddress[_tokenIndex] != address(0));
        EIP20 ERC20Token = EIP20(TokenAddress[_tokenIndex]);
        if (ERC20Token.balanceOf(address(this)) >= _amount) {
            ERC20Token.transfer(_account, _amount);
        } else {
            revert();
        }
        // emit event
        emit Withdraw(_account, _amount, now, _tokenIndex);
    }
}
function removeController(address _controller)
public
onlyEscrow
{
    require(isController[_controller]);
    isController[_controller] = false;
}

/**
 * remove controller
 * require input address is a controller
 * execute any time in sc state
 */