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

/// Models the label and type of a single supported Bazel target.
/// See http://bazel.build/docs/build-ref.html#targets.
public class RuleInfo: Equatable, Hashable, CustomDebugStringConvertible {
  public let label: BuildLabel
  public let type: String
  /// Set of BuildLabels referencing targets that are required by this RuleInfo. For example, test
  /// hosts for XCTest targets.
  public let linkedTargetLabels: Set<BuildLabel>

  public var hashValue: Int {
    return label.hashValue ^ type.hashValue
  }

  public var debugDescription: String {
    return "\(Swift.type(of: self))(\(label) \(type))"
  }

  init(label: BuildLabel, type: String, linkedTargetLabels: Set<BuildLabel>) {
    self.label = label
    self.type = type
    self.linkedTargetLabels = linkedTargetLabels
  }

  func equals(_ other: RuleInfo) -> Bool {
    guard Swift.type(of: self) == Swift.type(of: other) else {
      return false
    }
    return self.type == other.type && self.label == other.label
  }
}


/// Encapsulates data about a file that may be a Bazel input or output.
public class BazelFileInfo: Equatable, Hashable, CustomDebugStringConvertible {
  public enum TargetType: Int {
    case sourceFile
    case generatedFile
  }

  /// The path to this file relative to rootPath.
  public let subPath: String

  /// The root of this file's path (typically used to indicate the path to a generated file's root).
  public let rootPath: String

  /// The type of this file.
  public let targetType: TargetType

  /// Whether or not this file object is a directory.
  public let isDirectory: Bool

  public lazy var fullPath: String = { [unowned self] in
    return NSString.path(withComponents: [self.rootPath, self.subPath])
  }()

  public lazy var uti: String? = { [unowned self] in
    return self.subPath.pbPathUTI
  }()

  public lazy var hashValue: Int = { [unowned self] in
    return self.subPath.hashValue &+
        self.rootPath.hashValue &+
        self.targetType.hashValue &+
        self.isDirectory.hashValue
  }()

  init?(info: AnyObject?) {
    guard let info = info as? [String: AnyObject] else {
      return nil
    }

    guard let subPath = info["path"] as? String,
              let isSourceFile = info["src"] as? Bool else {
      assertionFailure("Aspect provided a file info dictionary but was missing required keys")
      return nil
    }

    self.subPath = subPath
    if let rootPath = info["root"] as? String {
      // Patch up
      self.rootPath = rootPath
    } else {
      self.rootPath = ""
    }
    self.targetType = isSourceFile ? .sourceFile : .generatedFile

    self.isDirectory = info["is_dir"] as? Bool ?? false
  }

  init(rootPath: String, subPath: String, isDirectory: Bool, targetType: TargetType) {
    self.rootPath = rootPath
    self.subPath = subPath
    self.isDirectory = isDirectory
    self.targetType = targetType
  }

  // MARK: - CustomDebugStringConvertible
  public lazy var debugDescription: String = { [unowned self] in
    return "{\(self.fullPath) \(self.isDirectory ? "<DIR> " : "")\(self.targetType)}"
  }()
}

public func ==(lhs: BazelFileInfo, rhs: BazelFileInfo) -> Bool {
  return lhs.targetType == rhs.targetType &&
      lhs.rootPath == rhs.rootPath &&
      lhs.subPath == rhs.subPath &&
      lhs.isDirectory == rhs.isDirectory
}


/// Models the full metadata of a single supported Bazel target.
/// See http://bazel.build/docs/build-ref.html#targets.
public final class RuleEntry: RuleInfo {
  // Include paths are represented by a string and a boolean indicating whether they should be
  // searched recursively or not.
  public typealias IncludePath = (String, Bool)

  /// Mapping of BUILD file type to Xcode Target type for non-bundled types.
  static let BuildTypeToTargetType = [
      "cc_binary": PBXTarget.ProductType.Application,
      "cc_library": PBXTarget.ProductType.StaticLibrary,
      "cc_test": PBXTarget.ProductType.Tool,
      // macos_command_line_application is not a bundled type in our rules as it does not contain
      // any resources, so we must explicitly list it here.
      "macos_command_line_application": PBXTarget.ProductType.Tool,
      "objc_library": PBXTarget.ProductType.StaticLibrary,
      "swift_library": PBXTarget.ProductType.StaticLibrary,
  ]

  /// Keys for a RuleEntry's attributes map. Definitions may be found in the Bazel Build
  /// Encyclopedia (see http://bazel.build/docs/be/overview.html).
  // Note: This set of must be kept in sync with the tulsi_aspects aspect.
  public enum Attribute: String {
    case binary
    case bridging_header
    // Contains defines that were specified by the user on the commandline or are built into
    // Bazel itself.
    case compiler_defines
    case copts
    case datamodels
    case enable_modules
    case has_swift_dependency
    case has_swift_info
    case launch_storyboard
    case pch
    case swift_language_version
    case swift_toolchain
    case swiftc_opts
    // Contains various files that are used as part of the build process but need no special
    // handling in the generated Xcode project. For example, asset_catalog, storyboard, and xibs
    // attributes all end up as supporting_files.
    case supporting_files
    // For the apple_unit_test and apple_ui_test rules, contains a label reference to the .xctest
    // bundle packaging target.
    case test_bundle
    // For the apple_unit_test and apple_ui_test rules, contains a label reference to the
    // ios_application target to be used as the test host when running the tests.
    case test_host
  }

  /// Bazel attributes for this rule (e.g., "binary": <some label> on an ios_application).
  public let attributes: [Attribute: AnyObject]

  /// Artifacts produced by Bazel when this rule is built.
  public let artifacts: [BazelFileInfo]

  /// Objective-C defines to be applied to this rule by Bazel.
  public let objcDefines: [String]?

  /// Swift defines to be applied to this rule by Bazel.
  public let swiftDefines: [String]?

  /// Source files associated with this rule.
  public let sourceFiles: [BazelFileInfo]

  /// Non-ARC source files associated with this rule.
  public let nonARCSourceFiles: [BazelFileInfo]

  /// Paths to directories that will include header files.
  public let includePaths: [IncludePath]?

  /// Set of the labels that this rule depends on.
  public let dependencies: Set<BuildLabel>

  /// Set of the labels that this test rule's binary depends on.
  public let testDependencies: Set<BuildLabel>

  /// Set of ios_application extension labels that this rule utilizes.
  public let extensions: Set<BuildLabel>

  /// .framework bundles provided by this rule.
  public let frameworkImports: [BazelFileInfo]

  /// List of implicit artifacts that are generated by this rule.
  public let secondaryArtifacts: [BazelFileInfo]

  /// The Swift language version used by this target.
  public let swiftLanguageVersion: String?

  /// The swift toolchain argument used by this target.
  public let swiftToolchain: String?

  /// List containing the transitive swiftmodules on which this rule depends.
  public let swiftTransitiveModules: [BazelFileInfo]

  /// List containing the transitive ObjC modulemaps on which this rule depends.
  public let objCModuleMaps: [BazelFileInfo]

  /// Module name to use in Xcode instead of the default.
  public let moduleName: String?

  /// The deployment platform target for this target.
  public let deploymentTarget: DeploymentTarget?

  /// Set of labels that this rule depends on but does not require.
  /// TODO(b/71904309): Remove this once test_suite fetching via Aspect is stable.
  // NOTE(abaire): This is a hack used for test_suite rules, where the possible expansions retrieved
  // via queries are filtered by the existence of the selected labels extracted via the normal
  // aspect path. Ideally the aspect would be able to directly express the relationship between the
  // test_suite and the test rules themselves, but that expansion is done prior to the application
  // of the aspect.
  public var weakDependencies = Set<BuildLabel>()

  /// Set of labels that this test_suite depends on. If this target is not a test_suite, returns
  /// an empty set. This maps directly to the `tests` attribute of the test_suite.
  public var testSuiteDependencies: Set<BuildLabel> {
    guard type == "test_suite" else { return Set() }

    // Legacy support for expansion of test_suite via a Bazel query. If a Bazel query is used,
    // `dependencies` will be empty and `weakDependencies` will contain the test_suite's
    // dependencies. Otherwise, `dependencies` will contain the test_suite's dependencies.
    guard dependencies.isEmpty else { return dependencies }

    return weakDependencies
  }

  /// The BUILD file that this rule was defined in.
  public let buildFilePath: String?

  // The CFBundleIdentifier associated with the target for this rule, if any.
  public let bundleID: String?

  /// The bundle name associated with the target for this rule, if any.
  public let bundleName: String?

  /// The product type for this rule (only for targets With AppleBundleInfo).
  let productType: PBXTarget.ProductType?

  /// The CFBundleIdentifier of the watchOS extension target associated with this rule, if any.
  public let extensionBundleID: String?

  /// The NSExtensionPointIdentifier of the extension associated with this rule, if any.
  public let extensionType: String?

  /// Xcode version used during the aspect run. Only set for bundled and runnable targets.
  public let xcodeVersion: String?

  /// Returns the set of non-versioned artifacts that are not source files.
  public var normalNonSourceArtifacts: [BazelFileInfo] {
    var artifacts = [BazelFileInfo]()
    if let description = attributes[.launch_storyboard] as? [String: AnyObject],
           let fileTarget = BazelFileInfo(info: description as AnyObject?) {
      artifacts.append(fileTarget)
    }

    if let fileTargets = parseFileDescriptionListAttribute(.supporting_files) {
      artifacts.append(contentsOf: fileTargets)
    }

    return artifacts
  }

  /// Returns the set of artifacts for which a versioned group should be created in the generated
  /// Xcode project.
  public var versionedNonSourceArtifacts: [BazelFileInfo] {
    if let fileTargets = parseFileDescriptionListAttribute(.datamodels) {
      return fileTargets
    }
    return []
  }

  /// The full set of input and output artifacts for this rule.
  public var projectArtifacts: [BazelFileInfo] {
    var artifacts = sourceFiles
    artifacts.append(contentsOf: nonARCSourceFiles)
    artifacts.append(contentsOf: frameworkImports)
    artifacts.append(contentsOf: normalNonSourceArtifacts)
    artifacts.append(contentsOf: versionedNonSourceArtifacts)
    return artifacts
  }

  private(set) lazy var pbxTargetType: PBXTarget.ProductType? = { [unowned self] in
    if let productType = self.productType {
      return productType
    }
    return RuleEntry.BuildTypeToTargetType[self.type]
  }()

  /// Returns the value to be used as the Xcode SDKROOT for the build target generated for this
  /// RuleEntry.
  private(set) lazy var XcodeSDKRoot: String? = { [unowned self] in
    guard type != "cc_binary" && type != "cc_test" else {
      return PlatformType.macos.deviceSDK
    }
    if let platformType = self.deploymentTarget?.platform {
      return platformType.deviceSDK
    }
    return PlatformType.ios.deviceSDK
  }()

  init(label: BuildLabel,
       type: String,
       attributes: [String: AnyObject],
       artifacts: [BazelFileInfo] = [],
       sourceFiles: [BazelFileInfo] = [],
       nonARCSourceFiles: [BazelFileInfo] = [],
       dependencies: Set<BuildLabel> = Set(),
       testDependencies: Set<BuildLabel> = Set(),
       frameworkImports: [BazelFileInfo] = [],
       secondaryArtifacts: [BazelFileInfo] = [],
       weakDependencies: Set<BuildLabel>? = nil,
       extensions: Set<BuildLabel>? = nil,
       bundleID: String? = nil,
       bundleName: String? = nil,
       productType: PBXTarget.ProductType? = nil,
       extensionBundleID: String? = nil,
       platformType: String? = nil,
       osDeploymentTarget: String? = nil,
       buildFilePath: String? = nil,
       objcDefines: [String]? = nil,
       swiftDefines: [String]? = nil,
       includePaths: [IncludePath]? = nil,
       swiftLanguageVersion: String? = nil,
       swiftToolchain: String? = nil,
       swiftTransitiveModules: [BazelFileInfo] = [],
       objCModuleMaps: [BazelFileInfo] = [],
       moduleName: String? = nil,
       extensionType: String? = nil,
       xcodeVersion: String? = nil) {

    var checkedAttributes = [Attribute: AnyObject]()
    for (key, value) in attributes {
      guard let checkedKey = Attribute(rawValue: key) else {
        print("Tulsi rule \(label.value) - Ignoring unknown attribute key \(key)")
        assertionFailure("Unknown attribute key \(key)")
        continue
      }
      checkedAttributes[checkedKey] = value
    }
    self.attributes = checkedAttributes
    let parsedPlatformType: PlatformType?
    if let platformTypeStr = platformType {
      parsedPlatformType = PlatformType(rawValue: platformTypeStr)
    } else {
      parsedPlatformType = nil
    }

    self.artifacts = artifacts
    self.sourceFiles = sourceFiles
    self.nonARCSourceFiles = nonARCSourceFiles
    self.dependencies = dependencies
    self.testDependencies = testDependencies
    self.frameworkImports = frameworkImports
    self.secondaryArtifacts = secondaryArtifacts
    if let weakDependencies = weakDependencies {
      self.weakDependencies = weakDependencies
    }
    if let extensions = extensions {
      self.extensions = extensions
    } else {
      self.extensions = Set()
    }
    self.bundleID = bundleID
    self.bundleName = bundleName
    self.productType = productType
    self.extensionBundleID = extensionBundleID
    var deploymentTarget: DeploymentTarget? = nil
    if let platform = parsedPlatformType,
        let osVersion = osDeploymentTarget {
      deploymentTarget = DeploymentTarget(platform: platform, osVersion: osVersion)
    }
    self.deploymentTarget = deploymentTarget
    self.buildFilePath = buildFilePath
    self.objcDefines = objcDefines
    self.moduleName = moduleName
    self.swiftDefines = swiftDefines
    self.includePaths = includePaths
    self.swiftLanguageVersion = swiftLanguageVersion
    self.swiftToolchain = swiftToolchain
    self.swiftTransitiveModules = swiftTransitiveModules
    self.xcodeVersion = xcodeVersion

    // Swift targets may have a generated Objective-C module map for their Swift generated header.
    // Unfortunately, this breaks Xcode's indexing (it doesn't really make sense to ask SourceKit
    // to index some source files in a module while at the same time giving it a compiled version
    // of the same module), so we must exclude it.
    //
    // We must do the same thing for tests, except that it may apply to multiple modules as we
    // combine sources from potentially multiple targets into one test target.
    let targetsToAvoid = testDependencies + [label]
    let moduleMapsToAvoid = targetsToAvoid.compactMap { (targetLabel: BuildLabel) -> String? in
      if let fileName = targetLabel.asFileName {
        return "\(fileName).modulemaps/module.modulemap"
      }
      return nil
    }
    if !moduleMapsToAvoid.isEmpty {
      self.objCModuleMaps = objCModuleMaps.filter { moduleMapFileInfo in
        let moduleMapPath = moduleMapFileInfo.fullPath
        for mapToAvoid in moduleMapsToAvoid {
          if moduleMapPath.hasSuffix(mapToAvoid) {
            return false
          }
        }
        return true
      }
    } else {
      self.objCModuleMaps = objCModuleMaps
    }
    self.extensionType = extensionType

    var linkedTargetLabels = Set<BuildLabel>()
    if let hostLabelString = self.attributes[.test_host] as? String {
      linkedTargetLabels.insert(BuildLabel(hostLabelString))
    }

    super.init(label: label, type: type, linkedTargetLabels: linkedTargetLabels)
  }

  convenience init(label: String,
                   type: String,
                   attributes: [String: AnyObject],
                   artifacts: [BazelFileInfo] = [],
                   sourceFiles: [BazelFileInfo] = [],
                   nonARCSourceFiles: [BazelFileInfo] = [],
                   dependencies: Set<BuildLabel> = Set(),
                   testDependencies: Set<BuildLabel> = Set(),
                   frameworkImports: [BazelFileInfo] = [],
                   secondaryArtifacts: [BazelFileInfo] = [],
                   weakDependencies: Set<BuildLabel>? = nil,
                   extensions: Set<BuildLabel>? = nil,
                   bundleID: String? = nil,
                   bundleName: String? = nil,
                   productType: PBXTarget.ProductType? = nil,
                   extensionBundleID: String? = nil,
                   platformType: String? = nil,
                   osDeploymentTarget: String? = nil,
                   buildFilePath: String? = nil,
                   objcDefines: [String]? = nil,
                   swiftDefines: [String]? = nil,
                   includePaths: [IncludePath]? = nil,
                   swiftLanguageVersion: String? = nil,
                   swiftToolchain: String? = nil,
                   swiftTransitiveModules: [BazelFileInfo] = [],
                   objCModuleMaps: [BazelFileInfo] = [],
                   moduleName: String? = nil,
                   extensionType: String? = nil,
                   xcodeVersion: String? = nil) {
    self.init(label: BuildLabel(label),
              type: type,
              attributes: attributes,
              artifacts: artifacts,
              sourceFiles: sourceFiles,
              nonARCSourceFiles: nonARCSourceFiles,
              dependencies: dependencies,
              testDependencies: testDependencies,
              frameworkImports: frameworkImports,
              secondaryArtifacts: secondaryArtifacts,
              weakDependencies: weakDependencies,
              extensions: extensions,
              bundleID: bundleID,
              bundleName: bundleName,
              productType: productType,
              extensionBundleID: extensionBundleID,
              platformType: platformType,
              osDeploymentTarget: osDeploymentTarget,
              buildFilePath: buildFilePath,
              objcDefines: objcDefines,
              swiftDefines: swiftDefines,
              includePaths: includePaths,
              swiftLanguageVersion: swiftLanguageVersion,
              swiftToolchain: swiftToolchain,
              swiftTransitiveModules: swiftTransitiveModules,
              objCModuleMaps: objCModuleMaps,
              moduleName: moduleName,
              extensionType: extensionType,
              xcodeVersion: xcodeVersion)
  }

  // MARK: Private methods

  private func parseFileDescriptionListAttribute(_ attribute: RuleEntry.Attribute) -> [BazelFileInfo]? {
    guard let descriptions = attributes[attribute] as? [[String: AnyObject]] else {
      return nil
    }

    var fileTargets = [BazelFileInfo]()
    for description in descriptions {
      guard let target = BazelFileInfo(info: description as AnyObject?) else {
        assertionFailure("Failed to resolve file description to a file target")
        continue
      }
      fileTargets.append(target)
    }
    return fileTargets
  }

  override func equals(_ other: RuleInfo) -> Bool {
    guard super.equals(other), let entry = other as? RuleEntry else {
      return false
    }
    return deploymentTarget == entry.deploymentTarget
  }
}

// MARK: - Equatable

public func ==(lhs: RuleInfo, rhs: RuleInfo) -> Bool {
  return lhs.equals(rhs)
}
