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


/// View controller for the editor that allows management of Generator Configs associated with a
/// project.
final class ProjectEditorConfigManagerViewController: NSViewController {

  /// Indices into the Add/Remove/Action SegmentedControl (as built by Interface Builder).
  private enum SegmentedControlButtonIndex: Int {
    case add = 0
    case remove = 1
    case action = 2
  }

  // Context indicating that a new config should be added after a document save completes.
  private static var PostSaveContextAddConfig = 0

  @IBOutlet var configArrayController: NSArrayController!
  @IBOutlet weak var addRemoveSegmentedControl: NSSegmentedControl!

  @objc dynamic var numBazelPackages: Int = 0 {
    didSet {
      let enableAddButton = numBazelPackages > 0
      addRemoveSegmentedControl.setEnabled(enableAddButton,
                                           forSegment: SegmentedControlButtonIndex.add.rawValue)
    }
  }

  @objc dynamic var numSelectedConfigs: Int = 0 {
    didSet {
      addRemoveSegmentedControl.setEnabled(numSelectedConfigs > 0,
                                           forSegment: SegmentedControlButtonIndex.remove.rawValue)
      addRemoveSegmentedControl.setEnabled(numSelectedConfigs == 1,
                                           forSegment: SegmentedControlButtonIndex.action.rawValue)
    }
  }

  override var representedObject: Any? {
    didSet {
      if let concreteRepresentedObject = representedObject {
        bind(NSBindingName(rawValue: "numBazelPackages"),
             to: concreteRepresentedObject,
             withKeyPath: "bazelPackages.@count",
             options: nil)
      }
    }
  }

  deinit {
    NSObject.unbind(NSBindingName(rawValue: "numBazelPackages"))
    NSObject.unbind(NSBindingName(rawValue: "numSelectedConfigs"))
  }

  override func loadView() {
    ValueTransformer.setValueTransformer(IsOneValueTransformer(),
                                           forName: NSValueTransformerName(rawValue: "IsOneValueTransformer"))
    super.loadView()
    bind(NSBindingName(rawValue: "numSelectedConfigs"),
         to: configArrayController,
         withKeyPath: "selectedObjects.@count",
         options: nil)
  }

  @IBAction func didClickAddRemoveSegmentedControl(_ sender: NSSegmentedCell) {
    // Ignore mouse up messages.
    if sender.selectedSegment < 0 { return }

    guard let button = SegmentedControlButtonIndex(rawValue: sender.selectedSegment) else {
      assertionFailure("Unexpected add/remove button index \(sender.selectedSegment)")
      return
    }

    switch button {
      case .add:
        didClickAddConfig(sender)
      case .remove:
        didClickRemoveSelectedConfigs(sender)
      case .action:
        didClickAction(sender)
    }
  }

  @IBAction func doGenerate(_ sender: AnyObject?) {
    // TODO(abaire): Make it clear to the user that only the first selection is generated.
    guard let configName = configArrayController.selectedObjects.first as? String else { return }
    guard requireValidBazel({ self.doGenerate(sender) }) else { return }

    let generatorController = XcodeProjectGenerationProgressViewController()
    generatorController.representedObject = representedObject
    presentViewControllerAsSheet(generatorController)

    let projectDocument = representedObject as! TulsiProjectDocument
    generatorController.generateProjectForConfigName(configName) { (projectURL: URL?) in
      self.dismissViewController(generatorController)
      if let projectURL = projectURL {
        LogMessage.postInfo("Opening generated project in Xcode",
                            context: projectDocument.projectName)
        NSWorkspace.shared.open(projectURL)
      }
    }
  }

  @IBAction func didDoubleClickConfigRow(_ sender: NSTableView) {
    guard requireValidBazel({ self.didDoubleClickConfigRow(sender) }) else { return }
    let clickedRow = sender.clickedRow
    guard clickedRow >= 0 else { return }
    let configName = (configArrayController.arrangedObjects as! [String])[clickedRow]
    editConfigNamed(configName)
  }

  @objc func document(_ doc:NSDocument, didSave:Bool, contextInfo: UnsafeMutableRawPointer) {
    if contextInfo == &ProjectEditorConfigManagerViewController.PostSaveContextAddConfig {
      if didSave {
        didClickAddConfig(nil)
      }
    }
  }

  // MARK: - Private methods

  private func didClickAddConfig(_ sender: AnyObject?) {
    guard requireValidBazel({ self.didClickAddConfig(sender) }) else { return }

    let projectDocument = representedObject as! TulsiProjectDocument

    // Adding a config to a project with no bazel packages is disallowed.
    guard let bazelPackages = projectDocument.bazelPackages, !bazelPackages.isEmpty else {
      // This should be prevented by the UI, so spawn a bug message and beep.
      LogMessage.postInfo("Bug: Add config invoked on a project with no packages.")
      NSSound.beep()
      return
    }

    let errorInfo: String
    do {
      let additionalFilePaths = bazelPackages.map() { "\($0)/BUILD" }
      guard let projectName = projectDocument.projectName,
                let generatorConfigFolderURL = projectDocument.generatorConfigFolderURL else {
        projectDocument.save(withDelegate: self,
                             didSave: #selector(ProjectEditorConfigManagerViewController.document(_:didSave:contextInfo:)),
                             contextInfo: &ProjectEditorConfigManagerViewController.PostSaveContextAddConfig)
        return
      }
      let optionSet = projectDocument.optionSet ?? TulsiOptionSet()
      let configDocument = try TulsiGeneratorConfigDocument.makeDocumentWithProjectRuleEntries(projectDocument.ruleInfos,
                                                                                               optionSet: optionSet,
                                                                                               projectName: projectName,
                                                                                               saveFolderURL: generatorConfigFolderURL,
                                                                                               infoExtractor: projectDocument.infoExtractor,
                                                                                               messageLog: projectDocument,
                                                                                               additionalFilePaths: additionalFilePaths,
                                                                                               bazelURL: projectDocument.bazelURL)
      projectDocument.trackChildConfigDocument(configDocument)
      configDocument.delegate = projectDocument
      configDocument.makeWindowControllers()
      configDocument.showWindows()
      return
    } catch let e as NSError {
      errorInfo = e.localizedDescription
    } catch {
      errorInfo = "Unexpected exception"
    }

    let msg = NSLocalizedString("Error_GeneralCriticalFailure",
                                comment: "A general, critical failure without a more fitting descriptive message.")
    LogMessage.postError(msg, details: errorInfo, context: projectDocument.projectName)
  }


  /// Verifies that the project's Bazel URL seems valid, forcing the user to select a valid path if
  /// necessary and invoking the given retryHandler once they've finished selection.
  /// Returns true if Bazel is already valid, false if the Bazel picker is being shown.
  private func requireValidBazel(_ retryHandler: @escaping () -> Void) -> Bool {
    let projectDocument = representedObject as! TulsiProjectDocument
    guard let bazelURL = projectDocument.bazelURL,
              FileManager.default.isExecutableFile(atPath: bazelURL.path) else {
      BazelSelectionPanel.beginSheetModalBazelSelectionPanelForWindow(self.view.window!,
                                                                      document: projectDocument) {
        (bazelURL: URL?) in
          if bazelURL != nil {
            retryHandler()
          }
      }
      return false
    }
    return true
  }

  private func didClickRemoveSelectedConfigs(_ sender: AnyObject?) {
    let document = representedObject as! TulsiProjectDocument
    let selectedConfigNames = configArrayController.selectedObjects as! [String]
    document.deleteConfigsNamed(selectedConfigNames)
  }

  private func didClickAction(_ sender: AnyObject?) {
    let selectedConfigNames = configArrayController.selectedObjects as! [String]
    if let configName = selectedConfigNames.first {
      editConfigNamed(configName)
    }
  }

  private func editConfigNamed(_ name: String) {
    let projectDocument = representedObject as! TulsiProjectDocument
    let errorInfo: String
    do {
      let configDocument = try projectDocument.loadConfigDocumentNamed(name) { (_) in
        // Nothing in particular has to be done when the config doc is loaded, the editor UI already
        // handles this via the document's processing state.
      }
      configDocument.makeWindowControllers()
      configDocument.showWindows()
      return
    } catch TulsiProjectDocument.DocumentError.noSuchConfig {
      errorInfo = "No URL for config named '\(name)'"
    } catch TulsiProjectDocument.DocumentError.configLoadFailed(let info) {
      errorInfo = info
    } catch TulsiProjectDocument.DocumentError.invalidWorkspace(let info) {
      errorInfo = "Invalid workspace: \(info)"
    } catch {
      errorInfo = "An unexpected exception occurred while loading config named '\(name)'"
    }
    let msg = NSLocalizedString("Error_ConfigLoadFailed",
                                comment: "Error when a TulsiGeneratorConfig failed to be reloaded.")
    LogMessage.postError(msg, details: errorInfo)
  }
}


/// Transformer that returns true if the value is equal to 1.
final class IsOneValueTransformer : ValueTransformer {
  override class func transformedValueClass() -> AnyClass {
    return NSString.self
  }

  override class func allowsReverseTransformation() -> Bool  {
    return false
  }

  override func transformedValue(_ value: Any?) -> Any? {
    if let intValue = value as? Int, intValue == 1 {
      return true
    }
    return false
  }
}
