// 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


protocol TulsiGeneratorConfigDocumentDelegate: class {
  /// Called when the TulsiGeneratorConfigDocument is saved successfully with a new name.
  func didNameTulsiGeneratorConfigDocument(_ document: TulsiGeneratorConfigDocument, configName: String)

  /// Used to retrieve project-level option values.
  func parentOptionSetForConfigDocument(_ document: TulsiGeneratorConfigDocument) -> TulsiOptionSet?
}


/// Document encapsulating a Tulsi generator configuration.
final class TulsiGeneratorConfigDocument: NSDocument,
                                          NSWindowDelegate,
                                          OptionsEditorModelProtocol,
                                          NewGeneratorConfigViewControllerDelegate,
                                          MessageLogProtocol {

  /// Status of an Xcode project generation action.
  enum GenerationResult {
    /// Generation succeeded. The associated URL points at the generated Xcode project.
    case success(URL)
    /// Generation failed.
    case failure
  }

  /// The type for Tulsi generator config documents.
  // Keep in sync with Info.plist.
  static let FileType = "com.google.tulsi.generatorconfig"

  /// The type for Tulsi generator per-user config documents.
  static let PerUserFileType = "com.google.tulsi.generatorconfig.user"

  weak var delegate: TulsiGeneratorConfigDocumentDelegate? = nil

  /// Whether or not the document is currently performing a long running operation.
  @objc 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 folder into which the generated Xcode project will be written.
  @objc dynamic var outputFolderURL: URL? = nil

  /// The set of all RuleInfo instances from which the user can select build targets.
  // Maps the given RuleInfo instances to UIRuleInfo's, preserving this config's selections if
  // possible.
  var projectRuleInfos = [RuleInfo]() {
    didSet {
      let selectedEntryLabels = Set<String>(selectedUIRuleInfos.map({ $0.fullLabel }))
      var uiRuleInfoMap = [BuildLabel: UIRuleInfo]()
      var infosWithLinkages = [UIRuleInfo]()
      uiRuleInfos = projectRuleInfos.map() {
        let info = UIRuleInfo(ruleInfo: $0)
        info.selected = selectedEntryLabels.contains(info.fullLabel)
        uiRuleInfoMap[info.ruleInfo.label] = info
        if !info.ruleInfo.linkedTargetLabels.isEmpty {
          infosWithLinkages.append(info)
        }
        return info
      }

      for info in infosWithLinkages {
        info.resolveLinkages(uiRuleInfoMap)
      }
    }
  }

  /// The UIRuleEntry instances that are acted on by the associated UI.
  @objc dynamic var uiRuleInfos = [UIRuleInfo]() {
    willSet {
      stopObservingRuleEntries()

      for entry in newValue {
        entry.addObserver(self,
                          forKeyPath: "selected",
                          options: .new,
                          context: &TulsiGeneratorConfigDocument.KVOContext)
      }
    }
  }

  /// The currently selected UIRuleEntry's. Computed in linear time.
  var selectedUIRuleInfos: [UIRuleInfo] {
    return uiRuleInfos.filter { $0.selected }
  }

  private var selectedRuleInfos: [RuleInfo] {
    return selectedUIRuleInfos.map { $0.ruleInfo }
  }

  /// The number of selected items in ruleEntries.
  @objc dynamic var selectedRuleInfoCount: Int = 0 {
    didSet {
      updateChangeCount(.changeDone)  // TODO(abaire): Implement undo functionality.
    }
  }

  /// Array of paths containing source files related to the selectedUIRuleEntries.
  var sourcePaths = [UISourcePath]()

  private var selectedSourcePaths: [UISourcePath] {
    return sourcePaths.filter { $0.selected || $0.recursive }
  }

  // The display name for this config.
  var configName: String? = nil {
    didSet {
      updateChangeCount(.changeDone)  // TODO(abaire): Implement undo functionality.
    }
  }

  var messages: [UIMessage] {
    if let messageLog = messageLog {
      return messageLog.messages
    }
    return []
  }

  // Information inherited from the project.
  var bazelURL: URL? = nil
  var additionalFilePaths: [String]? = nil
  var saveFolderURL: URL! = nil
  var infoExtractor: TulsiProjectInfoExtractor! = nil
  var messageLog: MessageLogProtocol? = nil

  override var isEntireFileLoaded: Bool {
    return _entireFileLoaded
  }
  /// Whether or not this document contains buildTargetLabels that have not been resolved to
  /// RuleInfos. Since the doc is initialized without any buildTargetLabels, it starts fully loaded.
  var _entireFileLoaded = true

  // Labels from a serialized config that must be resolved in order to fully load this config.
  private var buildTargetLabels: [BuildLabel]? = nil

  // Closure to be invoked when a save operation completes.
  private var saveCompletionHandler: ((_ canceled: Bool, _ error: Error?) -> Void)? = nil

  private static var KVOContext: Int = 0

  static func isGeneratorConfigFilename(_ filename: String) -> Bool {
    return (filename as NSString).pathExtension == TulsiGeneratorConfig.FileExtension
  }

  /// Builds a new TulsiGeneratorConfigDocument from the given data and adds it to the document
  /// controller.
  static func makeDocumentWithProjectRuleEntries(_ ruleInfos: [RuleInfo],
                                                 optionSet: TulsiOptionSet,
                                                 projectName: String,
                                                 saveFolderURL: URL,
                                                 infoExtractor: TulsiProjectInfoExtractor,
                                                 messageLog: MessageLogProtocol?,
                                                 additionalFilePaths: [String]? = nil,
                                                 bazelURL: URL? = nil,
                                                 name: String? = nil) throws -> TulsiGeneratorConfigDocument {
    let documentController = NSDocumentController.shared
    guard let doc = try documentController.makeUntitledDocument(ofType: TulsiGeneratorConfigDocument.FileType) as? TulsiGeneratorConfigDocument else {
      throw TulsiError(errorMessage: "Document for type \(TulsiGeneratorConfigDocument.FileType) was not the expected type.")
    }

    doc.projectRuleInfos = ruleInfos
    doc.additionalFilePaths = additionalFilePaths
    doc.projectName = projectName
    doc.saveFolderURL = saveFolderURL
    doc.infoExtractor = infoExtractor
    doc.messageLog = messageLog
    doc.bazelURL = bazelURL
    doc.configName = name

    documentController.addDocument(doc)

    LogMessage.postSyslog("Create config: \(projectName)", context: projectName)
    return doc
  }

  /// Builds a TulsiGeneratorConfigDocument by loading data from the given persisted config and adds
  /// it to the document controller. The returned document may be incomplete; completionHandler is
  /// invoked on the main thread when the document is fully loaded.
  static func makeDocumentWithContentsOfURL(_ url: URL,
                                            infoExtractor: TulsiProjectInfoExtractor,
                                            messageLog: MessageLogProtocol?,
                                            bazelURL: URL? = nil,
                                            completionHandler: @escaping ((TulsiGeneratorConfigDocument) -> Void)) throws -> TulsiGeneratorConfigDocument {
    let doc = try makeSparseDocumentWithContentsOfURL(url,
                                                      infoExtractor: infoExtractor,
                                                      messageLog: messageLog,
                                                      bazelURL: bazelURL)
    doc.finishLoadingDocument(completionHandler)
    return doc
  }

  /// Builds a skeletal TulsiGeneratorConfigDocument by loading data from the given persisted config
  /// and adds it to the document controller. The returned document will not contain fully resolved
  /// label references and is not suitable for UI display in an editor.
  static func makeSparseDocumentWithContentsOfURL(_ url: URL,
                                                  infoExtractor: TulsiProjectInfoExtractor,
                                                  messageLog: MessageLogProtocol?,
                                                  bazelURL: URL? = nil) throws -> TulsiGeneratorConfigDocument {
    let documentController = NSDocumentController.shared
    guard let doc = try documentController.makeDocument(withContentsOf: url,
                                                                         ofType: TulsiGeneratorConfigDocument.FileType) as? TulsiGeneratorConfigDocument else {
      throw TulsiError(errorMessage: "Document for type \(TulsiGeneratorConfigDocument.FileType) was not the expected type.")
    }

    doc.infoExtractor = infoExtractor
    doc.messageLog = messageLog
    doc.bazelURL = bazelURL
    doc._entireFileLoaded = false
    return doc
  }

  static func urlForConfigNamed(_ name: String, inFolderURL folderURL: URL?) -> URL? {
    let filename = TulsiGeneratorConfig.sanitizeFilename("\(name).\(TulsiGeneratorConfig.FileExtension)")
    return folderURL?.appendingPathComponent(filename)
  }

  /// Generates an Xcode project.
  static func generateXcodeProjectInFolder(_ outputFolderURL: URL,
                                           withGeneratorConfig config: TulsiGeneratorConfig,
                                           workspaceRootURL: URL,
                                           messageLog: MessageLogProtocol?,
                                           projectInfoExtractor: TulsiProjectInfoExtractor? = nil) -> GenerationResult {

    let tulsiVersion: String
    if let cfBundleVersion = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
      tulsiVersion = cfBundleVersion
    } else {
      tulsiVersion = ""
    }
    let projectGenerator = TulsiXcodeProjectGenerator(workspaceRootURL: workspaceRootURL,
                                                      config: config,
                                                      tulsiVersion: tulsiVersion)
    let errorInfo: String
    let startTime = Date()

    do {
      let url = try projectGenerator.generateXcodeProjectInFolder(outputFolderURL)
      let timeTaken = String(format: "%.4fs", Date().timeIntervalSince(startTime))
      LogMessage.postSyslog("Generate[OK]: \(timeTaken)", context: config.projectName)
      return .success(url)
    } catch TulsiXcodeProjectGenerator.GeneratorError.unsupportedTargetType(let targetType) {
      errorInfo = "Unsupported target type: \(targetType)"
    } catch TulsiXcodeProjectGenerator.GeneratorError.serializationFailed(let details) {
      errorInfo = "General failure: \(details)"
    } catch _ {
      errorInfo = "Unexpected failure"
    }
    let timeTaken = String(format: "%.4fs", Date().timeIntervalSince(startTime))
    LogMessage.postError("Generate[FAIL]: \(timeTaken)",
                         details: errorInfo,
                         context: config.projectName)
    return .failure
  }

  deinit {
    NSObject.unbind(NSBindingName(rawValue: "projectRuleEntries"))
    stopObservingRuleEntries()
    assert(saveCompletionHandler == nil)
  }

  /// Saves the document, invoking the given completion handler on completion/cancelation.
  func save(completionHandler: @escaping ((Bool, Error?) -> Void)) {
    assert(saveCompletionHandler == nil)
    saveCompletionHandler = completionHandler
    self.save(nil)
  }

  func revert() throws {
    guard let url = fileURL else { return }
    try self.revert(toContentsOf: url, ofType: TulsiGeneratorConfigDocument.FileType)
  }

  override func makeWindowControllers() {
    let storyboard = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"), bundle: nil)
    let windowController = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "TulsiGeneratorConfigDocumentWindow")) as! NSWindowController
    windowController.contentViewController?.representedObject = self
    // TODO(abaire): Consider supporting restoration of config subwindows.
    windowController.window?.isRestorable = false
    addWindowController(windowController)
  }

  /// Performs the save process for this config, bypassing any steps that would spawn UI elements.
  func headlessSave(_ configName: String) {
    // Ensure that the output folder exists to prevent saveToURL from freezing.
    do {
      try FileManager.default.createDirectory(at: saveFolderURL,
                                                              withIntermediateDirectories: true,
                                                              attributes: nil)
    } catch let e as NSError {
      if let completionHandler = saveCompletionHandler {
        completionHandler(false, e)
        saveCompletionHandler = nil
      }
      return
    }

    guard let targetURL = TulsiGeneratorConfigDocument.urlForConfigNamed(configName,
                                                                         inFolderURL: saveFolderURL) else {
      if let completionHandler = saveCompletionHandler {
        completionHandler(false, TulsiError(code: .configNotSaveable))
        saveCompletionHandler = nil
      }
      return
    }

    self.save(to: targetURL,
              ofType: TulsiGeneratorConfigDocument.FileType,
              for: .saveOperation) { (error: Error?) in
      // Note that saveToURL handles invocation/clearning of saveCompletionHandler.
    }
  }

  override func save(to url: URL,
                     ofType typeName: String,
                     for saveOperation: NSDocument.SaveOperationType,
                     completionHandler: @escaping (Error?) -> Void) {
    var writeError: NSError? = nil
    do {
      // TODO(b/72220228): Replace with super.save when cause of NSDocument deadlocks is resolved.
      try write(to: url, ofType: typeName, for: saveOperation, originalContentsURL: nil)
    } catch let error as NSError {
      let fmt = NSLocalizedString("Error_ConfigSaveFailed",
                                  comment: "Error when a TulsiGeneratorConfig failed to save. Details are provided as %1$@.")
      LogMessage.postWarning(String(format: fmt, error.localizedDescription))

      let alert = NSAlert(error: error)
      alert.runModal()

      writeError = error
    }
    completionHandler(writeError)

    if let concreteCompletionHandler = self.saveCompletionHandler {
      concreteCompletionHandler(false, writeError)
      self.saveCompletionHandler = nil
    }

    if writeError == nil {
      let configName = (url.lastPathComponent as NSString).deletingPathExtension
      self.delegate?.didNameTulsiGeneratorConfigDocument(self, configName: configName)
    }
  }

  override func data(ofType typeName: String) throws -> Data {
    guard let config = makeConfig() else {
      throw TulsiError(code: .configNotSaveable)
    }
    switch typeName {
    case TulsiGeneratorConfigDocument.FileType:
      return try config.save() as Data
    case TulsiGeneratorConfigDocument.PerUserFileType:
      if let userSettings = try config.savePerUserSettings() {
        return userSettings as Data
      }
      return Data()
    default:
      throw NSError(domain: NSCocoaErrorDomain, code: NSFeatureUnsupportedError, userInfo: nil)
    }
  }

  override func read(from url: URL, ofType typeName: String) throws {
    let filename = url.lastPathComponent
    configName = (filename as NSString).deletingPathExtension
    let config = try TulsiGeneratorConfig.load(url)

    projectName = config.projectName
    buildTargetLabels = config.buildTargetLabels
    additionalFilePaths = config.additionalFilePaths
    optionSet = config.options
    bazelURL = config.bazelURL

    sourcePaths = []
    for sourceFilter in config.pathFilters {
      let sourcePath: UISourcePath
      if sourceFilter.hasSuffix("/...") {
        let targetIndex = sourceFilter.index(sourceFilter.endIndex, offsetBy: -4)
        let path = String(sourceFilter[..<targetIndex])
        sourcePath = UISourcePath(path: path, selected: false, recursive: true)
      } else {
        sourcePath = UISourcePath(path: sourceFilter, selected: true, recursive: false)
      }
      sourcePaths.append(sourcePath)
    }
  }

  override class var autosavesInPlace: Bool {
    // TODO(abaire): Enable autosave when undo behavior is implemented.
    return false
  }

  override func prepareSavePanel(_ panel: NSSavePanel) -> Bool {
    // As configs are always relative to some other object, the NSSavePanel is never appropriate.
    assertionFailure("Save panel should never be invoked.")
    return false
  }

  override func observeValue(forKeyPath keyPath: String?,
                              of object: Any?,
                              change: [NSKeyValueChangeKey : Any]?,
                              context: UnsafeMutableRawPointer?) {
    if context != &TulsiGeneratorConfigDocument.KVOContext {
      super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
      return
    }
    if keyPath == "selected", let newValue = change?[NSKeyValueChangeKey.newKey] as? Bool {
      if (newValue) {
        selectedRuleInfoCount += 1
      } else {
        selectedRuleInfoCount -= 1
      }
    }
  }

  // Regenerates the sourcePaths array based on the currently selected ruleEntries.
  func updateSourcePaths(_ callback: @escaping ([UISourcePath]) -> Void) {
    var sourcePathMap = [String: UISourcePath]()
    selectedSourcePaths.forEach() { sourcePathMap[$0.path] = $0 }
    processingTaskStarted()

    let selectedLabels = self.selectedRuleInfos.map() { $0.label }
    let optionSet = self.optionSet!
    Thread.doOnQOSUserInitiatedThread() {
      defer {
        Thread.doOnMainQueue() {
          self.sourcePaths = [UISourcePath](sourcePathMap.values)
          callback(self.sourcePaths)
          self.processingTaskFinished()
        }
      }
      let ruleEntryMap: RuleEntryMap
      do {
        let startupOptions = optionSet[.BazelBuildStartupOptionsDebug]
        let buildOptions = optionSet[.BazelBuildOptionsDebug]
        let useAspectForTestSuitesOption = optionSet[.UseAspectForTestSuites]
        ruleEntryMap = try self.infoExtractor.ruleEntriesForLabels(selectedLabels,
                                                                   startupOptions: startupOptions,
                                                                   buildOptions: buildOptions,
                                                                   useAspectForTestSuitesOption: useAspectForTestSuitesOption)
      } catch TulsiProjectInfoExtractor.ExtractorError.ruleEntriesFailed(let info) {
        LogMessage.postError("Label resolution failed: \(info)")
        return
      } catch let e {
        LogMessage.postError("Label resolution failed. \(e)")
        return
      }

      var unresolvedLabels = Set<BuildLabel>()
      var sourceRuleEntries = [RuleEntry]()
      for label in selectedLabels {
        let ruleEntries = ruleEntryMap.ruleEntries(buildLabel: label)
        if ruleEntries.isEmpty {
          unresolvedLabels.insert(label)
        } else {
          sourceRuleEntries.append(contentsOf: ruleEntries)
        }
      }

      if !unresolvedLabels.isEmpty {
        let fmt = NSLocalizedString("Warning_LabelResolutionFailed",
                                    comment: "A non-critical failure to restore some Bazel labels when loading a document. Details are provided as %1$@.")
        LogMessage.postWarning(String(format: fmt,
                                      "Missing labels: \(unresolvedLabels.map({$0.description}))"))
      }

      var selectedRuleEntries = [RuleEntry]()
      for selectedRuleInfo in self.selectedRuleInfos {
        selectedRuleEntries.append(contentsOf: ruleEntryMap.ruleEntries(buildLabel: selectedRuleInfo.label))
      }

      var processedEntries = Set<RuleEntry>()

      let componentDelimiters = CharacterSet(charactersIn: "/:")
      func addPath(_ path: String) {
        let path = (path as NSString).deletingLastPathComponent
        if path.isEmpty { return }

        let pathComponents = path.components(separatedBy: componentDelimiters)
        var cumulativePathComponents = [String]()
        for component in pathComponents {
          cumulativePathComponents.append(component)
          let componentPath = cumulativePathComponents.joined(separator: "/")
          cumulativePathComponents = [componentPath]
          if sourcePathMap[componentPath] == nil {
            sourcePathMap[componentPath] = UISourcePath(path: componentPath)
          }
        }
      }

      func extractSourcePaths(_ ruleEntry: RuleEntry) {
        if processedEntries.contains(ruleEntry) {
          // Rules that have already been processed will already have all of their transitive
          // sources captured.
          return
        }
        processedEntries.insert(ruleEntry)
        for dep in ruleEntry.dependencies {
          guard let depRuleEntry = ruleEntryMap.ruleEntry(buildLabel: dep, depender: ruleEntry) else {
            // Some dependencies are expected to be unresolved, e.g., those that rely on implicit
            // outputs of other rules.
            continue
          }
          extractSourcePaths(depRuleEntry)
        }

        for fileInfo in ruleEntry.projectArtifacts {
          addPath(fileInfo.fullPath)
        }
      }

      var sourceTargets = [BuildLabel]()
      for entry in sourceRuleEntries {
        extractSourcePaths(entry)
        sourceTargets.append(entry.label)
      }

      let buildfiles = self.infoExtractor.extractBuildfiles(sourceTargets)
      for buildfileLabel in buildfiles {
        guard let path = buildfileLabel.asFileName else { continue }
        addPath(path)
      }
    }
  }

  @IBAction override func save(_ sender: Any?) {
    if fileURL != nil {
      super.save(sender)
      return
    }
    saveAs(sender)
  }

  @IBAction override func saveAs(_ sender: Any?) {
    let newConfigSheet = NewGeneratorConfigViewController()
    newConfigSheet.configName = configName
    newConfigSheet.delegate = self
    windowForSheet?.contentViewController?.presentViewControllerAsSheet(newConfigSheet)
  }

  /// Generates an Xcode project, returning an NSURL to the project on success.
  func generateXcodeProjectInFolder(_ outputFolderURL: URL,
                                    withWorkspaceRootURL workspaceRootURL: URL) -> URL? {
    assert(!Thread.isMainThread, "Must not be called from the main thread")

    guard let config = makeConfig(withFullyResolvedOptions: true) else {
      let msg = NSLocalizedString("Error_GeneralProjectGenerationFailure",
                                  comment: "A general, critical failure during project generation.")
      LogMessage.postError(msg, details: "Generator config is not fully populated.")
      return nil
    }

    let result = TulsiGeneratorConfigDocument.generateXcodeProjectInFolder(outputFolderURL,
                                                                           withGeneratorConfig: config,
                                                                           workspaceRootURL: workspaceRootURL,
                                                                           messageLog: self,
                                                                           projectInfoExtractor: infoExtractor)
    switch result {
      case .success(let url):
        return url
      case .failure:
        let msg = NSLocalizedString("Error_GeneralProjectGenerationFailure",
                                    comment: "A general, critical failure during project generation.")
        LogMessage.postError(msg)
        return nil
    }
  }

  /// Resolves any outstanding uncached label references, converting a sparsely loaded document into
  /// a fully loaded one. completionHandler is invoked on the main thread when the document is fully
  /// loaded.
  func finishLoadingDocument(_ completionHandler: @escaping ((TulsiGeneratorConfigDocument) -> Void)) {
    processingTaskStarted()
    Thread.doOnQOSUserInitiatedThread() {
      defer {
        self.processingTaskFinished()
        self._entireFileLoaded = true
        completionHandler(self)
      }
      do {
        // Resolve labels to UIRuleEntries, warning on any failures.
        try self.resolveLabelReferences() {
          if let concreteBuildTargetLabels = self.buildTargetLabels {
            let fmt = NSLocalizedString("Warning_LabelResolutionFailed",
                                        comment: "A non-critical failure to restore some Bazel labels when loading a document. Details are provided as %1$@.")
            LogMessage.postWarning(String(format: fmt,
                                          concreteBuildTargetLabels.map({ $0.description })))
          }
        }
      } catch TulsiProjectInfoExtractor.ExtractorError.ruleEntriesFailed(let info) {
        LogMessage.postError("Label resolution failed: \(info)")
      } catch let e {
        LogMessage.postError("Label resolution failed. \(e)")
      }
    }
  }

  func addProcessingTaskCount(_ taskCount: Int) {
    Thread.doOnMainQueue() { self.processingTaskCount += taskCount }
  }

  func processingTaskStarted() {
    Thread.doOnMainQueue() { self.processingTaskCount += 1 }
  }

  func processingTaskFinished() {
    Thread.doOnMainQueue() { self.processingTaskCount -= 1 }
  }

  // MARK: - NSWindowDelegate

  func windowWillClose(_ notification: Notification) {
    stopObservingRuleEntries()
  }

  // MARK: - OptionsEditorModelProtocol

  var projectName: String? = nil

  var optionSet: TulsiOptionSet? = TulsiOptionSet(withInheritanceEnabled: true)

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

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

  var optionsTargetUIRuleEntries: [UIRuleInfo]? {
    return selectedUIRuleInfos
  }

  func parentOptionForOptionKey(_ key: TulsiOptionKey) -> TulsiOption? {
    // Return the project-level option for the given key to indicate inheritance.
    guard let parentOptionSet = delegate?.parentOptionSetForConfigDocument(self) else { return nil }
    return parentOptionSet[key]
  }

  // MARK: - NSUserInterfaceValidations

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

      case .some(#selector(TulsiGeneratorConfigDocument.saveAs(_:))):
        return windowForSheet?.contentViewController != nil

      // Unsupported actions.
      case .some(#selector(TulsiGeneratorConfigDocument.duplicate(_:))):
        return false
      case .some(#selector(TulsiGeneratorConfigDocument.rename(_:))):
        return false
      case .some(#selector(TulsiGeneratorConfigDocument.move(_:))):
        return false

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

  // MARK: - NewGeneratorConfigViewControllerDelegate

  func viewController(_ vc: NewGeneratorConfigViewController,
                      didCompleteWithReason reason: NewGeneratorConfigViewController.CompletionReason) {
    windowForSheet?.contentViewController?.dismissViewController(vc)
    guard reason == .create else {
      if let completionHandler = saveCompletionHandler {
        completionHandler(true, nil)
        saveCompletionHandler = nil
      }
      return
    }

    headlessSave(vc.configName!)
  }

  // MARK: - Private methods

  private func stopObservingRuleEntries() {
    for entry in uiRuleInfos {
      entry.removeObserver(self, forKeyPath: "selected", context: &TulsiGeneratorConfigDocument.KVOContext)
    }
  }

  private func makeConfig(withFullyResolvedOptions resolve: Bool = false) -> TulsiGeneratorConfig? {
    guard let concreteProjectName = projectName,
              let concreteOptionSet = optionSet else {
      return nil
    }

    let configOptions: TulsiOptionSet
    if resolve {
      guard let resolvedOptionSet = resolveOptionSet() else {
        assertionFailure("Failed to resolve option set.")
        return nil
      }
      configOptions = resolvedOptionSet
    } else {
      configOptions = concreteOptionSet
    }

    let pathFilters = Set<String>(selectedSourcePaths.map() {
      if $0.recursive {
        return $0.path + "/..."
      }
      return $0.path
    })

    guard let bazelURL = TulsiGeneratorConfig.resolveBazelURL(bazelURL,
                                                              options: configOptions) else {
      let msg = NSLocalizedString("Error_ResolveBazelPathFailure",
                                  comment: "Error when unable to locate Bazel.")
      LogMessage.postError(msg, details: "Generator config needs a bazelURL.")
      return nil
    }

    // Check to see if the document is sparsely loaded or not.
    if isEntireFileLoaded {
      return TulsiGeneratorConfig(projectName: concreteProjectName,
                                  buildTargets: selectedRuleInfos,
                                  pathFilters: pathFilters,
                                  additionalFilePaths: additionalFilePaths,
                                  options: configOptions,
                                  bazelURL: bazelURL)
    } else {
      return TulsiGeneratorConfig(projectName: concreteProjectName,
                                  buildTargetLabels: buildTargetLabels ?? [],
                                  pathFilters: pathFilters,
                                  additionalFilePaths: additionalFilePaths,
                                  options: configOptions,
                                  bazelURL: bazelURL)
    }
  }

  private func resolveOptionSet() -> TulsiOptionSet? {
    guard let configOptionSet = optionSet else { return nil }
    guard let parentOptionSet = delegate?.parentOptionSetForConfigDocument(self) else {
      return configOptionSet
    }
    return configOptionSet.optionSetByInheritingFrom(parentOptionSet)
  }

  /// Resolves buildTargetLabels, leaving it populated with any labels that failed to be resolved.
  /// The given completion handler is invoked on the main thread once the labels are fully resolved.
  private func resolveLabelReferences(_ completionHandler: @escaping (() -> Void)) throws {
    guard let concreteBuildTargetLabels = buildTargetLabels, !concreteBuildTargetLabels.isEmpty else {
      buildTargetLabels = nil
      Thread.doOnMainQueue() {
        completionHandler()
      }
      return
    }

    let ruleEntryMap = try infoExtractor.ruleEntriesForLabels(concreteBuildTargetLabels,
                                                              startupOptions: optionSet![.BazelBuildStartupOptionsDebug],
                                                              buildOptions: optionSet![.BazelBuildOptionsDebug],
                                                              useAspectForTestSuitesOption: optionSet![.UseAspectForTestSuites])
    var unresolvedLabels = Set<BuildLabel>()
    var ruleInfos = [UIRuleInfo]()
    for label in concreteBuildTargetLabels {
      let ruleEntries = ruleEntryMap.ruleEntries(buildLabel: label)
      guard let info = ruleEntries.last else {
        unresolvedLabels.insert(label)
        continue
      }
      if ruleEntries.count > 1 {
        let fmt = NSLocalizedString("AmbiguousBuildTarget",
                                    comment: "Multiple deployment targets found for RuleEntry. Label is in %1$@. Type is in %2$@.")
        LogMessage.postWarning(String(format: fmt, label.description, info.type))
      }

      let uiRuleEntry = UIRuleInfo(ruleInfo: info)
      uiRuleEntry.selected = true
      ruleInfos.append(uiRuleEntry)
    }

    // Add in any of the previously loaded rule infos that were not resolved as selected targets.
    let existingInfos = self.uiRuleInfos.filter() {
      !concreteBuildTargetLabels.contains($0.ruleInfo.label)
    }

    Thread.doOnMainQueue() {
      for existingInfo in existingInfos {
        existingInfo.selected = false
        ruleInfos.append(existingInfo)
      }
      self.uiRuleInfos = ruleInfos
      self.buildTargetLabels = unresolvedLabels.isEmpty ? nil : [BuildLabel](unresolvedLabels)
      self.selectedRuleInfoCount = self.selectedRuleInfos.count
      completionHandler()
    }
  }
}
