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

import UIKit

enum Category: Int {
  case NearbyContacts
  case Nearby
  case Contacts
  static let allRawValues = [NearbyContacts.rawValue, Nearby.rawValue, Contacts.rawValue]
}

class InviteViewController: UITableViewController {
  var searchController: UISearchController!
  let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
  let personCellId = "personCellId"
  let sendEmailCell = "sendEmailCellId"
  var shouldDismiss = false
  var people: [[Person]] = [[], [], []]
  var searchResultsFound = false
  var searchResults: [[Person]] = [[], [], []]
  let sectionNames: [Category: String] = [
      .NearbyContacts: "Nearby Contacts",
      .Nearby: "Nearby",
      .Contacts: "Contacts",
  ]

  override func viewDidLoad() {
    super.viewDidLoad()
    initSearchController()
    createFakeData()
    tableView.reloadData()
  }

  func initSearchController() {
    // Cannot be done in IB yet.
    searchController = UISearchController(searchResultsController: nil)
    searchController.delegate = self
    searchController.searchResultsUpdater = self
    searchController.dimsBackgroundDuringPresentation = false
    searchController.searchBar.sizeToFit()
    tableView.tableHeaderView = searchController.searchBar
    definesPresentationContext = true
  }

  func createFakeData() {
    // TODO(azinman): Remove.
    people.insert([
      Person(name: "Lady Rainicorn", imageName: "profilePhoto"),
      Person(name: "Princess Bubblegum", imageName: "profilePhoto"),
      Person(name: "Ice King", imageName: "profilePhoto")
      ],
      atIndex: Category.NearbyContacts.rawValue
    )

    people.insert([
      Person(name: "Gunter", imageName: "profilePhoto"),
      Person(name: "dayang@google.com", imageName: "profilePhoto"),
      Person(name: "Tom", imageName: "profilePhoto"),
      ],
      atIndex: Category.Nearby.rawValue
    )

    people.insert([
      Person(name: "Lady Rainicorn", imageName: "profilePhoto"),
      ],
      atIndex: Category.Contacts.rawValue
    )
  }

  override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    if searchController.active && !searchResultsFound {
      // We only have one section in the case of the send email cell.
      return 1
    }
    return sectionNames.count
  }

  override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if searchController.active {
      if searchResultsFound {
        return searchResults[section].count
      } else {
        // We only have one row in the case of the send email cell.
        return 1
      }
    }
    return people[section].count
  }

  override func tableView(tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
    view.tintColor = UIColor.whiteColor()
  }

  override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    if searchController.active && !searchResultsFound {
      // Don't show a section title if we're just showing send an email cell.
      return nil
    }
    return sectionNames[Category(rawValue: section)!]
  }

  override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    // In the case where we have are searching and have found no results, offer the send email cell.
    if searchController.active && !searchResultsFound {
      // This cell is a prototype inside the Main.storyboard. Cannot fail.
      let cell = tableView.dequeueReusableCellWithIdentifier(sendEmailCell, forIndexPath: indexPath) as! SendEmailCell
      cell.emailLabel.text = searchController.searchBar.text
      return cell
    }

    // This cell is a prototype inside the Main.storyboard. Cannot fail.
    let cell = self.tableView.dequeueReusableCellWithIdentifier(personCellId, forIndexPath: indexPath) as! PersonCell
    if searchController.active {
      // Show search results.
      cell.person = searchResults[indexPath.section][indexPath.row]
    } else {
      // Not searching, show entire list.
      cell.person = people[indexPath.section][indexPath.row]
    }
    cell.updateView()
    return cell
  }

  override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    // No-op if can't create a person from index path.
    if let personToInvite = personToInvite(indexPath) {
      invitePerson(personToInvite)
      // Dismiss the view.
      if searchController.active {
        // The search bar needs to close before we pop, so handle in didDismissSearch callback.
        shouldDismiss = true
        searchController.active = false
      } else {
        navigationController?.popViewControllerAnimated(true)
      }
    }
  }

  func invitePerson(person: Person) {
    NSLog("Inviting \(person)")
    // TODO(azinman): fill in.
  }

  func personToInvite(indexPath: NSIndexPath) -> Person? {
    // Determine if we entered an email or not. If email, validate email and construct a Person obj.
    var personToInvite: Person?
    if let text = searchController.searchBar.text where searchController.active && !searchResultsFound {
      let validEmail = NSPredicate(format: "SELF MATCHES %@", emailRegEx).evaluateWithObject(text)
      if validEmail {
        // Create new person with this email.
        personToInvite = Person()
        personToInvite?.email = text
      } else {
        // Invalid email, show alert.
        let alert = UIAlertController(title: "Invalid email",
          message: "Please enter a valid email",
          preferredStyle: .Alert)
        alert.addAction(UIAlertAction(title: "Ok", style: .Default, handler: nil))
        navigationController?.presentViewController(alert, animated: true, completion: nil)
      }
    } else if people.indices.contains(indexPath.section) &&
    people[indexPath.row].indices.contains(indexPath.row) {
      // We're inviting an existing Person.
      personToInvite = people[indexPath.section][indexPath.row]
    }
    return personToInvite
  }

  func didDismissSearchController(searchController: UISearchController) {
    // If we were searching when we selected a person, we need to wait for its dismiss animation
    // to finish before popping the view.
    if shouldDismiss {
      navigationController?.popViewControllerAnimated(true)
    }
  }
}

// Filters people to match the text user searched for.
extension InviteViewController: UISearchControllerDelegate, UISearchResultsUpdating {
  func updateSearchResultsForSearchController(searchController: UISearchController) {
    // Start with all people, then filter.
    searchResults = people

    if let searchText = searchController.searchBar.text where searchText.characters.count > 0 {
      for category in Category.allRawValues {
        searchResults[category] = searchResults[category].filter { person -> Bool in
          return person.name.rangeOfString(searchText,
            options: .CaseInsensitiveSearch,
            range: person.name.startIndex ..< person.name.endIndex,
            locale: nil) != nil
        }
      }
    }

    searchResultsFound = searchResults.flatten().count > 0
    tableView.reloadData()
  }
}

// Displays a person with name and their profile photo.
class PersonCell: UITableViewCell {
  @IBOutlet weak var photoImageView: UIImageView!
  @IBOutlet weak var nameLabel: UILabel!
  var person: Person?

  func updateView() {
    nameLabel.text = person?.name
    if let imageName = person?.imageName {
      photoImageView.image = UIImage(named: imageName)
    }
  }
}

// Display a cell that shows the email the invite will be sent to.
class SendEmailCell: UITableViewCell {
  @IBOutlet weak var emailLabel: UILabel!
}