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


// Provides methods utilizing Bazel query (http://bazel.build/docs/query.html) to extract
// information from a workspace.
final class BazelQueryInfoExtractor: QueuedLogging {

  enum ExtractorError: Error {
    /// A valid Bazel binary could not be located.
    case invalidBazelPath
  }

  /// The location of the bazel binary.
  var bazelURL: URL
  /// The location of the directory in which the workspace enclosing this BUILD file can be found.
  let workspaceRootURL: URL
  /// Universal flags for all Bazel invocations.
  private let bazelUniversalFlags: BazelFlags

  private let localizedMessageLogger: LocalizedMessageLogger
  private var queuedInfoMessages = [String]()

  private typealias CompletionHandler = (Process, Data, String?, String) -> Void

  init(bazelURL: URL,
       workspaceRootURL: URL,
       bazelUniversalFlags: BazelFlags,
       localizedMessageLogger: LocalizedMessageLogger) {
    self.bazelURL = bazelURL
    self.workspaceRootURL = workspaceRootURL
    self.bazelUniversalFlags = bazelUniversalFlags
    self.localizedMessageLogger = localizedMessageLogger
  }

  func extractTargetRulesFromPackages(_ packages: [String]) -> [RuleInfo] {
    guard !packages.isEmpty else {
      return []
    }

    let profilingStart = localizedMessageLogger.startProfiling("fetch_rules",
                                                               message: "Fetching rules for packages \(packages)")
    var infos = [RuleInfo]()
    let query = packages.map({ "kind(rule, \($0):all)"}).joined(separator: "+")
    do {
      let (process, data, stderr, debugInfo) =
          try self.bazelSynchronousQueryProcess(query,
                                                outputKind: "xml",
                                                loggingIdentifier: "bazel_query_fetch_rules")
      if process.terminationStatus != 0 {
        showExtractionError(debugInfo, stderr: stderr, displayLastLineIfNoErrorLines: true)
      } else if let entries = self.extractRuleInfosFromBazelXMLOutput(data) {
        infos = entries
      }
    } catch {
      // The error has already been displayed to the user.
      return []
    }

    localizedMessageLogger.logProfilingEnd(profilingStart)
    return infos
  }

  /// Extracts all of the transitive BUILD and skylark (.bzl) files used by the given targets.
  func extractBuildfiles<T: Collection>(_ targets: T) -> Set<BuildLabel> where T.Iterator.Element == BuildLabel {
    if targets.isEmpty { return Set() }

    let profilingStart = localizedMessageLogger.startProfiling("extracting_skylark_files",
                                                               message: "Finding Skylark files for \(targets.count) rules")

    let labelDeps = targets.map {"deps(\($0.value))"}
    let joinedLabelDeps = labelDeps.joined(separator: "+")
    let query = "buildfiles(\(joinedLabelDeps))"
    let buildFiles: Set<BuildLabel>
    do {
      // Errors in the BUILD structure being examined should not prevent partial extraction, so this
      // command is considered successful if it returns any valid data at all.
      let (_, data, _, debugInfo) = try self.bazelSynchronousQueryProcess(query,
                                                                          outputKind: "xml",
                                                                          additionalArguments: ["--keep_going"],
                                                                          loggingIdentifier: "bazel_query_extracting_skylark_files")
      self.queuedInfoMessages.append(debugInfo)

      if let labels = extractSourceFileLabelsFromBazelXMLOutput(data) {
        buildFiles = Set(labels)
      } else {
        localizedMessageLogger.warning("BazelBuildfilesQueryFailed",
                                       comment: "Bazel 'buildfiles' query failed to extract information.")
        buildFiles = Set()
      }

      localizedMessageLogger.logProfilingEnd(profilingStart)
    } catch {
      // Error will be displayed at the end of project generation.
      return Set()
    }

    return buildFiles
  }

  // MARK: - Private methods

  private func showExtractionError(_ debugInfo: String,
                                   stderr: String?,
                                   displayLastLineIfNoErrorLines: Bool = false) {
    localizedMessageLogger.infoMessage(debugInfo)
    let details: String?
    if let stderr = stderr {
      if displayLastLineIfNoErrorLines {
        details = BazelErrorExtractor.firstErrorLinesOrLastLinesFromString(stderr)
      } else {
        details = BazelErrorExtractor.firstErrorLinesFromString(stderr)
      }
    } else {
      details = nil
    }
    localizedMessageLogger.error("BazelInfoExtractionFailed",
                                 comment: "Error message for when a Bazel extractor did not complete successfully. Details are logged separately.",
                                 details: details)
  }

  // Generates a Process that will perform a bazel query, capturing the output data and passing it
  // to the terminationHandler.
  private func bazelQueryProcess(_ query: String,
                                 outputKind: String? = nil,
                                 additionalArguments: [String] = [],
                                 message: String = "",
                                 loggingIdentifier: String? = nil,
                                 terminationHandler: @escaping CompletionHandler) throws -> Process {
    guard FileManager.default.fileExists(atPath: bazelURL.path) else {
      localizedMessageLogger.error("BazelBinaryNotFound",
                                   comment: "Error to show when the bazel binary cannot be found at the previously saved location %1$@.",
                                   values: bazelURL as NSURL)
      throw ExtractorError.invalidBazelPath
    }

    var arguments = [
        "--max_idle_secs=60",
    ]
    arguments.append(contentsOf: bazelUniversalFlags.startup)
    arguments.append("query")
    arguments.append(contentsOf: bazelUniversalFlags.build)
    arguments.append(contentsOf: [
        "--announce_rc",  // Print the RC files used by this operation.
        "--noimplicit_deps",
        "--order_output=no",
        "--noshow_loading_progress",
        "--noshow_progress",
        query
    ])
    arguments.append(contentsOf: additionalArguments)
    if let kind = outputKind {
      arguments.append(contentsOf: ["--output", kind])
    }

    var message = message
    if message != "" {
      message = "\(message)\n"
    }

    let process = TulsiProcessRunner.createProcess(bazelURL.path,
                                                   arguments: arguments,
                                                   messageLogger: localizedMessageLogger,
                                                   loggingIdentifier: loggingIdentifier) {
      completionInfo in
        let debugInfoFormatString = NSLocalizedString("DebugInfoForBazelCommand",
                                                      bundle: Bundle(for: type(of: self)),
                                                      comment: "Provides general information about a Bazel failure; a more detailed error may be reported elsewhere. The Bazel command is %1$@, exit code is %2$d, stderr %3$@.")
        let stderr = NSString(data: completionInfo.stderr, encoding: String.Encoding.utf8.rawValue)
        let debugInfo = String(format: debugInfoFormatString,
                               completionInfo.commandlineString,
                               completionInfo.terminationStatus,
                               stderr ?? "<No STDERR>")

      terminationHandler(completionInfo.process,
                         completionInfo.stdout,
                         stderr as String?,
                         debugInfo)
    }

    return process
  }

  /// Performs the given Bazel query synchronously in the workspaceRootURL directory.
  private func bazelSynchronousQueryProcess(_ query: String,
                                            outputKind: String? = nil,
                                            additionalArguments: [String] = [],
                                            message: String = "",
                                            loggingIdentifier: String? = nil) throws -> (bazelProcess: Process,
                                                                                         returnedData: Data,
                                                                                         stderrString: String?,
                                                                                         debugInfo: String) {
    let semaphore = DispatchSemaphore(value: 0)
    var data: Data! = nil
    var stderr: String? = nil
    var info: String! = nil

    let process = try bazelQueryProcess(query,
                                        outputKind: outputKind,
                                        additionalArguments: additionalArguments,
                                        message: message,
                                        loggingIdentifier: loggingIdentifier) {
      (_: Process, returnedData: Data, stderrString: String?, debugInfo: String) in
        data = returnedData
        stderr = stderrString
        info = debugInfo
      semaphore.signal()
    }

    process.currentDirectoryPath = workspaceRootURL.path
    process.launch()

    _ = semaphore.wait(timeout: DispatchTime.distantFuture)
    return (process, data, stderr, info)
  }

  private func extractRuleInfosWithRuleInputsFromBazelXMLOutput(_ bazelOutput: Data) -> [RuleInfo: Set<BuildLabel>]? {
    do {
      var infos = [RuleInfo: Set<BuildLabel>]()
      let doc = try XMLDocument(data: bazelOutput, options: XMLNode.Options(rawValue: 0))
      let rules = try doc.nodes(forXPath: "/query/rule")
      for ruleNode in rules {
        guard let ruleElement = ruleNode as? XMLElement else {
          localizedMessageLogger.error("BazelResponseXMLNonElementType",
                                       comment: "General error to show when the XML parser returns something other " +
                                               "than an NSXMLElement. This should never happen in practice.")
          continue
        }
        guard let ruleLabel = ruleElement.attribute(forName: "name")?.stringValue else {
          localizedMessageLogger.error("BazelResponseMissingRequiredAttribute",
                                       comment: "Bazel response XML element %1$@ was found but was missing an attribute named %2$@.",
                                       values: ruleElement, "name")
          continue
        }
        guard let ruleType = ruleElement.attribute(forName: "class")?.stringValue else {
          localizedMessageLogger.error("BazelResponseMissingRequiredAttribute",
                                       comment: "Bazel response XML element %1$@ was found but was missing an attribute named %2$@.",
                                       values: ruleElement, "class")
          continue
        }

        func extractLabelsFromXpath(_ xpath: String) throws -> Set<BuildLabel> {
          var labelSet = Set<BuildLabel>()
          let nodes = try ruleElement.nodes(forXPath: xpath)
          for node in nodes {
            guard let label = node.stringValue else {
              localizedMessageLogger.error("BazelResponseLabelAttributeInvalid",
                                           comment: "Bazel response XML element %1$@ should have a valid string value but does not.",
                                           values: node)
              continue
            }
            labelSet.insert(BuildLabel(label))
          }
          return labelSet
        }

        // Retrieve the list of linked targets through the test_host attribute. This provides a
        // link between the test target and the test host so they can be linked in Xcode.
        var linkedTargetLabels = Set<BuildLabel>()
        linkedTargetLabels.formUnion(
            try extractLabelsFromXpath("./label[@name='test_host']/@value"))

        let entry = RuleInfo(label: BuildLabel(ruleLabel),
                             type: ruleType,
                             linkedTargetLabels: linkedTargetLabels)

        infos[entry] = try extractLabelsFromXpath("./rule-input/@name")
      }
      return infos
    } catch let e as NSError {
      localizedMessageLogger.error("BazelResponseXMLParsingFailed",
                                   comment: "Extractor Bazel output failed to be parsed as XML with error %1$@. This may be a Bazel bug or a bad BUILD file.",
                                   values: e.localizedDescription)
      return nil
    }
  }

  private func extractRuleInfosFromBazelXMLOutput(_ bazelOutput: Data) -> [RuleInfo]? {
    if let infoMap = extractRuleInfosWithRuleInputsFromBazelXMLOutput(bazelOutput) {
      return [RuleInfo](infoMap.keys)
    }
    return nil
  }

  private func extractSourceFileLabelsFromBazelXMLOutput(_ bazelOutput: Data) -> Set<BuildLabel>? {
    do {
      let doc = try XMLDocument(data: bazelOutput, options: XMLNode.Options(rawValue: 0))
      let fileLabels = try doc.nodes(forXPath: "/query/source-file/@name")
      var extractedLabels = Set<BuildLabel>()
      for labelNode in fileLabels {
        guard let value = labelNode.stringValue else {
          localizedMessageLogger.error("BazelResponseLabelAttributeInvalid",
                                       comment: "Bazel response XML element %1$@ should have a valid string value but does not.",
                                       values: labelNode)
          continue
        }
        extractedLabels.insert(BuildLabel(value))
      }
      return extractedLabels
    } catch let e as NSError {
      localizedMessageLogger.error("BazelResponseXMLParsingFailed",
                                   comment: "Extractor Bazel output failed to be parsed as XML with error %1$@. This may be a Bazel bug or a bad BUILD file.",
                                   values: e.localizedDescription)
      return nil
    }
  }

  // MARK: - QueuedLogging

  func logQueuedInfoMessages() {
    guard !self.queuedInfoMessages.isEmpty else {
      return
    }
    localizedMessageLogger.debugMessage("Log of Bazel query output follows:")
    for message in self.queuedInfoMessages {
      localizedMessageLogger.debugMessage(message)
    }
    self.queuedInfoMessages.removeAll()
  }

  var hasQueuedInfoMessages: Bool {
    return !self.queuedInfoMessages.isEmpty
  }
}
