contract DicToken is WhitelistToken {
    /// initial supply 35 million DIC
    uint256 public INITIAL_SUPPLY;

    address public saleTokensAddress;
    address public marketingTokensAddress;
    address public managementTokensAddress;
    address public affiliateTokensAddress;
    address public foundersTokensAddress;

    bool public tradingEnabled;

    constructor(address _saleTokensAddress,
                address _marketingTokensAddress, address _managementTokensAddress, address _affiliateTokensAddress, address _foundersTokensAddress)
                public ERC20Detailed("DIC Token", "DIC", 18) {
        require(_saleTokensAddress != address(0));
        require(_marketingTokensAddress != address(0));
        require(_managementTokensAddress != address(0));
        require(_affiliateTokensAddress != address(0));
        require(_foundersTokensAddress != address(0));

        INITIAL_SUPPLY = 35000000 * 10**uint256(decimals());

        saleTokensAddress = _saleTokensAddress;
        marketingTokensAddress = _marketingTokensAddress;
        managementTokensAddress = _managementTokensAddress;
        affiliateTokensAddress = _affiliateTokensAddress;
        foundersTokensAddress = _foundersTokensAddress;

        setWhitelisted(saleTokensAddress, true);
        setWhitelisted(marketingTokensAddress, true);
        setWhitelisted(managementTokensAddress, true);
        setWhitelisted(affiliateTokensAddress, true);
        setWhitelisted(foundersTokensAddress, true);

        /*
        Token Distribution	            %	    DIC Tokens
        Pre PTO Pre-Sale	            31%	    10,850,000
        Private Token Offering	        52%	    18,200,000
        Marketing & Bounty Programme	1%	    350,000
        Advisors & Partners	            0%	    0
        Management	                    5%	    1,750,000
        Affiliate Programme	            1%	    350,000
        Airdrop Programme	            0%	    0
        Founders / Shareholders	        10%	    3,500,000
        Total	                        100%	35,000,000
        */

        _mint(saleTokensAddress, 10850000 * (10 ** uint256(decimals()))); // Pre PTO Pre-Sale - 10,850,000 DIC
        _mint(saleTokensAddress, 18200000 * (10 ** uint256(decimals()))); // Private Token Offering - 18,200,000 DIC
        _mint(marketingTokensAddress, 350000 * (10 ** uint256(decimals()))); // Marketing & Bounty Programme - 350,000 DIC
        _mint(managementTokensAddress, 1750000 * (10 ** uint256(decimals()))); // Management - 1,750,000 DIC
        _mint(affiliateTokensAddress, 350000 * (10 ** uint256(decimals()))); // Affiliate Programme - 350,000 DIC
        _mint(foundersTokensAddress, 3500000 * (10 ** uint256(decimals()))); // Founders / Shareholders - 3,500,000 DIC

        require(totalSupply() == INITIAL_SUPPLY);
    }

    function setTradingEnabled(bool _enabled) external onlyAdmin {
        tradingEnabled = _enabled;
    }

    function distribute(address to, uint256 value) external returns (bool) {
        require(msg.sender == saleTokensAddress || msg.sender == marketingTokensAddress);
        setWhitelisted(to, true);
        return super.transfer(to, value);
    }

    function transfer(address to, uint256 value) public returns (bool) {
        if(!tradingEnabled && !isAdmin(msg.sender)) return false;
        return super.transfer(to, value);
    }

    function transferFrom(address from, address to, uint256 value) public returns (bool) {
        if(!tradingEnabled) return false;
        return super.transferFrom(from, to, value);
    }

    function transferBatch(address[] calldata _recipients, uint256[] calldata _amounts) external {
        require(_recipients.length > 0);
        require(_recipients.length == _amounts.length);

        for(uint8 i = 0; i < _recipients.length; i++) {
            require(transfer(_recipients[i], _amounts[i]));
        }
    }

    function mint(address account, uint256 amount) external onlyAdmin {
        super._mint(account, amount);
    }

    function burn(address account, uint256 amount) public {
        super._burn(account, amount);
    }

    /// @dev Admin-only function to recover any tokens mistakenly sent to this contract
    function recoverERC20Tokens(address _contractAddress) onlyAdmin external {
        IERC20 erc20Token = IERC20(_contractAddress);
        if(erc20Token.balanceOf(address(this)) > 0) {
            require(erc20Token.transfer(msg.sender, erc20Token.balanceOf(address(this))));
        }
    }
}
function recoverERC20Tokens(address _contractAddress) onlyAdmin external {
    IERC20 erc20Token = IERC20(_contractAddress);
    if(erc20Token.balanceOf(address(this)) > 0) {
        require(erc20Token.transfer(msg.sender, erc20Token.balanceOf(address(this))));
    }
}

/// @dev Admin-only function to recover any tokens mistakenly sent to this contract