/*
 * Copyright 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 androidx.benchmark

import android.os.Build
import android.util.JsonWriter
import androidx.annotation.VisibleForTesting
import androidx.test.platform.app.InstrumentationRegistry
import java.io.File
import java.io.IOException

internal object ResultWriter {
    @VisibleForTesting
    internal val reports = ArrayList<BenchmarkState.Report>()

    fun appendReport(report: BenchmarkState.Report) {
        reports.add(report)

        if (Arguments.outputEnable) {
            // Currently, we just overwrite the whole file
            // Ideally, append for efficiency
            val packageName =
                InstrumentationRegistry.getInstrumentation().targetContext!!.packageName

            val file = File(Arguments.testOutputDir, "$packageName-benchmarkData.json")
            writeReport(file, reports)
            InstrumentationResults.reportAdditionalFileToCopy("results_json", file.absolutePath)
        }
    }

    @VisibleForTesting
    internal fun writeReport(file: File, reports: List<BenchmarkState.Report>) {
        file.run {
            if (!exists()) {
                parentFile?.mkdirs()
                try {
                    createNewFile()
                } catch (exception: IOException) {
                    throw IOException(
                        """
                            Failed to create file for benchmark report in:
                            $parent
                            Make sure the instrumentation argument additionalOutputDir is set to 
                            a writable directory on device. If using a version of Android Gradle 
                            Plugin that doesn't support additionalOutputDir, ensure your app's 
                            manifest file enables legacy storage behavior by adding the 
                            application attribute: android:requestLegacyExternalStorage="true"
                        """.trimIndent(),
                        exception
                    )
                }
            }

            val writer = JsonWriter(bufferedWriter())
            writer.setIndent("    ")

            writer.beginObject()

            writer.name("context").beginObject()
                .name("build").buildInfoObject()
                .name("cpuCoreCount").value(CpuInfo.coreDirs.size)
                .name("cpuLocked").value(CpuInfo.locked)
                .name("cpuMaxFreqHz").value(CpuInfo.maxFreqHz)
                .name("memTotalBytes").value(MemInfo.memTotalBytes)
                .name("sustainedPerformanceModeEnabled")
                .value(IsolationActivity.sustainedPerformanceModeInUse)
            writer.endObject()

            writer.name("benchmarks").beginArray()
            reports.forEach { writer.reportObject(it) }
            writer.endArray()

            writer.endObject()

            writer.flush()
            writer.close()
        }
    }

    private fun JsonWriter.buildInfoObject(): JsonWriter {
        beginObject()
            .name("device").value(Build.DEVICE)
            .name("fingerprint").value(Build.FINGERPRINT)
            .name("model").value(Build.MODEL)
            .name("version").beginObject().name("sdk").value(Build.VERSION.SDK_INT).endObject()
        return endObject()
    }

    private fun JsonWriter.reportObject(report: BenchmarkState.Report): JsonWriter {
        beginObject()
            .name("name").value(report.testName)
            .name("params").paramsObject(report)
            .name("className").value(report.className)
            .name("totalRunTimeNs").value(report.totalRunTimeNs)
            .name("metrics").metricsContainerObject(report.stats, report.data)
            .name("warmupIterations").value(report.warmupIterations)
            .name("repeatIterations").value(report.repeatIterations)
            .name("thermalThrottleSleepSeconds").value(report.thermalThrottleSleepSeconds)
        return endObject()
    }

    private fun JsonWriter.statsObject(
        stats: Stats
    ): JsonWriter {
        name("minimum").value(stats.min)
        name("maximum").value(stats.max)
        name("median").value(stats.median)
        return this
    }

    private fun JsonWriter.metricsContainerObject(
        stats: List<Stats>,
        data: List<List<Long>>
    ): JsonWriter {
        beginObject()
        for (i in 0..stats.lastIndex) {
            name(stats[i].name).beginObject()
            statsObject(stats[i])
            name("runs").beginArray()
            data[i].forEach { value(it) }
            endArray()
            endObject()
        }
        return endObject()
    }

    private fun JsonWriter.paramsObject(report: BenchmarkState.Report): JsonWriter {
        beginObject()
        getParams(report.testName).forEach { name(it.key).value(it.value) }
        return endObject()
    }

    private fun getParams(testName: String): Map<String, String> {
        val parameterStrStart = testName.indexOf('[')
        val parameterStrEnd = testName.lastIndexOf(']')

        val params = HashMap<String, String>()
        if (parameterStrStart >= 0 && parameterStrEnd >= 0) {
            val paramListString = testName.substring(parameterStrStart + 1, parameterStrEnd)
            paramListString.split(",").forEach { paramString ->
                val separatorIndex = paramString.indexOfFirst { it == ':' || it == '=' }
                if (separatorIndex in 1 until paramString.length - 1) {
                    val key = paramString.substring(0, separatorIndex)
                    val value = paramString.substring(separatorIndex + 1)
                    params[key] = value
                }
            }
        }
        return params
    }
}
