import {Book, Logger as DamageLogger, Librarian} from './interfaces';
import {Category} from './enums';
import {ReferenceItem, UniversityLibrarian} from './classes';
import { CalculateLateFees as CalcFee, MaxBooksAllowed }  from './lib/utilityfunctions';
import refBook from './encyclopedia';

export function GetAllBooks(): Book[] {
  const 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;
}

export 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}.`);
}

export 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;
}

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

export function CreateCustomerId(chars: string, nums: number): string {
  return chars + nums;
}

export 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;
}

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

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

// Note: no implementation.
export function GetTitles(author: string): string[];
export function GetTitles(available: boolean): string[];
// Now an implementation:
export function GetTitles(bookProperty: any): string[] {
  const allBooks = GetAllBooks();

  const foundTitles: Array<string> = [];
  if (typeof bookProperty == 'string') {
    //  get books by author, add to foundTitles
    for (let book of allBooks) {
      if (book.author === bookProperty) {
        foundTitles.push(book.title);
      }
    }
  }
  else if (typeof bookProperty === 'boolean') {
    // get available books, add to foundTitles
    for (let book of allBooks) {
      if (book.available === bookProperty) {
        foundTitles.push(book.title);
      }
    }
  }
  else {
    throw new Error('Invalid property type: ' + typeof bookProperty);
  }

  return foundTitles;
}

export function PrintBook(book: Book): void {
  console.log(`${book.title} by ${book.author}.`);
}

//******************************************************************************

function bookDemo() {
  let myBook: Book = {
    author: 'Jane Austen',
    available: true,
    category: Category.Fiction,
    // copies: 3,
    id: 5,
    pages: 250,
    title: 'Pride and prejudice',
    // year: '1813',
    markDamaged: reason => console.log(`Damaged: ${reason}.`),
  };

  PrintBook(myBook);
  myBook.markDamaged!('Torn back cover');
  let logDamage: DamageLogger = reason => console.log(`Damage reported: ${reason}.`);
  logDamage('Coffee stains');
}

function classDemo() {
  let favoriteLibrarian: Librarian = new UniversityLibrarian();
  favoriteLibrarian.name = 'Sharon';
  favoriteLibrarian.assistCustomer('Lynda');

  // let ref: ReferenceItem = new ReferenceItem('Facts and Figures', 2016);
  // ref.publisher = 'Random Data publisher';
  // ref.printItem();
  // console.log(ref.publisher);

  let Newspaper = class extends ReferenceItem {
    printCitation(): void {
      console.log(`Newspaper: ${this.title}.`);
    }
  };

  let myPaper = new Newspaper('The gazette', 2016);
  myPaper.printCitation();

  class Novel extends class { title: string } {
    mainCharacter: string;
  }
  let favoriteNovel = new Novel();
  favoriteNovel.mainCharacter = 'Hero';
  favoriteNovel.title = 'Plot';
  console.log(favoriteNovel);
}

function importDemo() {
  let fee = CalcFee(10);
  let max = MaxBooksAllowed(12);
  console.log(`Fee: ${fee}, max books: ${max}.`);

  let ref = new refBook('Fact Book', 2016, 1);
  console.log(ref);
}

false && bookDemo();
false && classDemo();
false && importDemo();