// 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 layered values for a single Tulsi option.
public class TulsiOption: Equatable, CustomStringConvertible {

  /// The string serialized for boolean options which are 'true'.
  public static let BooleanTrueValue = "YES"
  /// The string serialized for boolean options which are 'false'.
  public static let BooleanFalseValue = "NO"

  /// Special keyword that may be used in an option's value in order to inherit a parent option's
  /// value.
  public static let InheritKeyword = "$(inherited)"

  /// The valid value types for this option.
  public enum ValueType {
    case bool, string
  }

  /// How this option is intended to be used.
  public struct OptionType: OptionSet {
    public let rawValue: Int

    public init(rawValue: Int) {
      self.rawValue = rawValue
    }

    /// An option that is handled in Tulsi's code.
    static let Generic = OptionType(rawValue: 0)

    /// An option that may be automatically encoded into a build setting.
    static let BuildSetting = OptionType(rawValue: 1 << 0)

    /// An option that may be specialized on a per-target basis.
    static let TargetSpecializable = OptionType(rawValue: 1 << 1)

    /// An option that may be automatically encoded into a build setting and overridden on a
    /// per-target basis.
    static let TargetSpecializableBuildSetting = OptionType([BuildSetting, TargetSpecializable])

    /// An option that is not visualized in the UI at all.
    static let Hidden = OptionType(rawValue: 1 << 16)

    /// An option that may only be persisted into per-user configs.
    static let PerUserOnly = OptionType(rawValue: 1 << 17)

    /// An option that merges its parent's value if the special InheritKeyword string appears.
    static let SupportsInheritKeyword = OptionType(rawValue: 1 << 18)
  }

  /// Name of this option as it should be displayed to the user.
  public let displayName: String
  /// Detailed description of what this option does.
  public let userDescription: String
  /// The type of value associated with this option.
  public let valueType: ValueType
  /// How this option is handled within Tulsi.
  public let optionType: OptionType

  /// Value of this option if the user does not provide any override.
  public let defaultValue: String?
  /// User-set value of this option for all targets within this project, unless overridden.
  public var projectValue: String? = nil
  /// Per-target values for this option.
  public var targetValues: [String: String]?

  /// Provides the value of this option with no target specialization.
  public var commonValue: String? {
    if projectValue != nil { return projectValue }
    return defaultValue
  }

  /// Returns true if the value of this option with no target specialization is the serialization
  /// string equivalent to true. Returns nil if there is no common value for this option.
  public var commonValueAsBool: Bool? {
    guard let val = commonValue else {
      return nil
    }
    return val == TulsiOption.BooleanTrueValue
  }

  /// Key under which this option's project-level value is stored.
  static let ProjectValueKey = "p"
  /// Key under which this option's target-level values are stored.
  static let TargetValuesKey = "t"
  typealias PersistenceType = [String: AnyObject]

  init(displayName: String,
       userDescription: String,
       valueType: ValueType,
       optionType: OptionType,
       defaultValue: String? = nil) {
    self.displayName = displayName
    self.userDescription = userDescription
    self.valueType = valueType
    self.optionType = optionType
    self.defaultValue = defaultValue

    if optionType.contains(.TargetSpecializable) {
      self.targetValues = [String: String]()
    } else {
      self.targetValues = nil
    }
  }

  /// Creates a new TulsiOption instance whose value is taken from an existing TulsiOption and may
  /// inherit parts/all of its values from another parent TulsiOption.
  init(resolvingValuesFrom opt: TulsiOption, byInheritingFrom parent: TulsiOption) {
    displayName = opt.displayName
    userDescription = opt.userDescription
    valueType = opt.valueType
    optionType = opt.optionType
    defaultValue = parent.commonValue
    projectValue = opt.projectValue
    targetValues = opt.targetValues

    let inheritValue = defaultValue ?? ""
    func resolveInheritKeyword(_ value: String?) -> String? {
      guard let value = value else { return nil }
      return value.replacingOccurrences(of: TulsiOption.InheritKeyword,
                                                        with: inheritValue)
    }
    if optionType.contains(.SupportsInheritKeyword) {
      projectValue = resolveInheritKeyword(projectValue)
      if targetValues != nil {
        for (key, value) in targetValues! {
          targetValues![key] = resolveInheritKeyword(value)
        }
      }
    }
  }

  /// Provides the resolved value of this option, potentially specialized for the given target.
  public func valueForTarget(_ target: String, inherit: Bool = true) -> String? {
    if let val = targetValues?[target] {
      return val
    }

    if inherit {
      return commonValue
    }
    return nil
  }

  public func sanitizeValue(_ value: String?) -> String? {
    if valueType == .bool {
      if value != TulsiOption.BooleanTrueValue {
        return TulsiOption.BooleanFalseValue
      }
      return value
    }
    return value?.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
  }

  // Generates a serialized form of this option's user-defined values or nil if the value is
  // the default.
  func serialize() -> PersistenceType? {
    var serialized = PersistenceType()
    if let value = projectValue {
      serialized[TulsiOption.ProjectValueKey] = value as AnyObject?
    }

    if let values = targetValues, !values.isEmpty {
      serialized[TulsiOption.TargetValuesKey] = values as AnyObject?
    }
    if serialized.isEmpty { return nil }
    return serialized
  }

  func deserialize(_ serialized: PersistenceType) {
    if let value = serialized[TulsiOption.ProjectValueKey] as? String {
      projectValue = value
    } else {
      projectValue = nil
    }

    if let values = serialized[TulsiOption.TargetValuesKey] as? [String: String] {
      targetValues = values
    } else if optionType.contains(.TargetSpecializable) {
      self.targetValues = [String: String]()
    } else {
      self.targetValues = nil
    }
  }

  // MARK: - CustomStringConvertible

  public var description: String {
    return "\(displayName) - \(String(describing: commonValue)):\(String(describing: targetValues))"
  }
}

public func ==(lhs: TulsiOption, rhs: TulsiOption) -> Bool {
  if !(lhs.displayName == rhs.displayName &&
      lhs.userDescription == rhs.userDescription &&
      lhs.valueType == rhs.valueType &&
      lhs.optionType == rhs.optionType) {
    return false
  }

  func optionalsAreEqual<T>(_ a: T?, _ b: T?) -> Bool where T: Equatable {
    if a == nil { return b == nil }
    if b == nil { return false }
    return a! == b!
  }
  func optionalDictsAreEqual<K, V>(_ a: [K: V]?, _ b: [K: V]?) -> Bool where K: Equatable, V: Equatable {
    if a == nil { return b == nil }
    if b == nil { return false }
    return a! == b!
  }
  return optionalsAreEqual(lhs.defaultValue, rhs.defaultValue) &&
      optionalsAreEqual(lhs.projectValue, rhs.projectValue) &&
      optionalDictsAreEqual(lhs.targetValues, rhs.targetValues)
}
