// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import Flutter
import UIKit

class ViewController: UITableViewController, BKHostBookApi {
  private var books: [BKBook] = []
  private var api: BKFlutterBookApi!
  private var editingIndex: Int = -1

  override func viewDidLoad() {
    super.viewDidLoad()
    self.navigationItem.title = "Books"
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    BKHostBookApiSetup(appDelegate.engine.binaryMessenger, self)
    api = BKFlutterBookApi.init(binaryMessenger: appDelegate.engine.binaryMessenger)
    if let url = URL(
      string: "https://www.googleapis.com/books/v1/volumes?q=greenwood+tulsa&maxResults=15")
    {
      self.loadBooks(url: url) { (newBooks) in
        if let newBooks = newBooks {
          self.books = newBooks
          self.tableView.reloadData()
        }
      }
    }
  }

  /**
   Loads a JSON file from the supplied URL, parses it and calls the callback with the array of
   parsed books on the main thread.
   */
  func loadBooks(url: URL, completion: @escaping ([BKBook]?) -> Void) {
    URLSession.shared.dataTask(with: url) { data, response, error in
      if let data = data {
        do {
          if let json = try JSONSerialization.jsonObject(with: data, options: [])
            as? [String: Any]
          {
            var newBooks: [BKBook] = []
            for item in json["items"] as! [[String: Any]] {
              let volumeInfo = item["volumeInfo"] as! [String: Any]
              let title = volumeInfo["title"] as! String
              let subtitle = volumeInfo["subtitle"] as! String?
              let authors = (volumeInfo["authors"] as! [String]).joined(separator: " & ")
              let pageCount = volumeInfo["pageCount"] as! Int32
              let publishedDate = volumeInfo["publishedDate"] as! String
              let summary = volumeInfo["description"] as! String?
              let imageLinks = volumeInfo["imageLinks"] as! [String: Any]
              let thumbnail: BKThumbnail = BKThumbnail.init()
              thumbnail.url = imageLinks["thumbnail"] as! String?
              let book: BKBook = BKBook.init()
              book.author = authors
              book.title = title
              book.subtitle = subtitle
              book.title = title
              book.pageCount = NSNumber.init(value: pageCount)
              book.publishDate = publishedDate
              book.summary = summary
              book.thumbnail = thumbnail
              newBooks.append(book)
            }
            DispatchQueue.main.async {
              completion(newBooks)
            }
          }
        } catch let error {
          print("json decode error: \(error)")
          completion(nil)
        }
      }
    }.resume()
  }

  override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.books.count
  }

  override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
    -> UITableViewCell
  {
    let cell: BookCell = self.tableView.dequeueReusableCell(withIdentifier: "BookCell") as! BookCell
    let bookInfo = books[indexPath.row]
    cell.title.text = bookInfo.title
    cell.subtitle.text = bookInfo.subtitle
    if let author = bookInfo.author {
      cell.byLine.text = "by: \(author)"
    }
    weak var weakSelf = self
    let editAction = UIAction(title: "Edit") { (action) in
      if let weakSelf = weakSelf {
        weakSelf.editItem(index: indexPath.row)
      }
    }
    cell.editButton.removeTarget(nil, action: nil, for: .allEvents)
    cell.editButton.addAction(editAction, for: UIControl.Event.touchUpInside)
    return cell
  }

  /**
   Presents the FlutterViewController that edits the book at the supplied index.
   */
  func editItem(index: Int) {
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let flutterViewController = FlutterViewController.init(
      engine: appDelegate.engine, nibName: nil, bundle: nil)
    self.editingIndex = index
    api.displayBookDetailsBook(self.books[index]) { (error) in
      if let error = error {
        print(error)
      }
    }
    self.present(flutterViewController, animated: true, completion: nil)
  }

  /**
   Called by Pigeon when the FlutterViewController is dismissed without accepting any edits.
   */
  func cancelWithError(_ error: AutoreleasingUnsafeMutablePointer<FlutterError?>) {
    self.editingIndex = -1
    self.dismiss(animated: true, completion: nil)
  }

  /**
   Called by Pigeon when edits to the book are accepted in the FlutterViewController.
   */
  func finishEditingBook(_ input: BKBook, error: AutoreleasingUnsafeMutablePointer<FlutterError?>) {
    self.books[editingIndex] = input
    self.tableView.reloadData()
    self.editingIndex = -1
    self.dismiss(animated: true, completion: nil)
  }
}