contract NamiMarket{
    using SafeMath for uint256;

    constructor(address _escrow, address _namiMultiSigWallet, address _namiAddress) public {
        require(_namiMultiSigWallet != 0x0);
        escrow = _escrow;
        namiMultiSigWallet = _namiMultiSigWallet;
        NamiAddr = _namiAddress;
    }

    // escrow has exclusive priveleges to call administrative
    // functions on this contract.
    address public escrow;
    uint public minWithdraw =  10**16; // 0.01 ether
    uint public maxWithdraw = 10**18; // max NAC withdraw one time, 1 ether

    // Gathered funds can be withdraw only to namimultisigwallet's address.
    address public namiMultiSigWallet;

    /// address of Nami token
    address public NamiAddr;
    bool public isPause;
    /*
    *
    * list setting function
    */
    mapping(address => bool) public isController;
    
    /**
     * 
     * List event
     */
    event Deposit(address indexed user, uint amount, uint timeDeposit);
    event Withdraw(address indexed user, uint amount, uint timeWithdraw);

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

    modifier onlyNami {
        require(msg.sender == NamiAddr);
        _;
    }

    modifier onlyNamiMultisig {
        require(msg.sender == namiMultiSigWallet);
        _;
    }
    
    modifier onlyController {
        require(isController[msg.sender] == true);
        _;
    }
    
    // change escrow
    function changeEscrow(address _escrow) public
        onlyNamiMultisig
    {
        require(_escrow != 0x0);
        escrow = _escrow;
    }
    
    // change pause
    function changePause() public
        onlyEscrow
    {
        isPause = !isPause;
    }
    
    // min and max for withdraw nac
    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 to nami multisignature wallet, only escrow can call
    /// @param _amount value ether in wei to withdraw
    function withdrawEther(uint _amount, address _to) public
        onlyEscrow
    {
        require(namiMultiSigWallet != address(0x0));
        // Available at any phase.
        if (address(this).balance > 0) {
            _to.transfer(_amount);
        }
    }


    /// @dev withdraw NAC to nami multisignature wallet, only escrow can call
    /// @param _amount value NAC to withdraw
    function withdrawNac(uint _amount) public
        onlyEscrow
    {
        require(namiMultiSigWallet != address(0x0));
        // Available at any phase.
        NamiCrowdSale namiToken = NamiCrowdSale(NamiAddr);
        if (namiToken.balanceOf(address(this)) > 0) {
            namiToken.transfer(namiMultiSigWallet, _amount);
        }
    }
    
    // set controller address
    /**
     * 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;
    }
   ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    string public name = "Nami Market";
    
    function depositEth() public payable
    {
        require(msg.value > 0);
        emit Deposit(msg.sender, msg.value, now);
    }
    
    function () public payable
    {
        depositEth();
    }
    
    function withdrawToken(address _account, uint _amount) public
        onlyController
    {
        require(_account != address(0x0) && _amount != 0);
        require(_amount >= minWithdraw && _amount <= maxWithdraw);
        if (address(this).balance > 0) {
            _account.transfer(_amount);
        }
        // emit event
        emit Withdraw(_account, _amount, now);
    }
}
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
 */