import Foundation
import ProjectDescription
import TSCBasic
import TuistCore
import TuistGraph
import TuistSupport

extension TuistGraph.Config {
    /// Maps a ProjectDescription.Config instance into a TuistGraph.Config model.
    /// - Parameters:
    ///   - manifest: Manifest representation of Tuist config.
    ///   - path: The path of the config file.
    static func from(manifest: ProjectDescription.Config, at path: AbsolutePath) throws -> TuistGraph.Config {
        let generationOptions = try manifest.generationOptions.map { try TuistGraph.Config.GenerationOption.from(manifest: $0) }
        let compatibleXcodeVersions = TuistGraph.CompatibleXcodeVersions.from(manifest: manifest.compatibleXcodeVersions)
        let generatorPaths = GeneratorPaths(manifestDirectory: path)
        let plugins = try manifest.plugins.map { try PluginLocation.from(manifest: $0, generatorPaths: generatorPaths) }

        var cloud: TuistGraph.Cloud?
        if let manifestCloud = manifest.cloud {
            cloud = try TuistGraph.Cloud.from(manifest: manifestCloud)
        }

        var cache: TuistGraph.Cache?
        if let manifestCache = manifest.cache {
            cache = TuistGraph.Cache.from(manifest: manifestCache)
        }

        return TuistGraph.Config(
            compatibleXcodeVersions: compatibleXcodeVersions,
            cloud: cloud,
            cache: cache,
            plugins: plugins,
            generationOptions: generationOptions,
            path: path
        )
    }
}

extension TuistGraph.Config.GenerationOption {
    /// Maps a ProjectDescription.Config.GenerationOptions instance into a TuistGraph.Config.GenerationOptions model.
    /// - Parameters:
    ///   - manifest: Manifest representation of Tuist config generation options
    ///   - generatorPaths: Generator paths.
    static func from(manifest: ProjectDescription.Config.GenerationOptions) throws -> TuistGraph.Config.GenerationOption {
        switch manifest {
        case let .xcodeProjectName(templateString):
            return .xcodeProjectName(templateString.description)
        case let .organizationName(name):
            return .organizationName(name)
        case let .developmentRegion(developmentRegion):
            return .developmentRegion(developmentRegion)
        case .disableAutogeneratedSchemes:
            return .disableAutogeneratedSchemes
        case .disableSynthesizedResourceAccessors:
            return .disableSynthesizedResourceAccessors
        case .disableShowEnvironmentVarsInScriptPhases:
            return .disableShowEnvironmentVarsInScriptPhases
        case .enableCodeCoverage:
            return .enableCodeCoverage
        case .resolveDependenciesWithSystemScm:
            return .resolveDependenciesWithSystemScm
        case .disablePackageVersionLocking:
            return .disablePackageVersionLocking
        }
    }
}
