enum Category {
  Biography,     // 0
  Poetry,        // 1
  Fiction,       // 2
}

let books: ({ author: string; available: boolean; category: Category; id: number; title: string })[] = [];

function GetAllBooks() {
  if (books.length < 4) {
    books = [
      {
        author: 'James Joyce',
        available: true,
        category: Category.Fiction,
        id: 1,
        title: 'Ulysses',
      },
      {
        author: 'Ernest Hemingway',
        available: false,
        category: Category.Fiction,
        id: 2,
        title: 'A farewall to arms',
      },
      {
        author: 'Maya Angelou',
        available: true,
        category: Category.Poetry,
        id: 3,
        title: 'I know why the caged bird sings',
      },
      {
        author: 'Herman Melville',
        available: true,
        category: Category.Fiction,
        id: 4,
        title: 'Moby Dick',
      }
    ];
  }

  return books;
}

function LogFirstAvailable(books = GetAllBooks()): void {

  const numberOfBooks: number = books.length;
  let firstAvailable: string = '';
  for (let currentBook of books) {
    if (currentBook.available) {
      firstAvailable = currentBook.title;
      break;
    }
  }

  console.log(`Total number of books: ${numberOfBooks}.`);
  console.log(`First available: ${firstAvailable}.`);
}

function CheckoutBooks(customer: string, ...bookIds: number[]): string[] {
  console.log(`Checking out books for ${customer}.`);

  let booksCheckedOut: string[] = [];
  for (let id of bookIds) {
    let book = GetBookById(id);
    if (book.available) {
      booksCheckedOut.push(book.title);
    }
  }

  return booksCheckedOut;
}

function CreateCustomer(name: string, age?: number, city?: string) {
  console.log(`Name: ${name}.`);
  if (age) {
    console.log(`Age: ${age}.`);
  }
  if (city) {
    console.log(`City: ${city}.`);
  }
}

function CreateCustomerId(name: string, id: number): string {
  return name + id;
}

function GetBookTitlesByCategory(categoryFilter: Category = Category.Fiction): Array<string> {
  console.log(`Getting books in category: ${Category[categoryFilter]}.`);

  const allBooks = GetAllBooks();
  const filteredTitles: string[] = [];

  for (let currentBook of allBooks) {
    if (currentBook.category === categoryFilter) {
      filteredTitles.push(currentBook.title);
    }
  }
  return filteredTitles;
}

function GetBookById(id: number) {
  const allBooks = GetAllBooks();
  return allBooks.filter(book => book.id === id)[0];
}

function LogBookTitles(titles: string[]): void {
  for (let title of titles) {
    console.log(title);
  }
}

//******************************************************************************
function defaultParamsDemo() {
  CreateCustomer('Michelle');
  CreateCustomer('Leigh', 6);
  CreateCustomer('Marie', 12, 'Atlanta');
}

function functionTypeDemos() {
  let idGenerator: (chars: string, nums: number) => string;
  idGenerator = CreateCustomerId;

  let myID: string = idGenerator('Daniel', 10);
  console.log(myID);

  idGenerator = (name, id) => id + name;
  myID = idGenerator('Daniel', 10);
  console.log(myID);
}

// const fictionBookTitles = GetBookTitlesByCategory(Category.Fiction);
// fictionBookTitles.forEach((val, idx, arr) => console.log(`${++idx} ${val}.`));
// let poetryBookTitles = GetBookTitlesByCategory();
// console.log(poetryBookTitles);

function functionCallDefaultParamsDemo() {
  console.log("Book count:", books.length);
  books.unshift({
    author: "Anon1",
    available: true,
    category: Category.Biography,
    id: 42,
    title: "Added1",
  });
  console.log("Book count:", books.length);
  LogFirstAvailable();
  books.unshift({
    author: "Anon2",
    available: true,
    category: Category.Biography,
    id: 42,
    title: "Added2",
  });
  console.log("Book count:", books.length);
  // Default is now 5: it is evaluated on each call.
  LogFirstAvailable();
}

function restParamsDemo() {
  let myBooks = CheckoutBooks('Ripper', 1, 2, 3, 4);
  myBooks.forEach(title => console.log(title);
}


// defaultParamsDemo();
// functionTypeDemos();
// functionCallDefaultParamsDemo();
restParamsDemo();