text: const filterBuilder = require("./utils/filters");
  
  /**
   * Search for items on AniList
   * @since 1.7.0
   * @memberof AniList
   */
  class Search {
  	/**
  	 * @description This constructor is meant for internal use and is apart of initializing. You cannot access this
  	 * through the AniList class and are not expect to.
  	 * @param { Utilities } utilities - The AniList Utilities class.
  	 * @hideconstructor
  	 */
  	constructor(utilities) {
  		this.util = utilities;
  	}
  
  	/**
  	 * Search for a specific character
  	 * @param {String} term - Required. The term to lookup. (ie: "Myne" or "Chise Hatori")
  	 * @param {Number} page - Which page of the results to look at. Will default to 1 if not provided.
  	 * @param {Number} amount - The amount of results per page. AniList will cap this at 25 and function will default to 5 if not provided.
  	 * @return { SearchEntry }
  	 * @since 1.7.0
  	 */
  	character(term, page = 1, amount = 5) {
  		if (!term) {
  			throw new Error("Search term was not provided!");
  		}
  
  		//Validate all type conditions.
  		if (typeof term !== "string") {
  			throw new Error("Term is not a string");
  		}
  		if (typeof page !== "number") {
  			throw new Error("Page number is not a number");
  		}
  		if (typeof amount !== "number") {
  			throw new Error("Amount is not a number");
  		}
  
  		return this.util.send(
  			`query ($page: Int, $perPage: Int, $search: String) {
              Page (page: $page, perPage: $perPage) { pageInfo { total currentPage lastPage hasNextPage perPage } 
              characters (search: $search) { id name { english: full } } } }`,
  			{ search: term, page: page, perPage: amount }
  		);
  	}
  
  	/**
  	 * Search for a specific studio
  	 * @param {String} term - Required. The term to lookup. (ie: "White Fox")
  	 * @param {Number} page - Which page of the results to look at. Will default to 1 if not provided.
  	 * @param {Number} amount - The amount of results per page. AniList will cap this at 25 and function will default to 5 if not provided.
  	 * @return { SearchEntry }
  	 * @since 1.7.0
  	 */
  	studio(term, page = 1, amount = 5) {
  		if (!term) {
  			throw new Error("Search term was not provided!");
  		}
  
  		//Validate all type conditions.
  		if (typeof term !== "string") {
  			throw new Error("Term is not a string");
  		}
  		if (typeof page !== "number") {
  			throw new Error("Page number is not a number");
  		}
  		if (typeof amount !== "number") {
  			throw new Error("Amount is not a number");
  		}
  
  		return this.util.send(
  			`query ($page: Int, $perPage: Int, $search: String) {
              Page (page: $page, perPage: $perPage) { pageInfo { total currentPage lastPage hasNextPage perPage } 
              studios (search: $search) { id name } } }`,
  			{ search: term, page: page, perPage: amount }
  		);
  	}
  
  	/**
  	 * Search for a specific staff member
  	 * @param {String} term - Required. The term to lookup. (ie: "Yuka Iguchi")
  	 * @param {Number} page - Which page of the results to look at. Will default to 1 if not provided.
  	 * @param {Number} amount - The amount of results per page. AniList will cap this at 25 and function will default to 5 if not provided.
  	 * @return { SearchEntry }
  	 * @since 1.7.0
  	 */
  	staff(term, page = 1, amount = 5) {
  		if (!term) {
  			throw new Error("Search term was not provided!");
  		}
  
  		//Validate all type conditions.
  		if (typeof term !== "string") {
  			throw new Error("Term is not a string");
  		}
  		if (typeof page !== "number") {
  			throw new Error("Page number is not a number");
  		}
  		if (typeof amount !== "number") {
  			throw new Error("Amount is not a number");
  		}
  
  		return this.util.send(
  			`query ($page: Int, $perPage: Int, $search: String) {
              Page (page: $page, perPage: $perPage) { pageInfo { total currentPage lastPage hasNextPage perPage } 
              staff (search: $search) { id name { english: full } } } }`,
  			{ search: term, page: page, perPage: amount }
  		);
  	}
  
  	/**
  	 * Search for a specific user
  	 * @param {String} term - Required. The term to lookup. (ie: "Butterstroke")
  	 * @param {Number} page - Which page of the results to look at. Will default to 1 if not provided.
  	 * @param {Number} amount - The amount of results per page. AniList will cap this at 25 and function will default to 5 if not provided.
  	 * @return { SearchEntry }
  	 * @since 1.7.0
  	 */
  	user(term, page = 1, amount = 5) {
  		if (!term) {
  			throw new Error("Search term was not provided!");
  		}
  
  		//Validate all type conditions.
  		if (typeof term !== "string") {
  			throw new Error("Term is not a string");
  		}
  		if (typeof page !== "number") {
  			throw new Error("Page number is not a number");
  		}
  		if (typeof amount !== "number") {
  			throw new Error("Amount is not a number");
  		}
  
  		return this.util.send(
  			`query ($page: Int, $perPage: Int, $search: String) {
              Page (page: $page, perPage: $perPage) { pageInfo { total currentPage lastPage hasNextPage perPage } 
              users (search: $search) { id name } } }`,
  			{ search: term, page: page, perPage: amount }
  		);
  	}
  
  	/**
  	 * Search for a specific anime
  	 * @param {String} term - The term to lookup. (ie: "Log Horizon"). For no term, input a null value
  	 * @param {Object} filter - A key-value paired object to filter search data.
  	 * @param {Number} page - Which page of the results to look at. Will default to 1 if not provided.
  	 * @param {Number} amount - The amount of results per page. AniList will cap this at 25 and function will default to 5 if not provided.
  	 * @return { SearchEntry }
  	 * @since 1.7.0
  	 */
  	anime(term = null, filter = null, page = 1, amount = 5) {
  		if (term && typeof term !== "string") {
  			throw new Error("Search term is not a string");
  		}
  		if (typeof page !== "number") {
  			throw new Error("Page number is not a number");
  		}
  		if (typeof amount !== "number") {
  			throw new Error("Amount is not a number");
  		}
  
  		let query = filterBuilder("anime", filter);
  
  		query += "id title { romaji english native userPreferred } } } }";
  		return this.util.send(query, { search: term, page: page, perPage: amount });
  	}
  
  	/**
  	 * Search for a specific manga
  	 * @param {String} term - The term to lookup. (ie: "Mahoutsukai no Yome"). For no term, input a null value.
  	 * @param {Object} filter - A key-value paired object to filter search data.
  	 * @param {Number} page - Which page of the results to look at. Will default to 1 if not provided.
  	 * @param {Number} amount - The amount of results per page. AniList will cap this at 25 and function will default to 5 if not provided.
  	 * @return { SearchEntry }
  	 * @since 1.7.0
  	 */
  	manga(term = null, filter = null, page = 1, amount = 5) {
  		if (term && typeof term !== "string") {
  			throw new Error("Search term is not a string");
  		}
  		if (typeof page !== "number") {
  			throw new Error("Page number is not a number");
  		}
  		if (typeof amount !== "number") {
  			throw new Error("Amount is not a number");
  		}
  
  		let query = filterBuilder("manga", filter);
  
  		query += "id title { romaji english native userPreferred } } } }";
  		return this.util.send(query, { search: term, page: page, perPage: amount });
  	}
  
  	/**
  	 * Search for a specific activity
  	 * @param {Number} activityID - The activityID to lookup. (ie: 152876349). For no term, input a null value.
  	 * @param {Object} filter - A key-value paired object to filter search data.
  	 * @param {Number} page - Which page of the results to look at. Will default to 1 if not provided.
  	 * @param {Number} amount - The amount of results per page. AniList will cap this at 25 and function will default to 5 if not provided.
  	 * @return { ActivityEntry }
  	 * @since 1.7.0
  	 */
  	activity(activityID = null, filter = null, page = 1, amount = 5) {
  		if (activityID && typeof activityID !== "number") {
  			throw new Error("activityID is not a number.");
  		}
  		if (typeof page !== "number") {
  			throw new Error("Page number is not a number");
  		}
  		if (typeof amount !== "number") {
  			throw new Error("Amount is not a number");
  		}
  
  		let query = filterBuilder("activity", filter);
  
  		query += `... on ListActivity { id type createdAt likeCount }
          ... on TextActivity { id type createdAt likeCount }
          ... on MessageActivity { id type createdAt likeCount }}}}`;
  
  		return this.util.send(query, { id: activityID, page: page, perPage: amount });
  	}
  }
  
  module.exports = Search;
  