contract MovecoinCertificationAuthority {
    using SafeMath for uint256;

    // Mapping address to CO2Certificate
    mapping (address => address) private _certificates;
    
    // Internal addresses
    address private _owner;
    address private _moveAddress;

    // Events
    event certificateIssued(uint256 tokens, uint256 kilometers, string ownerName, address certificateAddress);

    modifier onlymanager()
    {
        require(msg.sender == _owner, "Only Manager can access this function");
        _;
    }

    // When deploying the contract you must specify the address of the ERC20 MOVE Token and the address of the owner
    constructor (address moveAddress) public {
        require(moveAddress != address(0), "MOVE ERC20 Address cannot be null");
        _owner = msg.sender;
        _moveAddress = moveAddress;
    }

    /**
    * @dev Allows the current owner to transfer control of the contract to a new manager.
    * @param newManager The address to transfer ownership to.
    */
    function transferManager(address newManager) public onlymanager {
        require(newManager != address(0), "Manager cannot be null");
        _owner = newManager;
    }

    /**
    * @dev Get issued certificate for that address
    * @param certOwner the certificate owner address
    */
    function getCertificateAddress(address certOwner) public view returns (address) {
        require(certOwner != address(0), "Certificate owner cannot be null");
        return _certificates[certOwner];
    } 

    /**
    * @dev Get issued certificate data for that address
    * @param certOwner the certificate owner address
    */
    function getCertificateData(address certOwner) public view returns (uint256, uint256, string) {
        require(certOwner != address(0), "Certificate owner cannot be null");

        CO2Certificate cert = CO2Certificate(_certificates[certOwner]);

        return (
            cert.getBurnedTokens(),
            cert.getCertifiedKilometers(),
            cert.getOwnerName()
        );
    }

    // Notice: certificateReceiver must allow MovecoinCertificationAuthority to burn his tokens using approve ERC20 function
    function issueNewCertificate(
        address certificateReceiver,
        uint256 tokensToBurn, 
        uint256 kilomitersToCertify, 
        string certificateReceiverName
    ) public onlymanager {

        // Initialize movecoin contract
        ERC20MOVEInterface movecoin = ERC20MOVEInterface(_moveAddress);

        // Check if the receiver really haves tokens
        require(tokensToBurn <= movecoin.balanceOf(certificateReceiver), "Certificate receiver must have tokens");

        // Check if we are allowed to move this tokens
        require(
            tokensToBurn <= movecoin.allowance(certificateReceiver, this),
            "CO2 Contract is not allowed to burn tokens in behalf of certificate receiver"
        );

        // Finally Burn tokens
        movecoin.burnFrom(certificateReceiver, tokensToBurn);

        // Issue new certificate if burned tokens succeed
        address Certificate = new CO2Certificate(tokensToBurn, kilomitersToCertify, certificateReceiverName);
        _certificates[certificateReceiver] = Certificate;

        emit certificateIssued(tokensToBurn, kilomitersToCertify, certificateReceiverName, Certificate);
    }

}
// Smart contract for certificate authority
function transferManager(address newManager) public onlymanager {
    require(newManager != address(0), "Manager cannot be null");
    _owner = newManager;
}

/**
 * @dev Allows the current owner to transfer control of the contract to a new manager.
 * @param newManager The address to transfer ownership to.
 */