// Copyright 2016 The Tulsi Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import Cocoa
import TulsiGenerator


final class TulsiProjectDocument: NSDocument,
                                  NSWindowDelegate,
                                  MessageLogProtocol,
                                  OptionsEditorModelProtocol,
                                  TulsiGeneratorConfigDocumentDelegate {

  enum DocumentError: Error {
    /// No config exists with the given name.
    case noSuchConfig
    /// The config failed to load with the given debug info.
    case configLoadFailed(String)
    /// The workspace used by the project is invalid due to the given debug info.
    case invalidWorkspace(String)
  }

  /// Prefix used to access the persisted output folder for a given BUILD file path.
  static let ProjectOutputPathKeyPrefix = "projectOutput_"

  /// The subdirectory within a project bundle into which shareable generator configs will be
  /// stored.
  static let ProjectConfigsSubpath = "Configs"

  /// Override for headless project generation (in which messages should not spawn alert dialogs).
  static var showAlertsOnErrors = true

  /// Override to prevent rule entries from being extracted immediately during loading of project
  /// documents. This is only useful if the Bazel binary is expected to be set after the project
  /// document is loaded but before any other actions.
  // TODO(abaire): Refactor project loading to make this unnecessary.
  // Ideally the project document should be loaded in a sparse form and rules should be updated on
  // demand later.
  static var suppressRuleEntryUpdateOnLoad = false

  /// The project model.
  var project: TulsiProject! = nil

  /// Whether or not the document is currently performing a long running operation.
  dynamic var processing: Bool = false

  // The number of tasks that need to complete before processing is finished. May only be mutated on
  // the main queue.
  private var processingTaskCount: Int = 0 {
    didSet {
      assert(processingTaskCount >= 0, "Processing task count may never be negative")
      processing = processingTaskCount > 0
    }
  }

  /// The display names of generator configs associated with this project.
  dynamic var generatorConfigNames = [String]()

  /// Whether or not there are any opened generator config documents associated with this project.
  var hasChildConfigDocuments: Bool {
    return childConfigDocuments.count > 0
  }

  /// Documents controlling the generator configs associated with this project.
  private var childConfigDocuments = NSHashTable<AnyObject>.weakObjects()

  /// One rule per target in the BUILD files associated with this project.
  var ruleInfos: [RuleInfo] {
    return _ruleInfos
  }

  private var _ruleInfos = [RuleInfo]() {
    didSet {
      // Update the associated config documents.
      let childDocuments = childConfigDocuments.allObjects as! [TulsiGeneratorConfigDocument]
      for configDoc in childDocuments {
        configDoc.projectRuleInfos = ruleInfos
      }
    }
  }

  /// The set of Bazel packages associated with this project.
  dynamic var bazelPackages: [String]? {
    set {
      project!.bazelPackages = newValue ?? [String]()
      updateChangeCount(.changeDone)  // TODO(abaire): Implement undo functionality.
      updateRuleEntries()
    }
    get {
      return project?.bazelPackages
    }
  }

  /// Location of the bazel binary.
  dynamic var bazelURL: URL? {
    set {
      project.bazelURL = newValue
      if newValue != nil && infoExtractor != nil {
        infoExtractor.bazelURL = newValue!
      }
      updateChangeCount(.changeDone)  // TODO(abaire): Implement undo functionality.
      updateRuleEntries()
    }
    get {
      return project?.bazelURL
    }
  }

  /// Binding point for the directory containing the project's WORKSPACE file.
  dynamic var workspaceRootURL: URL? {
    return project?.workspaceRootURL
  }

  /// URL to the folder into which generator configs are saved.
  var generatorConfigFolderURL: URL? {
    return fileURL?.appendingPathComponent(TulsiProjectDocument.ProjectConfigsSubpath)
  }

  var infoExtractor: TulsiProjectInfoExtractor! = nil
  private var logEventObserver: NSObjectProtocol! = nil

  /// Array of user-facing messages, generally output by the Tulsi generator.
  dynamic var messages = [UIMessage]()

  lazy var bundleExtension: String = {
    TulsiProjectDocument.getTulsiBundleExtension()
  }()

  static func getTulsiBundleExtension() -> String {
    let bundle = Bundle(for: self)
    let documentTypes = bundle.infoDictionary!["CFBundleDocumentTypes"] as! [[String: AnyObject]]
    let extensions = documentTypes.first!["CFBundleTypeExtensions"] as! [String]
    return extensions.first!
  }

  override init() {
    super.init()
    logEventObserver = NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: TulsiMessageNotification),
                                                                               object: nil,
                                                                               queue: OperationQueue.main) {
      [weak self] (notification: Notification) in
        guard let item = LogMessage(notification: notification) else {
          return
        }
        self?.handleLogMessage(item)
    }
  }

  deinit {
    NotificationCenter.default.removeObserver(logEventObserver)
  }

  func clearMessages() {
    messages.removeAll(keepingCapacity: true)
  }

  func addBUILDFileURL(_ buildFile: URL) -> Bool {
    guard let package = packageForBUILDFile(buildFile) else {
      return false
    }
    bazelPackages!.append(package)
    return true
  }

  func containsBUILDFileURL(_ buildFile: URL) -> Bool {
    guard let package = packageForBUILDFile(buildFile),
              let concreteBazelPackages = bazelPackages else {
      return false
    }
    return concreteBazelPackages.contains(package)
  }

  func createNewProject(_ projectName: String, workspaceFileURL: URL) {
    willChangeValue(forKey: "bazelURL")
    willChangeValue(forKey: "bazelPackages")
    willChangeValue(forKey: "workspaceRootURL")

    // Default the bundleURL to a sibling of the selected workspace file.
    let bundleName = "\(projectName).\(bundleExtension)"
    let workspaceRootURL = workspaceFileURL.deletingLastPathComponent()
    let tempProjectBundleURL = workspaceRootURL.appendingPathComponent(bundleName)

    project = TulsiProject(projectName: projectName,
                           projectBundleURL: tempProjectBundleURL,
                           workspaceRootURL: workspaceRootURL)
    updateChangeCount(.changeDone)  // TODO(abaire): Implement undo functionality.

    LogMessage.postSyslog("Create project: \(projectName)")

    didChangeValue(forKey: "bazelURL")
    didChangeValue(forKey: "bazelPackages")
    didChangeValue(forKey: "workspaceRootURL")
  }

  override func writeSafely(to url: URL,
                            ofType typeName: String,
                            for saveOperation: NSSaveOperationType) throws {
    // Ensure that the project's URL is set to the location in which this document is being saved so
    // that relative paths can be set properly.
    project.projectBundleURL = url
    try super.writeSafely(to: url, ofType: typeName, for: saveOperation)
  }

  override class func autosavesInPlace() -> Bool {
    return true
  }

  override func prepareSavePanel(_ panel: NSSavePanel) -> Bool {
    panel.message = NSLocalizedString("Document_SelectTulsiProjectOutputFolderMessage",
                                      comment: "Message to show at the top of the Tulsi project save as panel, explaining what to do.")
    panel.canCreateDirectories = true
    panel.allowedFileTypes = ["com.google.tulsi.project"]
    panel.nameFieldStringValue = project.projectBundleURL.lastPathComponent
    return true
  }

  override func fileWrapper(ofType typeName: String) throws -> FileWrapper {
    let contents = [String: FileWrapper]()
    let bundleFileWrapper = FileWrapper(directoryWithFileWrappers: contents)
    bundleFileWrapper.addRegularFile(withContents: try project.save() as Data,
                                     preferredFilename: TulsiProject.ProjectFilename)

    if let perUserData = try project.savePerUserSettings() {
      bundleFileWrapper.addRegularFile(withContents: perUserData as Data,
                                       preferredFilename: TulsiProject.perUserFilename)
    }

    let configsFolder: FileWrapper
    let reachableError: NSErrorPointer = nil
    if let existingConfigFolderURL = generatorConfigFolderURL, (existingConfigFolderURL as NSURL).checkResourceIsReachableAndReturnError(reachableError) {
      // Preserve any existing config documents.
      configsFolder = try FileWrapper(url: existingConfigFolderURL,
                                        options:  FileWrapper.ReadingOptions())
    } else {
      // Add a placeholder Configs directory.
      configsFolder = FileWrapper(directoryWithFileWrappers: [:])
    }
    configsFolder.preferredFilename = TulsiProjectDocument.ProjectConfigsSubpath
    bundleFileWrapper.addFileWrapper(configsFolder)
    return bundleFileWrapper
  }

  override func read(from fileWrapper: FileWrapper, ofType typeName: String) throws {
    guard let concreteFileURL = fileURL,
              let projectFileWrapper = fileWrapper.fileWrappers?[TulsiProject.ProjectFilename],
              let fileContents = projectFileWrapper.regularFileContents else {
      return
    }

    let additionalOptionData: Data?
    if let perUserDataFileWrapper = fileWrapper.fileWrappers?[TulsiProject.perUserFilename] {
      additionalOptionData = perUserDataFileWrapper.regularFileContents
    } else {
      additionalOptionData = nil
    }
    project = try TulsiProject(data: fileContents,
                               projectBundleURL: concreteFileURL,
                               additionalOptionData: additionalOptionData)

    if let configsDir = fileWrapper.fileWrappers?[TulsiProjectDocument.ProjectConfigsSubpath],
           let configFileWrappers = configsDir.fileWrappers, configsDir.isDirectory {
      var configNames = [String]()
      for (_, fileWrapper) in configFileWrappers {
        if let filename = fileWrapper.filename, fileWrapper.isRegularFile &&
                TulsiGeneratorConfigDocument.isGeneratorConfigFilename(filename) {
          let name = (filename as NSString).deletingPathExtension
          configNames.append(name)
        }
      }

      generatorConfigNames = configNames.sorted()
    }

    // Verify that the workspace is a valid one.
    let workspaceFile = project.workspaceRootURL.appendingPathComponent("WORKSPACE",
                                                                        isDirectory: false)
    var isDirectory = ObjCBool(false)
    if !FileManager.default.fileExists(atPath: workspaceFile.path,
                                       isDirectory: &isDirectory) || isDirectory.boolValue {
      let fmt = NSLocalizedString("Error_NoWORKSPACEFile",
                                  comment: "Error when project does not have a valid Bazel WORKSPACE file at %1$@.")
      LogMessage.postError(String(format: fmt, workspaceFile.path))
      throw DocumentError.invalidWorkspace("Missing WORKSPACE file at \(workspaceFile.path)")
    }

    if !TulsiProjectDocument.suppressRuleEntryUpdateOnLoad {
      updateRuleEntries()
    }
  }

  override func makeWindowControllers() {
    let storyboard = NSStoryboard(name: "Main", bundle: nil)
    let windowController = storyboard.instantiateController(withIdentifier: "TulsiProjectDocumentWindow") as! NSWindowController
    windowController.contentViewController?.representedObject = self
    addWindowController(windowController)
  }

  override func willPresentError(_ error: Error) -> Error {
    // Track errors shown to the user for bug reporting purposes.
    LogMessage.postInfo("Presented error: \(error)", context: projectName)
    return super.willPresentError(error)
  }

  /// Tracks the given document as a child of this project.
  func trackChildConfigDocument(_ document: TulsiGeneratorConfigDocument) {
    childConfigDocuments.add(document)
    // Ensure that the child document is aware of the project-level processing tasks.
    document.addProcessingTaskCount(processingTaskCount)
  }

  /// Closes any generator config documents associated with this project.
  func closeChildConfigDocuments() {
    let childDocuments = childConfigDocuments.allObjects as! [TulsiGeneratorConfigDocument]
    for configDoc in childDocuments {
      configDoc.close()
    }
    childConfigDocuments.removeAllObjects()
  }

  func deleteConfigsNamed(_ configNamesToRemove: [String]) {
    let fileManager = FileManager.default

    var nameToDoc = [String: TulsiGeneratorConfigDocument]()
    for doc in childConfigDocuments.allObjects as! [TulsiGeneratorConfigDocument] {
      guard let name = doc.configName else { continue }
      nameToDoc[name] = doc
    }
    var configNames = Set<String>(generatorConfigNames)

    for name in configNamesToRemove {
      configNames.remove(name)
      if let doc = nameToDoc[name] {
        childConfigDocuments.remove(doc)
        doc.close()
      }
      if let url = urlForConfigNamed(name) {
        let errorInfo: String?
        do {
          try fileManager.removeItem(at: url)
          errorInfo = nil
        } catch let e as NSError {
          errorInfo = "Unexpected exception \(e.localizedDescription)"
        } catch {
          errorInfo = "Unexpected exception"
        }
        if let errorInfo = errorInfo {
          let fmt = NSLocalizedString("Error_ConfigDeleteFailed",
                                      comment: "Error when a TulsiGeneratorConfig named %1$@ could not be deleted.")
          LogMessage.postError(String(format: fmt, name), details: errorInfo)
        }
      }
    }

    generatorConfigNames = configNames.sorted()
  }

  func urlForConfigNamed(_ name: String) -> URL? {
     return TulsiGeneratorConfigDocument.urlForConfigNamed(name,
                                                           inFolderURL: generatorConfigFolderURL)
  }

  /// Asynchronously loads a previously created config with the given name, invoking the given
  /// completionHandler on the main thread when the document is fully loaded.
  func loadConfigDocumentNamed(_ name: String,
                               completionHandler: @escaping ((TulsiGeneratorConfigDocument?) -> Void)) throws -> TulsiGeneratorConfigDocument {
    let doc = try loadSparseConfigDocumentNamed(name)
    doc.finishLoadingDocument(completionHandler)
    return doc
  }

  /// Sparsely loads a previously created config with the given name. The returned document may have
  /// unresolved label references.
  func loadSparseConfigDocumentNamed(_ name: String) throws -> TulsiGeneratorConfigDocument {
    guard let configURL = urlForConfigNamed(name) else {
      throw DocumentError.noSuchConfig
    }

    let documentController = NSDocumentController.shared()
    if let configDocument = documentController.document(for: configURL) as? TulsiGeneratorConfigDocument {
      return configDocument
    }

    do {
      let configDocument = try TulsiGeneratorConfigDocument.makeSparseDocumentWithContentsOfURL(configURL,
                                                                                                infoExtractor: infoExtractor,
                                                                                                messageLog: self,
                                                                                                bazelURL: bazelURL)
      configDocument.projectRuleInfos = ruleInfos
      configDocument.delegate = self
      trackChildConfigDocument(configDocument)
      return configDocument
    } catch let e as NSError {
      throw DocumentError.configLoadFailed("Failed to load config from '\(configURL.path)' with error \(e.localizedDescription)")
    } catch {
      throw DocumentError.configLoadFailed("Unexpected exception loading config from '\(configURL.path)'")
    }
  }

  /// Displays a generic critical error message to the user with the given debug message.
  /// This should be used sparingly and only for messages that would indicate bugs in Tulsi.
  func generalError(_ debugMessage: String) {
    let msg = NSLocalizedString("Error_GeneralCriticalFailure",
                                comment: "A general, critical failure without a more fitting descriptive message.")
    LogMessage.postError(msg, details: debugMessage)
  }

  // MARK: - NSUserInterfaceValidations

  override func validateUserInterfaceItem(_ item: NSValidatedUserInterfaceItem) -> Bool {
    let itemAction = item.action
    switch itemAction {
      case .some(#selector(TulsiProjectDocument.save(_:))):
        return true
      case .some(#selector(TulsiProjectDocument.saveAs(_:))):
        return true
      case .some(#selector(TulsiProjectDocument.rename(_:))):
        return true
      case .some(#selector(TulsiProjectDocument.move(_:))):
        return true

      // Unsupported actions.
      case .some(#selector(TulsiProjectDocument.duplicate(_:))):
        // TODO(abaire): Consider implementing and allowing project duplication.
        return false

      default:
        Swift.print("Unhandled menu action: \(String(describing: itemAction))")
    }
    return false
  }

  // MARK: - TulsiGeneratorConfigDocumentDelegate

  func didNameTulsiGeneratorConfigDocument(_ document: TulsiGeneratorConfigDocument, configName: String) {
    if !generatorConfigNames.contains(configName) {
      let configNames = (generatorConfigNames + [configName]).sorted()
      generatorConfigNames = configNames
    }
  }

  func parentOptionSetForConfigDocument(_: TulsiGeneratorConfigDocument) -> TulsiOptionSet? {
    return optionSet
  }

  // MARK: - OptionsEditorModelProtocol

  var projectName: String? {
    guard let concreteProject = project else { return nil }
    return concreteProject.projectName
  }

  var optionSet: TulsiOptionSet? {
    guard let concreteProject = project else { return nil }
    return concreteProject.options
  }

  var projectValueColumnTitle: String {
    return NSLocalizedString("OptionsEditor_ColumnTitle_Project",
                             comment: "Title for the options editor column used to edit per-tulsiproj values.")
  }

  var defaultValueColumnTitle: String {
    return NSLocalizedString("OptionsEditor_ColumnTitle_Default",
                             comment: "Title for the options editor column used to display the built-in default values.")
  }

  var optionsTargetUIRuleEntries: [UIRuleInfo]? {
    return nil
  }

  // MARK: - Private methods

  private func handleLogMessage(_ item: LogMessage) {
    let fullMessage: String
    if let details = item.details {
      fullMessage = "\(item.message) [Details]: \(details)"
    } else {
      fullMessage = item.message
    }

    switch item.level {
      case .Error:
        messages.append(UIMessage(text: fullMessage, type: .error))
        if TulsiProjectDocument.showAlertsOnErrors {
          // TODO(abaire): Implement better error handling, allowing recovery of a good state.
          ErrorAlertView.displayModalError(item.message, details: item.details)
        }

      case .Warning:
        messages.append(UIMessage(text: fullMessage, type: .warning))

      case .Info:
        messages.append(UIMessage(text: fullMessage, type: .info))

      case .Syslog:
        break

      case .Debug:
        messages.append(UIMessage(text: fullMessage, type: .debug))
    }
  }

  private func processingTaskStarted() {
    Thread.doOnMainQueue() {
      self.processingTaskCount += 1
      let childDocuments = self.childConfigDocuments.allObjects as! [TulsiGeneratorConfigDocument]
      for configDoc in childDocuments {
        configDoc.processingTaskStarted()
      }
    }
  }

  private func processingTaskFinished() {
    Thread.doOnMainQueue() {
      self.processingTaskCount -= 1
      let childDocuments = self.childConfigDocuments.allObjects as! [TulsiGeneratorConfigDocument]
      for configDoc in childDocuments {
        configDoc.processingTaskFinished()
      }
    }
  }

  private func packageForBUILDFile(_ buildFile: URL) -> String? {
    let packageURL = buildFile.deletingLastPathComponent()

    // If the relative path is a child of the workspace root return it.
    if let relativePath = project.workspaceRelativePathForURL(packageURL), !relativePath.hasPrefix("/") && !relativePath.hasPrefix("..") {
      return relativePath
    }
    return nil
  }

  // Fetches target rule entries from the project's BUILD documents.
  private func updateRuleEntries() {
    guard let concreteBazelURL = bazelURL else {
      return
    }

    // TODO(abaire): Cancel any outstanding update operations.
    processingTaskStarted()
    infoExtractor = TulsiProjectInfoExtractor(bazelURL: concreteBazelURL, project: project)

    Thread.doOnQOSUserInitiatedThread() {
      let updatedRuleEntries = self.infoExtractor.extractTargetRules()
      Thread.doOnMainQueue() {
        self._ruleInfos = updatedRuleEntries
        self.processingTaskFinished()
      }
    }
  }
}


/// Convenience class for displaying an error message with an optional detail accessory view.
class ErrorAlertView: NSAlert {
  dynamic var text = ""

  static func displayModalError(_ message: String, details: String? = nil) {
    let alert = ErrorAlertView()
    alert.messageText = "\(message)\n\nA fatal error occurred. Please check the message window " +
        "and file a bug if appropriate."
    alert.alertStyle = .critical

    if let details = details {
      alert.text = details

      var views: NSArray = []
      Bundle.main.loadNibNamed("ErrorAlertDetailView",
                                         owner: alert,
                                         topLevelObjects: &views)
      // Note: topLevelObjects will contain the accessory view and an NSApplication object in a
      // non-deterministic order.
      views = views.filter() { $0 is NSView } as NSArray
      if let accessoryView = views.firstObject as? NSScrollView {
        alert.accessoryView = accessoryView
      } else {
        assertionFailure("Failed to load accessory view for error alert.")
      }
    }
    alert.runModal()
  }
}
