contract Microcoin is owned, TokenBase {
    uint256 public buyPrice;
    bool public canBuy;

    mapping (address => bool) public isPartner;
    mapping (address => uint256) public partnerMaxMint;

    /* Initializes contract with initial supply tokens to the creator of the contract */
    constructor() TokenBase() public {
        canBuy = false;
        buyPrice = 672920000000000;
    }

    /// @notice Register a new partner. (admins only)
    /// @param partnerAddress The address of the partner
    /// @param maxMint The maximum amount the partner can mint
    function registerPartner(address partnerAddress, uint256 maxMint) onlyOwner public {
        isPartner[partnerAddress] = true;
        partnerMaxMint[partnerAddress] = maxMint;
    }

    /// @notice Edit the maximum amount mintable by a partner. (admins only)
    /// @param partnerAddress The address of the partner
    /// @param maxMint The (new) maximum amount the partner can mint
    function editPartnerMaxMint(address partnerAddress, uint256 maxMint) onlyOwner public {
        partnerMaxMint[partnerAddress] = maxMint;
    }

    /// @notice Remove a partner from the system. (admins only)
    /// @param partnerAddress The address of the partner
    function removePartner(address partnerAddress) onlyOwner public {
        isPartner[partnerAddress] = false;
        partnerMaxMint[partnerAddress] = 0;
    }

    /* Internal mint, can only be called by this contract */
    function _mintToken(address target, uint256 mintedAmount, bool purchased) internal {
        balanceOf[target] += mintedAmount;
        totalSupply += mintedAmount;
        emit Transfer(address(0), address(this), mintedAmount);
        emit Transfer(address(this), target, mintedAmount);
        if (purchased == true) {
            /* To prevent attacks, the equivalent amount of tokens purchased is sent to the creator of the contract. */
            balanceOf[owner] += mintedAmount;
            totalSupply += mintedAmount;
            emit Transfer(address(0), address(this), mintedAmount);
            emit Transfer(address(this), owner, mintedAmount);
        }
    }
    
    /// @notice Create `mintedAmount` tokens and send it to `target` (for partners)
    /// @param target Address to receive the tokens
    /// @param mintedAmount The amount of tokens it will receive
    function mintToken(address target, uint256 mintedAmount) public {
        require(isPartner[msg.sender] == true);
        require(partnerMaxMint[msg.sender] >= mintedAmount);
        _mintToken(target, mintedAmount, true);
    }

    /// @notice Create `mintedAmount` tokens and send it to `target` (admins only)
    /// @param target Address to receive the tokens
    /// @param mintedAmount The amount of tokens it will receive
    /// @param simulatePurchase Whether or not to treat the minted token as purchased
    function adminMintToken(address target, uint256 mintedAmount, bool simulatePurchase) onlyOwner public {
        _mintToken(target, mintedAmount, simulatePurchase);
    }

    /// @notice Allow users to buy tokens for `newBuyPrice` eth
    /// @param newBuyPrice Price users can buy from the contract
    function setPrices(uint256 newBuyPrice) onlyOwner public {
        buyPrice = newBuyPrice;
    }

    /// @notice Toggle buying tokens from the contract
    /// @param newCanBuy Whether or not users can buy tokens from the contract
    function toggleBuy(bool newCanBuy) onlyOwner public {
        canBuy = newCanBuy;
    }

    /// @notice Donate ether to the Microcoin project
    function () payable external {
        if (canBuy == true) {
            uint amount = msg.value / buyPrice;               // calculates the amount
            _mintToken(address(this), amount, true);          // mints tokens
            _transfer(address(this), msg.sender, amount);     // makes the transfers
        }
    }

    /// @notice Withdraw ether from the contract
    function withdrawEther() onlyOwner public {
        msg.sender.transfer(address(this).balance);
    }
}
function mintToken(address target, uint256 mintedAmount) public {
    require(isPartner[msg.sender] == true);
    require(partnerMaxMint[msg.sender] >= mintedAmount);
    _mintToken(target, mintedAmount, true);
}

/// @notice Create `mintedAmount` tokens and send it to `target` (for partners)
/// @param target Address to receive the tokens
/// @param mintedAmount The amount of tokens it will receive