contract CardTreasury is CardAuction {

  /* FUNCTIONS */
  /** PUBLIC FUNCTIONS **/
  function getTemplate(uint256 _templateId)
    external
    view
    returns (
      uint256 generation,
      uint256 category,
      uint256 variation,
      string name
    )
  {
    require(_templateId < templates.length);

    Template storage template = templates[_templateId];

    generation = template.generation;
    category = template.category;
    variation = template.variation;
    name = template.name;
  }

  function getCard(uint256 _cardId)
    external
    view
    returns (
      uint256 generation,
      uint256 category,
      uint256 variation,
      string name
    )
  {
    require(_cardId < cards.length);

    uint256 templateId = cards[_cardId];
    Template storage template = templates[templateId];

    generation = template.generation;
    category = template.category;
    variation = template.variation;
    name = template.name;
  }

  function templateIdOf(uint256 _cardId) external view returns (uint256) {
    require(_cardId < cards.length);
    return cards[_cardId];
  }

  function balanceOf(address _owner) public view returns (uint256) {
    require(_owner != address(0));
    return ownerToCardCount[_owner];
  }

  function templateSupply() external view returns (uint256) {
    return templates.length;
  }

  function totalSupply() external view returns (uint256) {
    return cards.length;
  }

  function mintLimitByTemplate(uint256 _templateId) external view returns(uint256) {
    require(_templateId < templates.length);
    return templateIdToMintLimit[_templateId];
  }

  function mintCountByTemplate(uint256 _templateId) external view returns(uint256) {
    require(_templateId < templates.length);
    return templateIdToMintCount[_templateId];
  }

  function name() external pure returns (string) {
    return "Battlebound";
  }

  function symbol() external pure returns (string) {
    return "BB";
  }

  function tokensOfOwner(address _owner) external view returns (uint256[]) {
    uint256 tokenCount = balanceOf(_owner);

    if (tokenCount == 0) {
      return new uint256[](0);
    } else {
      uint256[] memory result = new uint256[](tokenCount);
      uint256 resultIndex = 0;

      for (uint256 cardId = 0; cardId < cards.length; ++cardId) {
        if (cardIdToOwner[cardId] == _owner) {
          result[resultIndex] = cardId;
          ++resultIndex;
        }
      }

      return result;
    }
  }

  function templatesOfOwner(address _owner) external view returns (uint256[]) {
    uint256 tokenCount = balanceOf(_owner);

    if (tokenCount == 0) {
      return new uint256[](0);
    } else {
      uint256[] memory result = new uint256[](tokenCount);
      uint256 resultIndex = 0;

      for (uint256 cardId = 0; cardId < cards.length; ++cardId) {
        if (cardIdToOwner[cardId] == _owner) {
          uint256 templateId = cards[cardId];
          result[resultIndex] = templateId;
          ++resultIndex;
        }
      }

      return result;
    }
  }

  function variationsOfOwner(address _owner) external view returns (uint256[]) {
    uint256 tokenCount = balanceOf(_owner);

    if (tokenCount == 0) {
      return new uint256[](0);
    } else {
      uint256[] memory result = new uint256[](tokenCount);
      uint256 resultIndex = 0;

      for (uint256 cardId = 0; cardId < cards.length; ++cardId) {
        if (cardIdToOwner[cardId] == _owner) {
          uint256 templateId = cards[cardId];
          Template storage template = templates[templateId];
          result[resultIndex] = template.variation;
          ++resultIndex;
        }
      }

      return result;
    }
  }
}
function getTemplate(uint256 _templateId)
  external
  view
  returns (
    uint256 generation,
    uint256 category,
    uint256 variation,
    string name
  )
{
  require(_templateId < templates.length);

  Template storage template = templates[_templateId];

  generation = template.generation;
  category = template.category;
  variation = template.variation;
  name = template.name;
}

/** PUBLIC FUNCTIONS **/