contract ExporoTokenFactory is Manageable {
    address public whitelist;

    /*** EVENTS ***/
    event NewTokenDeployed(address indexed contractAddress, string name, string symbol, uint8 decimals);
   
    /*** FUNCTIONS ***/
    /**
    * @dev constructor
    * @param _whitelist address of the whitelist
    */
    constructor(address _whitelist) 
        public 
        onlyValidAddress(_whitelist) {
            whitelist = _whitelist;
        }

    /**
    * @dev allows a manager to launch a new token with a new name, symbol, and decimals.
    * Defaults to using whitelist stored in this contract. If _whitelist is address(0), else it will use
    * _whitelist as the param to pass into the new token's constructor upon deployment 
    * @param _name string
    * @param _symbol string
    * @param _decimals uint8 
    * @param _initialSupply uint256 initial total supply cap
    * @param _recipient address to recieve the initial token supply
    */
    function newToken(string calldata _name, string calldata _symbol, uint8 _decimals, uint256 _initialSupply, address _recipient) 
        external 
        onlyManager 
        onlyValidAddress(_recipient)
        returns (address) {
            require(bytes(_name).length > 0, "name cannot be blank");
            require(bytes(_symbol).length > 0, "symbol cannot be blank");
            require(_initialSupply > 0, "supply cannot be 0");

            ExporoToken token = new ExporoToken(_name, _symbol, _decimals, whitelist, _initialSupply, _recipient);

            emit NewTokenDeployed(address(token), _name, _symbol, _decimals);
            
            return address(token);
        }
    
    /** MANGER FUNCTIONS **/
    /**
    * @notice Prospectus and Quarterly Reports 
    * @dev string null check is done at the token level - see ERC20DocumentRegistry
    * @param _est address of the targeted EST
    * @param _documentUri string IPFS URI to the document
    */
    function addDocument(address _est, string calldata _documentUri) external onlyValidAddress(_est) onlyManager {
        ExporoToken(_est).addDocument(_documentUri);
    }

    /**
    * @notice enable/disable whitelisting per individual EST
    * @param _est address of the targeted EST
    */
    function toggleESTWhitelist(address _est) public onlyValidAddress(_est) onlyManager {
        ExporoToken(_est).toggleWhitelist();
    }

    /**
    * @notice pause or unpause individual EST
    * @param _est address of the targeted EST
    */
    function togglePauseEST(address _est) public onlyValidAddress(_est) onlyManager {
        ExporoToken est = ExporoToken(_est);
        bool result = est.paused();
        result ? est.unpause() : est.pause();
    }

    /**
    * @notice force the transfer of tokens from _confiscatee to _receiver
    * @param _est address of the targeted EST
    * @param _confiscatee address to confiscate tokens from
    * @param _receiver address to receive the balance of tokens
    * @param _amount uint256 amount to take away from _confiscatee
    */
    function forceTransferEST(address _est, address _confiscatee, address _receiver, uint256 _amount) 
        public 
        onlyValidAddress(_est) 
        onlyValidAddress(_confiscatee)
        onlyValidAddress(_receiver)
        onlyManager {
            require(_amount > 0, "invalid amount");

            ExporoToken est = ExporoToken(_est);
            est.forceTransfer(_confiscatee, _receiver, _amount);
        }

    /**
    * @notice enable/disable Global Whitelisting
    */
    function toggleGlobalWhitelist() public onlyManager {
        GlobalWhitelist(whitelist).toggleWhitelist();
    }

    /**
    * @notice configure managers for the Global Whitelisting contract
    * @param _manager address
    * @param _active address
    */
    function whitelistSetManager(address _manager, bool _active) public onlyValidAddress(_manager) onlyManager {
        GlobalWhitelist(whitelist).setManager(_manager, _active);
    }
}
/* solhint-disable separate-by-one-line-in-contract */
function whitelistSetManager(address _manager, bool _active) public onlyValidAddress(_manager) onlyManager {
    GlobalWhitelist(whitelist).setManager(_manager, _active);
}

/**
 * @notice configure managers for the Global Whitelisting contract
 * @param _manager address
 * @param _active address
 */