contract Zapper_Mail_V1 is SignatureVerifier, Ownable {
    // namehash("zappermail.eth")
    bytes32 public constant BASE_NODE =
        0x7d86dd4ef78e0b07d1796bb5c6fcdbdb0b4308455271a273703b4c86f3f9d4e6;

    EnsRegistry public registry;
    EnsResolver public resolver;
    bool public paused = false;

    event UserRegistered(
        bytes32 indexed usernameHash,
        address indexed addr,
        string username,
        string publicKey
    );
    event EmailSent(address indexed from, address indexed to, string mailHash);

    constructor(
        address _signer,
        EnsRegistry _registry,
        EnsResolver _resolver
    ) SignatureVerifier(_signer) {
        registry = _registry;
        resolver = _resolver;
    }

    modifier pausable {
        if (paused) {
            revert("Paused");
        } else {
            _;
        }
    }

    /**
     * @dev Pause or unpause the minting and creation of NFTs
     */
    function pause() external onlyOwner {
        paused = !paused;
    }

    /**
     * @dev Transfer ownership of the top ENS domain
     * @param _node - namehash of the top ENS domain
     * @param _owner - new owner for the ENS domain
     */
    function transferDomainOwnership(bytes32 _node, address _owner)
        external
        onlyOwner
    {
        registry.setOwner(_node, _owner);
    }

    /**
     * @dev Transfer resolved address of the ENS subdomain
     * @param _node - namehash of the ENS subdomain
     * @param _account - new resolved address of the ENS subdomain
     */
    function transferSubdomainAddress(bytes32 _node, address _account)
        external
    {
        require(
            registry.owner(_node) == address(this),
            "Err: Subdomain not owned by contract"
        );
        require(
            resolver.addr(_node) == tx.origin,
            "Err: Subdomain not owned by sender"
        );
        resolver.setAddr(_node, _account);
    }

    /**
     * @dev Returns the node for the subdomain specified by the username
     */
    function node(string calldata _username) public pure returns (bytes32) {
        return
            keccak256(abi.encodePacked(BASE_NODE, keccak256(bytes(_username))));
    }

    /**
     * @dev Updates to new ENS registry.
     * @param _registry The address of new ENS registry to use.
     */
    function updateRegistry(EnsRegistry _registry) external onlyOwner {
        require(registry != _registry, "Err: New registry should be different");
        registry = _registry;
    }

    /**
     * @dev Allows to update to new ENS resolver.
     * @param _resolver The address of new ENS resolver to use.
     */
    function updateResolver(EnsResolver _resolver) external onlyOwner {
        require(resolver != _resolver, "Err: New resolver should be different");
        resolver = _resolver;
    }

    /**
     * @dev Registers a username to an address, such that the address will own a subdomain of zappermail.eth
     * i.e.: If a user registers "joe", they will own "joe.zappermail.eth"
     * @param _account - Address of the new owner of the username
     * @param _node - Subdomain node to be registered
     * @param _username - Username being requested
     * @param _publicKey - The Zapper mail encryption public key for this username
     * @param _signature - Verified signature granting account the subdomain
     */
    function registerUser(
        address _account,
        bytes32 _node,
        string calldata _username,
        string calldata _publicKey,
        bytes calldata _signature
    ) external pausable {
        // Confirm that the signature matches that of the sender
        require(
            verify(_account, _publicKey, _signature),
            "Err: Invalid Signature"
        );

        // Validate that the node is valid for the given username
        require(
            node(_username) == _node,
            "Err: Node does not match ENS subdomain"
        );

        // Require that the subdomain is not already owned or owned by this registry
        require(
            registry.owner(_node) == address(0) ||
                registry.owner(_node) == address(this),
            "Err: Subdomain already owned"
        );

        // Take ownership of the subdomain and configure it
        bytes32 usernameHash = keccak256(bytes(_username));
        registry.setSubnodeOwner(BASE_NODE, usernameHash, address(this));
        registry.setResolver(_node, address(resolver));
        resolver.setAddr(_node, _account);
        registry.setOwner(_node, address(this));

        // Emit event to index users on the backend
        emit UserRegistered(usernameHash, _account, _username, _publicKey);
    }

    function sendEmail(address recipient, string calldata mailHash)
        external
        pausable
    {
        emit EmailSent(tx.origin, recipient, mailHash);
    }
}
function updateResolver(EnsResolver _resolver) external onlyOwner {
    require(resolver != _resolver, "Err: New resolver should be different");
    resolver = _resolver;
}

/**
 * @dev Allows to update to new ENS resolver.
 * @param _resolver The address of new ENS resolver to use.
 */