contract CryptoHandles is ERC721Token {

    address public owner;
    uint256 public defaultBuyNowPrice = 100 finney;
    uint256 public defaultAuctionPrice = 1 ether;
    uint256 public defaultAuctionDuration = 1 days;

    AuctionHouse public auctions;

    mapping (uint => bytes32) handles;
    mapping (bytes32 => uint) reverse;

    event SetRecord(bytes32 indexed handle, string indexed key, string value);

    function CryptoHandles(address auctionAddress) {
      owner = msg.sender;
      auctions = AuctionHouse(auctionAddress);
    }

    /**
    * @dev Change owner of the contract
    */
    function changeOwner(address newOwner) external {
      require(msg.sender == owner);
      owner = newOwner;
    }

    /**
    * @dev Withdraw funds
    */
    function withdraw() external {
      require(msg.sender == owner);
      owner.transfer(this.balance);
    }

    /**
    * @dev Set buy now price
    */
    function setBuyNowPrice(uint price) external {
      require(msg.sender == owner);
      defaultBuyNowPrice = price;
    }

    /**
    * @dev Set buy now price
    */
    function setAuctionPrice(uint price) external {
      require(msg.sender == owner);
      defaultAuctionPrice = price;
    }

    /**
    * @dev Set duration
    */
    function setAuctionDuration(uint duration) external {
      require(msg.sender == owner);
      defaultAuctionDuration = duration;
    }

    /**
    * @dev Accept proceeds from auction sales
    */
    function() public payable {}

    /**
    * @dev Create a new handle if the handle is valid and not owned
    * @param _handle bytes32 handle to register
    */
    function create(bytes32 _handle) external payable {
        require(isHandleValid(_handle));
        require(isHandleAvailable(_handle));
        uint _tokenId = totalTokens;
        handles[_tokenId] = _handle;
        reverse[_handle] = _tokenId;

        // handle buy now
        if (msg.value == defaultBuyNowPrice) {
          _mint(msg.sender, _tokenId);
        } else {
          // otherwise start an auction
          require(msg.value == 0);
          // mint the token to the address
          _mint(address(auctions), _tokenId);
          auctions.createAuction(
              address(this),
              _tokenId,
              defaultAuctionPrice,
              0,
              defaultAuctionDuration,
              address(this)
          );
        }
    }

    /**
    * @dev Checks if a handle is valid: a-z, 0-9, _
    * @param _handle bytes32 to check validity
    */
    function isHandleValid(bytes32 _handle) public pure returns (bool) {
        if (_handle == 0x0) {
            return false;
        }
        bool padded;
        for (uint i = 0; i < 32; i++) {
            byte char = byte(bytes32(uint(_handle) * 2 ** (8 * i)));
            // null for padding
            if (char == 0x0) {
                padded = true;
                continue;
            }
            // numbers 0-9
            if (char >= 0x30  && char <= 0x39 && !padded) {
                continue;
            }
            // lowercase letters a-z
            if (char >= 0x61  && char <= 0x7A && !padded) {
                continue;
            }
            // underscores _
            if (char == 0x5F && !padded) {
                continue;
            }
            return false;
        }
        return true;
    }

    /**
    * @dev Checks if a handle is available
    * @param _handle bytes32 handle to check availability
    */
    function isHandleAvailable(bytes32 _handle) public view returns (bool) {
        // Get the tokenId for a given handle
        uint tokenId = reverse[_handle];
        if (handles[tokenId] != _handle) {
          return true;
        }
    }

    /**
    * @dev Approve the AuctionHouse and start an auction
    * @param _tokenId uint256
    * @param _startingPrice uint256
    * @param _endingPrice uint256
    * @param _duration uint256
    */
    function approveAndAuction(uint256 _tokenId, uint256 _startingPrice, uint256 _endingPrice, uint256 _duration) external {
        require(ownerOf(_tokenId) == msg.sender);
        tokenApprovals[_tokenId] = address(auctions);
        auctions.createAuction(
            address(this),
            _tokenId,
            _startingPrice,
            _endingPrice,
            _duration,
            msg.sender
        );
    }

    /**
    * @dev Get tokenId for a given handle
    * @param _handle bytes32 handle
    */
    function tokenIdForHandle(bytes32 _handle) public view returns (uint) {
        // Handle 0 index
        uint tokenId = reverse[_handle];
        require(handles[tokenId] == _handle);
        return tokenId;
    }

    /**
    * @dev Get handle for a given tokenId
    * @param _tokenId uint
    */
    function handleForTokenId(uint _tokenId) public view returns (bytes32) {
        bytes32 handle = handles[_tokenId];
        require(handle != 0x0);
        return handle;
    }

    /**
    * @dev Get the handle owner
    * @param _handle bytes32 handle to check availability
    */
    function getHandleOwner(bytes32 _handle) public view returns (address) {
        // Handle 0 index
        uint tokenId = reverse[_handle];
        require(handles[tokenId] == _handle);
        return ownerOf(tokenId);
    }

    /// Records for a handle
    mapping(bytes32 => mapping(string => string)) internal records;

    function setRecord(bytes32 _handle, string _key, string _value) external {
        uint tokenId = reverse[_handle];
        require(ownerOf(tokenId) == msg.sender);
        records[_handle][_key] = _value;
        SetRecord(_handle, _key, _value);
    }

    function getRecord(bytes32 _handle, string _key) external view returns (string) {
        return records[_handle][_key];
    }
}
function() public payable {}
/**
 * @dev Accept proceeds from auction sales
 */