import { Character, Human, Droid } from "./types/backingTypes";

/**
 * Copied from GraphQL JS:
 *
 * Copyright (c) 2015-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

/**
 * This defines a basic set of data for our Star Wars Schema.
 *
 * This data is hard coded for the sake of the demo, but you could imagine
 * fetching this data from a backend service rather than from hardcoded
 * JSON objects in a more complex demo.
 */

const luke = {
  type: "Human",
  id: "1000",
  name: "Luke Skywalker",
  friends: ["1002", "1003", "2000", "2001"],
  appears_in: [4, 5, 6],
  home_planet: "Tatooine",
};

const vader = {
  type: "Human",
  id: "1001",
  name: "Darth Vader",
  friends: ["1004"],
  appears_in: [4, 5, 6],
  home_planet: "Tatooine",
};

const han = {
  type: "Human",
  id: "1002",
  name: "Han Solo",
  friends: ["1000", "1003", "2001"],
  appears_in: [4, 5, 6],
};

const leia = {
  type: "Human",
  id: "1003",
  name: "Leia Organa",
  friends: ["1000", "1002", "2000", "2001"],
  appears_in: [4, 5, 6],
  home_planet: "Alderaan",
};

const tarkin = {
  type: "Human",
  id: "1004",
  name: "Wilhuff Tarkin",
  friends: ["1001"],
  appears_in: [4],
};

const humanData = {
  "1000": luke,
  "1001": vader,
  "1002": han,
  "1003": leia,
  "1004": tarkin,
} as { [key in string]: Human };

const threepio = {
  type: "Droid",
  id: "2000",
  name: "C-3PO",
  friends: ["1000", "1002", "1003", "2001"],
  appears_in: [4, 5, 6],
  primary_function: "Protocol",
};

const artoo = {
  type: "Droid",
  id: "2001",
  name: "R2-D2",
  friends: ["1000", "1002", "1003"],
  appears_in: [4, 5, 6],
  primary_function: "Astromech",
};

const droidData = {
  "2000": threepio,
  "2001": artoo,
} as { [key in string]: Droid };

/**
 * Helper function to get a character by ID.
 */
function getCharacter(id: string) {
  // Returning a promise just to illustrate GraphQL.js's support.
  return Promise.resolve(humanData[id] || droidData[id]);
}

/**
 * Allows us to query for a character's friends.
 */
export function getFriends(character: Character) {
  // Notice that GraphQL accepts Arrays of Promises.
  return character.friends.map((id) => getCharacter(id));
}

/**
 * Allows us to fetch the undisputed hero of the Star Wars trilogy, R2-D2.
 */
export function getHero(episode?: number | null): Character {
  if (episode === 5) {
    // Luke is the hero of Episode V.
    return luke as Human;
  }
  // Artoo is the hero otherwise.
  return artoo as Droid;
}

export const allHumans = Object.keys(humanData).map((key) => humanData[key]);

/**
 * Allows us to query for the human with the given id.
 */
export function getHuman(id: string): Human {
  return humanData[id];
}

export const allDroids = Object.keys(droidData).map((key) => droidData[key]);

/**
 * Allows us to query for the droid with the given id.
 */
export function getDroid(id: string): Droid {
  return droidData[id];
}
