/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * 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.
 */

package com.android.build.gradle.internal

import com.android.SdkConstants
import com.google.common.annotations.VisibleForTesting
import com.google.common.base.Charsets
import java.io.File
import java.io.FileInputStream
import java.io.InputStreamReader
import java.util.Properties

/**
 * SdkType represents which kind is the SDK located (or if it's missing).
 */
enum class SdkType {
    REGULAR, PLATFORM, TEST, MISSING
}

/**
 * SdkLocation is the result of calling {@code SdkLocator.getSdkLocation(sourceSet) and contains
 * the located SDK directory and its type.
 */
data class SdkLocation(val directory: File?, val type: SdkType)

/**
 * A SdkLocationSourceSet represents all the variables and information necessary for locating the
 * SDK to be used based on all the possible ways that the user can set their preferences.
 *
 * <p>Create a new instance using {@code SdkLocationSourceSet(gradleProject.rootDir)} and the
 * constructor will collect the proper variables from the local.properties file, the environment
 * variables and system properties.
 *
 * <p>For testing reasons you can override any of the components.
 */
data class SdkLocationSourceSet(
    val projectRoot: File,
    internal val localProperties: Properties = GradleLocalPropertiesFactory.get(projectRoot),
    internal val environmentProperties: Properties = EnvironmentVariablesPropertiesFactory.get(),
    internal val systemProperties: Properties = SystemPropertiesFactory.get())

/**
 * SdkLocator contains the logic to select the SDK based on the variables set by the user.
 *
 * <p>Use {@link SdkLocator.getSdkLocation(sourceSet)} to fetch a {@code SdkLocation} object based
 * on the user preferences represented by the passed {@code sourceSet}. If this sourceSet was used
 * before than the result will be cached.
 *
 * <p>To clear the cache, at the end of the build for example, use {@link SdkLocator.resetCache()}.
 */
object SdkLocator {

    @JvmStatic
    @VisibleForTesting
    var sdkTestDirectory: File? = null

    @VisibleForTesting
    const val ANDROID_DIR_PROPERTY = "android.dir"
    @VisibleForTesting
    const val ANDROID_HOME_SYSTEM_PROPERTY = "android.home"

    // Order defines the preference for matching an SDK directory.
    internal enum class SdkLocationSource(val sdkType: SdkType) {
        TEST_SDK_DIRECTORY(SdkType.TEST) {
            override fun getSdkPathProperty(sourceSet: SdkLocationSourceSet): String? {
                return sdkTestDirectory?.absolutePath
            }
        },
        LOCAL_SDK_DIR(SdkType.REGULAR) {
            override fun getSdkPathProperty(sourceSet: SdkLocationSourceSet): String? {
                return sourceSet.localProperties.getProperty(SdkConstants.SDK_DIR_PROPERTY)
            }

        }, LOCAL_ANDROID_DIR(SdkType.PLATFORM) { // TODO: Check if this is still used.
            override fun getSdkPathProperty(sourceSet: SdkLocationSourceSet): String? {
                return sourceSet.localProperties.getProperty(ANDROID_DIR_PROPERTY)
            }

        }, ENV_ANDROID_HOME(SdkType.REGULAR) {
            override fun getSdkPathProperty(sourceSet: SdkLocationSourceSet): String? {
                return sourceSet.environmentProperties.getProperty(SdkConstants.ANDROID_HOME_ENV)
            }

        }, ENV_SDK_ROOT(SdkType.REGULAR) {
            override fun getSdkPathProperty(sourceSet: SdkLocationSourceSet): String? {
                return sourceSet.environmentProperties.getProperty(SdkConstants.ANDROID_SDK_ROOT_ENV)
            }

        }, SYS_ANDROID_HOME(SdkType.REGULAR) {
            override fun getSdkPathProperty(sourceSet: SdkLocationSourceSet): String? {
                return sourceSet.systemProperties.getProperty(ANDROID_HOME_SYSTEM_PROPERTY)
            }
        };

        fun getSdkLocation(sourceSet: SdkLocationSourceSet): SdkLocation? {
            return getSdkPathProperty(sourceSet)?.let {
                    path -> validateSdkPath(path, sourceSet.projectRoot)?.let {
                        SdkLocation(it, sdkType)
                    }
            }
        }
        abstract fun getSdkPathProperty(sourceSet: SdkLocationSourceSet): String?

        // Basic SDK path validation:
        // * If it's not an absolute path, uses the project rootDir as base.
        // * Check if the path points to a directory in the disk.
        private fun validateSdkPath(path: String, rootDir: File): File? {
            var sdk = File(path)
            if (!sdk.isAbsolute) {
                // Canonical file transforms paths like: .../userHome/projectRoot/../AndroidSDK
                // Into: .../userHome/AndroidSDK
                // This makes no difference on the behavior of the code, but for error messages is much
                // more clear to present the canonical path to the user.
                sdk = File(rootDir, path).canonicalFile
            }
            return if (sdk.isDirectory) sdk else null
        }
    }

    // We cache by the source set used, so if any property changes we don't use the cache and locate
    // the SDK directory again.
    private var cachedSdkLocationKey: SdkLocationSourceSet? = null
    private var cachedSdkLocation: SdkLocation? = null

    @JvmStatic
    fun getSdkLocation(projectRootDir: File): SdkLocation {
        return getSdkLocation(SdkLocationSourceSet(projectRootDir))
    }

    @JvmStatic
    @Synchronized
    fun getSdkLocation(sourceSet: SdkLocationSourceSet): SdkLocation {
        cachedSdkLocationKey?.let {
            if (it == sourceSet) {
                return cachedSdkLocation!!
            }
        }

        for (source in SdkLocationSource.values()) {
            source.getSdkLocation(sourceSet)?.let {
                updateCache(it, sourceSet)
                return it
            }
        }

        SdkLocation(null, SdkType.MISSING).let {
            updateCache(it, sourceSet)
            return it
        }
    }

    @Synchronized
    private fun updateCache(sdkLocation: SdkLocation, sourceSet: SdkLocationSourceSet) {
        cachedSdkLocationKey = sourceSet
        cachedSdkLocation = sdkLocation

    }

    @JvmStatic
    @Synchronized
    fun resetCache() {
        GradleLocalPropertiesFactory.resetCache()
        cachedSdkLocationKey = null
        cachedSdkLocation = null

    }
}

private object GradleLocalPropertiesFactory {

    val cache = mutableMapOf<File, Properties>()

    @Synchronized
    internal fun get(projectRoot: File): Properties {
        val properties = Properties()
        val localProperties = File(projectRoot, SdkConstants.FN_LOCAL_PROPERTIES)

        if (localProperties.isFile) {
            InputStreamReader(FileInputStream(localProperties), Charsets.UTF_8).use { reader ->
                properties.load(reader)
            }
        }

        cache[projectRoot] = properties
        return properties
    }

    @Synchronized
    internal fun resetCache() {
        cache.clear()
    }

}

private object EnvironmentVariablesPropertiesFactory {
    internal fun get(): Properties {
        val properties = Properties()
        System.getenv(SdkConstants.ANDROID_HOME_ENV)?.let {
            properties.setProperty(SdkConstants.ANDROID_HOME_ENV, it) }
        System.getenv(SdkConstants.ANDROID_SDK_ROOT_ENV)?.let {
            properties.setProperty(SdkConstants.ANDROID_SDK_ROOT_ENV, it) }
        return properties
    }
}

private object SystemPropertiesFactory {
    internal fun get(): Properties {
        val properties = Properties()
        System.getProperty(SdkLocator.ANDROID_HOME_SYSTEM_PROPERTY)?.let {
            properties.setProperty(SdkLocator.ANDROID_HOME_SYSTEM_PROPERTY, it) }
        return properties
    }
}