// 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 a configuration which can be used to generate an Xcode project directly.
public class TulsiGeneratorConfig {

  public enum ConfigError: Error {
    /// The give input file does not exist or cannot be read.
    case badInputFilePath
    /// A per-user config was found but could not be read.
    case failedToReadAdditionalOptionsData(String)
    /// Deserialization failed with the given debug info.
    case deserializationFailed(String)
    /// Serialization failed with the given debug info.
    case serializationFailed(String)
  }

  /// The file extension used when saving generator configs.
  public static let FileExtension = "tulsigen"

  /// Filename to be used when writing out user-specific values.
  public static var perUserFilename: String {
    return "\(NSUserName()).tulsigen-user"
  }

  /// The name of the Xcode project.
  public let projectName: String

  public var defaultFilename: String {
    return TulsiGeneratorConfig.sanitizeFilename("\(projectName).\(TulsiGeneratorConfig.FileExtension)")
  }

  /// The name of the Xcode project that will be generated by this config.
  public var xcodeProjectFilename: String {
    return TulsiGeneratorConfig.sanitizeFilename("\(projectName).xcodeproj")
  }

  /// The Bazel targets to generate Xcode build targets for.
  public let buildTargetLabels: [BuildLabel]

  /// The directory paths for which source files should be included in the generated Xcode project.
  public let pathFilters: Set<String>

  /// Additional file paths to add to the Xcode project (e.g., BUILD file paths).
  public let additionalFilePaths: [String]?
  /// The options for this config.
  public let options: TulsiOptionSet

  /// Path to the Bazel binary.
  public var bazelURL: URL

  static let ProjectNameKey = "projectName"
  static let BuildTargetsKey = "buildTargets"
  static let PathFiltersKey = "sourceFilters"
  static let AdditionalFilePathsKey = "additionalFilePaths"

  /// Returns a copy of the given filename sanitized by replacing path separators.
  public static func sanitizeFilename(_ filename: String) -> String {
    return filename.replacingOccurrences(of: "/", with: "_")
  }

  public static func load(_ inputFile: URL, bazelURL: URL? = nil) throws -> TulsiGeneratorConfig {
    let fileManager = FileManager.default
    guard let data = fileManager.contents(atPath: inputFile.path) else {
      throw ConfigError.badInputFilePath
    }

    let additionalOptionData: Data?
    let optionsFolderURL = inputFile.deletingLastPathComponent()
    let additionalOptionsFileURL = optionsFolderURL.appendingPathComponent(TulsiGeneratorConfig.perUserFilename)
    let perUserPath = additionalOptionsFileURL.path
    if fileManager.isReadableFile(atPath: perUserPath) {
      additionalOptionData = fileManager.contents(atPath: perUserPath)
      if additionalOptionData == nil {
        throw ConfigError.failedToReadAdditionalOptionsData("Could not read file at path \(perUserPath)")
      }
    } else {
      additionalOptionData = nil
    }

    return try TulsiGeneratorConfig(data: data,
                                    additionalOptionData: additionalOptionData,
                                    bazelURL: bazelURL)
  }

  public init(projectName: String,
              buildTargetLabels: [BuildLabel],
              pathFilters: Set<String>,
              additionalFilePaths: [String]?,
              options: TulsiOptionSet,
              bazelURL: URL?) {
    self.projectName = projectName
    self.buildTargetLabels = buildTargetLabels
    self.pathFilters = pathFilters
    self.additionalFilePaths = additionalFilePaths
    self.options = options

    if let bazelURL = bazelURL {
      self.bazelURL = bazelURL
    } else if let savedBazelPath = options[.BazelPath].commonValue {
      self.bazelURL = URL(fileURLWithPath: savedBazelPath)
    } else {
      // TODO(abaire): Flag a fallback to searching for the binary.
      self.bazelURL = URL(fileURLWithPath: "")
    }
  }

  public convenience init(projectName: String,
                          buildTargets: [RuleInfo],
                          pathFilters: Set<String>,
                          additionalFilePaths: [String]?,
                          options: TulsiOptionSet,
                          bazelURL: URL?) {
    self.init(projectName: projectName,
              buildTargetLabels: buildTargets.map({ $0.label }),
              pathFilters: pathFilters,
              additionalFilePaths: additionalFilePaths,
              options: options,
              bazelURL: bazelURL)
  }

  public convenience init(data: Data,
                          additionalOptionData: Data? = nil,
                          bazelURL: URL? = nil) throws {
    func extractJSONDict(_ data: Data, errorBuilder: (String) -> ConfigError) throws -> [String: AnyObject] {
      do {
        guard let jsonDict = try JSONSerialization.jsonObject(with: data,
                                                                        options: JSONSerialization.ReadingOptions()) as? [String: AnyObject] else {
          throw errorBuilder("Config file contents are invalid")
        }
        return jsonDict
      } catch let e as ConfigError {
        throw e
      } catch let e as NSError {
        throw errorBuilder(e.localizedDescription)
      } catch {
        assertionFailure("Unexpected exception")
        throw errorBuilder("Unexpected exception")
      }
    }

    let dict = try extractJSONDict(data) { ConfigError.deserializationFailed($0)}

    let projectName = dict[TulsiGeneratorConfig.ProjectNameKey] as? String ?? "Unnamed Tulsi Project"
    let buildTargetLabels = dict[TulsiGeneratorConfig.BuildTargetsKey] as? [String] ?? []
    let additionalFilePaths = dict[TulsiGeneratorConfig.AdditionalFilePathsKey] as? [String]
    let rawPathFilters = Set<String>(dict[TulsiGeneratorConfig.PathFiltersKey] as? [String] ?? [])

    // While //foo/bar is a valid filesystem path, Xcode won't open a project with such a path in
    // its structures, leading to arduous debug process.
    if let badPath = additionalFilePaths?.first(where: { $0.hasPrefix("//") }) {
      throw ConfigError.deserializationFailed("Invalid additional file path: \(badPath)")
    }


    // Convert any path filters specified as build labels to their package paths.
    var pathFilters = Set<String>()
    for sourceTarget in rawPathFilters {
      if let packageName = BuildLabel(sourceTarget).packageName {
        pathFilters.insert(packageName)
      }
    }

    var optionsDict = TulsiOptionSet.getOptionsFromContainerDictionary(dict) ?? [:]
    if let additionalOptionData = additionalOptionData {
      let additionalOptions = try extractJSONDict(additionalOptionData) {
        ConfigError.failedToReadAdditionalOptionsData($0)
      }
      guard let newOptions = TulsiOptionSet.getOptionsFromContainerDictionary(additionalOptions) else {
        throw ConfigError.failedToReadAdditionalOptionsData("Invalid per-user options file")
      }
      for (key, value) in newOptions {
        optionsDict[key] = value
      }
    }
    let options = TulsiOptionSet(fromDictionary: optionsDict)

    self.init(projectName: projectName,
              buildTargetLabels: buildTargetLabels.map({ BuildLabel($0) }),
              pathFilters: pathFilters,
              additionalFilePaths: additionalFilePaths,
              options: options,
              bazelURL: bazelURL)
  }

  public func save() throws -> NSData {
    let sortedBuildTargetLabels = buildTargetLabels.map({ $0.value }).sorted()
    let sortedPathFilters = [String](pathFilters).sorted()
    var dict: [String: Any] = [
        TulsiGeneratorConfig.ProjectNameKey: projectName as AnyObject,
        TulsiGeneratorConfig.BuildTargetsKey: sortedBuildTargetLabels as AnyObject,
        TulsiGeneratorConfig.PathFiltersKey: sortedPathFilters as AnyObject,
    ]
    if let additionalFilePaths = additionalFilePaths {
      dict[TulsiGeneratorConfig.AdditionalFilePathsKey] = additionalFilePaths as AnyObject?
    }
    options.saveShareableOptionsIntoDictionary(&dict)

    do {
      return try JSONSerialization.tulsi_newlineTerminatedDataWithJSONObject(dict,
                                                                             options: .prettyPrinted)
    } catch let e as NSError {
      throw ConfigError.serializationFailed(e.localizedDescription)
    } catch {
      throw ConfigError.serializationFailed("Unexpected exception")
    }
  }

  public func savePerUserSettings() throws -> NSData? {
    var dict = [String: Any]()
    options.savePerUserOptionsIntoDictionary(&dict)
    if dict.isEmpty { return nil }
    do {
      return try JSONSerialization.tulsi_newlineTerminatedDataWithJSONObject(dict,
                                                                             options: .prettyPrinted)
    } catch let e as NSError {
      throw ConfigError.serializationFailed(e.localizedDescription)
    } catch {
      throw ConfigError.serializationFailed("Unexpected exception")
    }
  }

  public func configByResolvingInheritedSettingsFromProject(_ project: TulsiProject) -> TulsiGeneratorConfig {
    let resolvedOptions = options.optionSetByInheritingFrom(project.options)
    return TulsiGeneratorConfig(projectName: projectName,
                                buildTargetLabels: buildTargetLabels,
                                pathFilters: pathFilters,
                                additionalFilePaths: additionalFilePaths,
                                options: resolvedOptions,
                                bazelURL: project.bazelURL ?? bazelURL)
  }

  public func configByAppendingPathFilters(_ additionalPathFilters: Set<String>) -> TulsiGeneratorConfig {
    let newPathFilters = pathFilters.union(additionalPathFilters)
    return TulsiGeneratorConfig(projectName: projectName,
                                buildTargetLabels: buildTargetLabels,
                                pathFilters: newPathFilters,
                                additionalFilePaths: additionalFilePaths,
                                options: options,
                                bazelURL: bazelURL)
  }
}
