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

/// Valid CPU types (for rules_apple Bazel targets).
public enum CPU: String {
  case i386
  case x86_64
  case armv7
  case armv7k
  case arm64
  case arm64e
  case arm64_32
  case sim_arm64

  public static let allCases: [CPU] = [.i386, .x86_64, .armv7, .armv7k, .arm64, .arm64e, .arm64_32, .sim_arm64]

  var isARM: Bool {
    switch self {
    case .i386: return false
    case .x86_64: return false
    case .armv7: return true
    case .armv7k: return true
    case .arm64: return true
    case .arm64e: return true
    case .arm64_32: return true
    case .sim_arm64: return true
    }
  }

  var watchCPU: CPU {
    if PlatformConfiguration.use64BitWatchSimulator {
      return isARM ? .armv7k : .x86_64
    } else {
      return isARM ? .armv7k : .i386
    }
  }
}

/// Represents a (PlatformType, AppleCPU) pair.
public struct PlatformConfiguration {

  /// Xcode 12 uses x86_64 64bit watch simulators in contrast to i386 32bit watch simulators
  /// used in Xcode 11 and older. 32bit apps cannot run on 64bit simulators and vice versa.
  /// Tulsi sets the CPU configuration at project generation time so we cannot dynamically
  /// swap between the two. Instead, Tulsi has an option 'Use64BitWatchSimulator' in the project
  /// config that allows the user to specify whether Tulsi should assume 64bit watch simulators.
  /// This value should be set to the value read from the Tulsi config and should be set as
  /// soon as the TulsiOption's are extracted to ensure the proper architecture is used
  /// everywhere.
  public static var use64BitWatchSimulator = false

  public let platform: PlatformType
  public let cpu: CPU

  /// Default to iOS 64-bit simulator, arm64 or x86_64 depending on what we're running on.
#if arch(arm64)
  public static let defaultConfiguration = PlatformConfiguration(platform: .ios, cpu: .sim_arm64)
#else
  public static let defaultConfiguration = PlatformConfiguration(platform: .ios, cpu: .x86_64)
#endif

  /// Returns all valid PlatformConfiguration identifiers.
  public static var allValidConfigurations: [PlatformConfiguration] {
    var platforms = [PlatformConfiguration]()
    for platformType in PlatformType.allCases {
      for cpu in platformType.validCPUs {
        platforms.append(PlatformConfiguration(platform: platformType, cpu: cpu))
      }
    }
    return platforms
  }

  public init(platform: PlatformType, cpu: CPU) {
    self.platform = platform
    self.cpu = cpu
  }

  /// Initialize based on an identifier; will only succeed if the identifier is present in
  /// PlatformConfiguration.allPlatformCPUIdentifiers (which checks for combination validity).
  public init?(identifier: String) {
    for validConfiguration in PlatformConfiguration.allValidConfigurations {
      if validConfiguration.identifier == identifier {
        self.platform = validConfiguration.platform
        self.cpu = validConfiguration.cpu
        return
      }
    }
    return nil
  }

  /// Human readable identifier for this (PlatformType, CPU) pair.
  var identifier: String {
    return "\(platform.bazelPlatform)_\(cpu.rawValue)"
  }
}

/// Valid Apple Platform Types.
/// See https://docs.bazel.build/versions/master/skylark/lib/apple_common.html#platform_type
public enum PlatformType: String {
  case ios
  case macos
  case tvos
  case watchos

  public static let allCases: [PlatformType] = [.ios, .macos, .tvos, .watchos]

  var validCPUs: Set<CPU> {
    switch self {
    case .ios: return [.i386, .x86_64, .armv7, .arm64, .arm64e, .sim_arm64]
    case .macos: return  [.x86_64, .arm64, .arm64e]
    case .tvos: return [.x86_64, .arm64,  .sim_arm64]
    case .watchos: return [.i386,  .x86_64, .armv7k, .arm64_32, .arm64]
    }
  }

  var bazelCPUPlatform: String {
    switch self {
    case .macos: return "darwin"
    default: return bazelPlatform
    }
  }

  var bazelPlatform: String {
    return rawValue
  }

  var buildSettingsDeploymentTarget: String {
    switch self {
    case .ios: return "IPHONEOS_DEPLOYMENT_TARGET"
    case .macos: return "MACOSX_DEPLOYMENT_TARGET"
    case .tvos: return "TVOS_DEPLOYMENT_TARGET"
    case .watchos: return "WATCHOS_DEPLOYMENT_TARGET"
    }
  }

  var simulatorSDK: String {
    switch self {
    case .ios: return "iphonesimulator"
    case .macos: return "macosx"
    case .tvos: return "appletvsimulator"
    case .watchos: return "watchsimulator"
    }
  }

  var deviceSDK: String {
    switch self {
    case .ios: return "iphoneos"
    case .macos: return "macosx"
    case .tvos: return "appletvos"
    case .watchos: return "watchos"
    }
  }

  var userString: String {
    switch self {
    case .ios: return "iOS"
    case .macos: return "macOS"
    case .tvos: return "tvOS"
    case .watchos: return "watchOS"
    }
  }

  /// Path of where the test host is expected to be built for each available platform.
  func testHostPath(hostTargetPath: String, hostTargetProductName: String) -> String? {
    switch self {
    case .ios: return "$(BUILT_PRODUCTS_DIR)/\(hostTargetPath)/\(hostTargetProductName)"
    case .macos: return "$(BUILT_PRODUCTS_DIR)/\(hostTargetPath)/Contents/MacOS/\(hostTargetProductName)"
    case .tvos: return "$(BUILT_PRODUCTS_DIR)/\(hostTargetPath)/\(hostTargetProductName)"
    case .watchos: return nil
    }
  }
}

/// Target platform and os version to be used when generating the project.
public struct DeploymentTarget : Equatable {
  let platform: PlatformType
  let osVersion: String

  public static func ==(lhs: DeploymentTarget, rhs: DeploymentTarget) -> Bool {
    return lhs.platform == rhs.platform && lhs.osVersion == rhs.osVersion
  }
}
