// 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 explicit tests for the presence of a WORKSPACE file. This is only useful
  /// in cases where Bazel will be invoked in such a way that the WORKSPACE file does not need to be
  /// available locally (e.g., in a remote-build scenario).
  static var suppressWORKSPACECheck = false

  /// 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)
    updateRuleEntries()
    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.
    if !TulsiProjectDocument.suppressWORKSPACECheck {
      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) {
    guard let configName = document.configName else { return }
    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
    }
  }

  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()
  }
}
