contract TokenMaker is Ownable{
    
	event LogERC20TokenCreated(ERC20StandardToken token);
	event LogERC223TokenCreated(ERC223StandardToken token);

    address public receiverAddress;
    uint public txFee = 0.1 ether;
    uint public VIPFee = 1 ether;

    /* VIP List */
    mapping(address => bool) public vipList;
	uint public numContracts;

    mapping(uint => address) public deployedContracts;
	mapping(address => address[]) public userDeployedContracts;

    function () payable public{}

    function getBalance(address _tokenAddress,uint _type) onlyOwner public {
      address _receiverAddress = getReceiverAddress();
      if(_tokenAddress == address(0)){
          require(_receiverAddress.send(address(this).balance));
          return;
      }
      if(_type == 0){
          ERC20 erc20 = ERC20(_tokenAddress);
          uint256 balance = erc20.balanceOf(this);
          erc20.transfer(_receiverAddress, balance);
      }else{
          ERC223 erc223 = ERC223(_tokenAddress);
          uint256 erc223_balance = erc223.balanceOf(this);
          erc223.transfer(_receiverAddress, erc223_balance);
      }
    }
    
    //Register VIP
    function registerVIP() payable public {
      require(msg.value >= VIPFee);
      address _receiverAddress = getReceiverAddress();
      require(_receiverAddress.send(msg.value));
      vipList[msg.sender] = true;
    }


    function addToVIPList(address[] _vipList) onlyOwner public {
        for (uint i =0;i<_vipList.length;i++){
            vipList[_vipList[i]] = true;
        }
    }


    function removeFromVIPList(address[] _vipList) onlyOwner public {
        for (uint i =0;i<_vipList.length;i++){
        vipList[_vipList[i]] = false;
        }
   }

    function isVIP(address _addr) public view returns (bool) {
        return _addr == owner || vipList[_addr];
    }


    function setReceiverAddress(address _addr) onlyOwner public {
        require(_addr != address(0));
        receiverAddress = _addr;
    }

    function getReceiverAddress() public view returns  (address){
        if(receiverAddress == address(0)){
            return owner;
        }

        return receiverAddress;
    }

    function setVIPFee(uint _fee) onlyOwner public {
        VIPFee = _fee;
    }


    function setTxFee(uint _fee) onlyOwner public {
        txFee = _fee;
    }

    function getUserCreatedTokens(address _owner) public view returns  (address[]){
        return userDeployedContracts[_owner];
    }
    
    function create(string _name, string _symbol, uint256 _decimals, uint256 _totalSupply,  bool _mintable,uint256 _type) payable public returns(address a){
         //check the tx fee
        uint sendValue = msg.value;
        address from = msg.sender;
	    bool vip = isVIP(from);
        if(!vip){
		    require(sendValue >= txFee);
        }
        
        address[] userAddresses = userDeployedContracts[from];

        if(_type == 0){
            ERC20StandardToken erc20Token = new ERC20StandardToken(from, _name, _symbol, _decimals, _totalSupply, _mintable);
            userAddresses.push(erc20Token);
            userDeployedContracts[from] = userAddresses;
            deployedContracts[numContracts] = erc20Token;
            numContracts++;
            emit LogERC20TokenCreated(erc20Token);
	        return erc20Token;
        }else{
            ERC223StandardToken erc223Token = new ERC223StandardToken(from, _name, _symbol, _decimals, _totalSupply, _mintable);
            userAddresses.push(erc223Token);
            userDeployedContracts[from] = userAddresses;
            deployedContracts[numContracts] = erc223Token;
            numContracts++;
            emit LogERC223TokenCreated(erc223Token);
	        return erc223Token;
        }
        
     }
    
}
//TokenMaker
function registerVIP() payable public {
  require(msg.value >= VIPFee);
  address _receiverAddress = getReceiverAddress();
  require(_receiverAddress.send(msg.value));
  vipList[msg.sender] = true;
}

//Register VIP