contract GeneralSecurityToken is SupportsInterfaceWithLookup, ERC721, ERC721BasicToken, Ownable {

   bytes4 private constant InterfaceId_ERC721Enumerable = 0x780e9d63;
   /**
    * 0x780e9d63 ===
    *   bytes4(keccak256('totalSupply()')) ^
    *   bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^
    *   bytes4(keccak256('tokenByIndex(uint256)'))
    */

   bytes4 private constant InterfaceId_ERC721Metadata = 0x5b5e139f;
   /**
    * 0x5b5e139f ===
    *   bytes4(keccak256('name()')) ^
    *   bytes4(keccak256('symbol()')) ^
    *   bytes4(keccak256('tokenURI(uint256)'))
    */

   // Token name
   string public name_ = "GeneralSecurityToken";

   // Token symbol
   string public symbol_ = "GST";
  
   uint public tokenIDCount = 0;

   // Mapping from owner to list of owned token IDs
   mapping(address => uint256[]) internal ownedTokens;

   // Mapping from token ID to index of the owner tokens list
   mapping(uint256 => uint256) internal ownedTokensIndex;

   // Array with all token ids, used for enumeration
   uint256[] internal allTokens;

   // Mapping from token id to position in the allTokens array
   mapping(uint256 => uint256) internal allTokensIndex;

   // Optional mapping for token URIs
   mapping(uint256 => string) internal tokenURIs;

   struct Data{
       string information;
       string URL;
   }
  
   mapping(uint256 => Data) internal tokenData;
   /**
    * @dev Constructor function
    */
   constructor() public {


       // register the supported interfaces to conform to ERC721 via ERC165
       _registerInterface(InterfaceId_ERC721Enumerable);
       _registerInterface(InterfaceId_ERC721Metadata);
   }

   /**
    * @dev External function to mint a new token
    * @dev Reverts if the given token ID already exists
    * @param _to address the beneficiary that will own the minted token
    */
   function mint(address _to) external onlyManager {
       _mint(_to, tokenIDCount++);
   }

   /**
    * @dev Gets the token name
    * @return string representing the token name
    */
   function name() external view returns (string) {
       return name_;
   }

   /**
    * @dev Gets the token symbol
    * @return string representing the token symbol
    */
   function symbol() external view returns (string) {
       return symbol_;
   }

   function arrayOfTokensByAddress(address _holder) public view returns(uint256[]) {
       return ownedTokens[_holder];
   }

   /**
    * @dev Returns an URI for a given token ID
    * @dev Throws if the token ID does not exist. May return an empty string.
    * @param _tokenId uint256 ID of the token to query
    */
   function tokenURI(uint256 _tokenId) public view returns (string) {
       require(exists(_tokenId));
       return tokenURIs[_tokenId];
   }

   /**
    * @dev Gets the token ID at a given index of the tokens list of the requested owner
    * @param _owner address owning the tokens list to be accessed
    * @param _index uint256 representing the index to be accessed of the requested tokens list
    * @return uint256 token ID at the given index of the tokens list owned by the requested address
    */
   function tokenOfOwnerByIndex(address _owner, uint256 _index) public view returns (uint256) {
       require(_index < balanceOf(_owner));
       return ownedTokens[_owner][_index];
   }

   /**
    * @dev Gets the total amount of tokens stored by the contract
    * @return uint256 representing the total amount of tokens
    */
   function totalSupply() public view returns (uint256) {
       return allTokens.length;
   }

   /**
    * @dev Gets the token ID at a given index of all the tokens in this contract
    * @dev Reverts if the index is greater or equal to the total number of tokens
    * @param _index uint256 representing the index to be accessed of the tokens list
    * @return uint256 token ID at the given index of the tokens list
    */
   function tokenByIndex(uint256 _index) public view returns (uint256) {
       require(_index < totalSupply());
       return allTokens[_index];
   }

   /**
    * @dev Internal function to set the token URI for a given token
    * @dev Reverts if the token ID does not exist
    * @param _tokenId uint256 ID of the token to set its URI
    * @param _uri string URI to assign
    */
   function _setTokenURI(uint256 _tokenId, string _uri) internal {
       require(exists(_tokenId));
       tokenURIs[_tokenId] = _uri;
   }

   /**
    * @dev Internal function to add a token ID to the list of a given address
    * @param _to address representing the new owner of the given token ID
    * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address
    */
   function addTokenTo(address _to, uint256 _tokenId) internal {
       super.addTokenTo(_to, _tokenId);
       uint256 length = ownedTokens[_to].length;
       ownedTokens[_to].push(_tokenId);
       ownedTokensIndex[_tokenId] = length;
   }

   /**
    * @dev Internal function to remove a token ID from the list of a given address
    * @param _from address representing the previous owner of the given token ID
    * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address
    */
   function removeTokenFrom(address _from, uint256 _tokenId) internal {
       super.removeTokenFrom(_from, _tokenId);

       uint256 tokenIndex = ownedTokensIndex[_tokenId];
       uint256 lastTokenIndex = ownedTokens[_from].length.sub(1);
       uint256 lastToken = ownedTokens[_from][lastTokenIndex];

       ownedTokens[_from][tokenIndex] = lastToken;
       ownedTokens[_from][lastTokenIndex] = 0;
       // Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are
       // going to be zero. Then we can make sure that we will remove _tokenId from the ownedTokens list since we are
       // first swapping the lastToken to the first position, and then dropping the element placed in the last
       // position of the list

       ownedTokens[_from].length--;
       ownedTokensIndex[_tokenId] = 0;
       ownedTokensIndex[lastToken] = tokenIndex;
   }

   /**
    * @dev Internal function to mint a new token
    * @dev Reverts if the given token ID already exists
    * @param _to address the beneficiary that will own the minted token
    */
   function _mint(address _to, uint256 _id) internal {
       allTokens.push(_id);
       allTokensIndex[_id] = _id;
       super._mint(_to, _id);
   }
  
   function addTokenData(uint _tokenId, string _information, string _URL) public {
           require(ownerOf(_tokenId) == msg.sender);
           tokenData[_tokenId].information = _information;
           tokenData[_tokenId].URL = _URL;

      
   }
  
   function getTokenData(uint _tokenId) public view returns(string Liscence, string URL){
       require(exists(_tokenId));
       Liscence = tokenData[_tokenId].information;
       URL = tokenData[_tokenId].URL;
   }
  
   function() payable{
       require(msg.value > 0.16 ether);
       _mint(msg.sender, tokenIDCount++);
   }
}
/**
 * @title Full ERC721 Token
 * This implementation includes all the required and some optional functionality of the ERC721 standard
 * Moreover, it includes approve all functionality using operator terminology
 * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
 */
function totalSupply() public view returns (uint256) {
    return allTokens.length;
}

/**
 * @dev Gets the total amount of tokens stored by the contract
 * @return uint256 representing the total amount of tokens
 */