contract Hedgie is ERC721Token, Ownable {
    /**
     * This is the total number of hex colors
     */
    uint256 internal _totalColors = 16777216;

    /**
     * This is the base URI for hedgie data
     */
    string public tokenURIPrefix = "https://api.hedgie.io/api/v2/hedgies/metas/";

    mapping (address => uint) internal approvedAddressIndexes;
    address[] internal approvedAddresses;

    constructor() ERC721Token("Hedgie", "HDG") public {
    }

    /**
    * @dev Mints a token to an address
    * @param _to address of the future owner of the token
    * @param _tokenId the ID of the token to mint
    */
    function mintTo(address _to, uint256 _tokenId) public onlyApprovedAddresses {
        require(_tokenId < _totalColors);
        _mint(_to, _tokenId);
    }


    function setTokenURIPrefix(string newPrefix) external onlyOwner {
        tokenURIPrefix = newPrefix;
    }

    function tokenURI(uint256 _tokenId) public view returns (string) {
        require(exists(_tokenId));

        string memory tokenIDString = Util.uint2str(uint(_tokenId));
        return Util.strConcat(tokenURIPrefix, tokenIDString);
    }

    function tokensOf(address _owner) public view returns (uint256[]){
        return ownedTokens[_owner];
    }

    /**
    * @dev Throws if called by any account other than the owner.
    */
    modifier onlyApprovedAddresses() {
        require(approvedAddressIndexes[msg.sender] != 0 || msg.sender == owner);
        _;
    }

    function addApprovedAddress(address newAddress) public onlyOwner {
        require(approvedAddressIndexes[newAddress] == 0);
        approvedAddresses.push(newAddress);
        approvedAddressIndexes[newAddress] = approvedAddresses.length;
    }

    function removeApprovedAddress(address addressToRemove) public onlyOwner {
        require(approvedAddressIndexes[addressToRemove] != 0);

        // delete it from array and from map
        uint i = approvedAddressIndexes[addressToRemove] - 1;
    
        // replace the slot if there are more items
        if (approvedAddresses.length > 1) {
            approvedAddresses[i] = approvedAddresses[approvedAddresses.length - 1];
            approvedAddressIndexes[approvedAddresses[i]] = i + 1;
        }

        delete approvedAddressIndexes[addressToRemove];
        approvedAddresses.length--;
    }

    function removeAllApprovedAddresses() public onlyOwner {
        for (uint i = approvedAddresses.length; i > 0; i--) {
            address toRemove = approvedAddresses[i - 1];
            delete approvedAddressIndexes[toRemove];
            approvedAddresses.length--;
        }
    }

    function getApprovedAddresses() public view onlyOwner returns (address[]) {
        return approvedAddresses;
    }
}
function mintTo(address _to, uint256 _tokenId) public onlyApprovedAddresses {
    require(_tokenId < _totalColors);
    _mint(_to, _tokenId);
}

/**
 * @dev Mints a token to an address
 * @param _to address of the future owner of the token
 * @param _tokenId the ID of the token to mint
 */