/*
 * Copyright 2018 The Bazel 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.
 */
package io.bazel.kotlin.builder.tasks.jvm

import com.google.devtools.build.lib.view.proto.Deps
import java.nio.file.Path
import java.nio.file.Paths
import java.util.*
import java.util.function.Predicate

internal class JdepsParser private constructor(private val filename: String, private val isImplicit: Predicate<String>) {
    private val packageSuffix: String = " ($filename)"

    private val depMap = HashMap<String, Deps.Dependency.Builder>()
    private val packages = HashSet<String>()

    private var mode = Mode.COLLECT_DEPS

    private fun consumeJarLine(classJarPath: String, kind: Deps.Dependency.Kind) {
        val path = Paths.get(classJarPath)

        // ignore absolute files, -- jdk jar paths etc.
        // only process jar files
        if (!(path.isAbsolute || !classJarPath.endsWith(".jar"))) {
            val entry = depMap.computeIfAbsent(classJarPath) {
                val depBuilder = Deps.Dependency.newBuilder()
                depBuilder.path = classJarPath
                depBuilder.kind = kind

                if (isImplicit.test(classJarPath)) {
                    depBuilder.kind = Deps.Dependency.Kind.IMPLICIT
                }
                depBuilder
            }

            // don't flip an implicit dep.
            if (entry.kind != Deps.Dependency.Kind.IMPLICIT) {
                entry.kind = kind
            }
        }
    }

    private enum class Mode {
        COLLECT_DEPS,
        DETERMINE_JDK,
        COLLECT_PACKAGES_JDK8,
        COLLECT_PACKAGES_JDK9
    }

    // maybe simplify this by tokenizing on whitespace and arrows.
    private fun processLine(line: String) {
        val trimmedLine = line.trim { it <= ' ' }
        when (mode) {
            Mode.COLLECT_DEPS -> if (!line.startsWith(" ")) {
                val parts = line.split(" -> ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
                if (parts.size == 2) {
                    if (parts[0] != filename) {
                        throw RuntimeException("should only get dependencies for dep: $filename")
                    }
                    consumeJarLine(parts[1], Deps.Dependency.Kind.EXPLICIT)
                }
            } else {
                mode = Mode.DETERMINE_JDK
                processLine(line)
            }
            Mode.DETERMINE_JDK -> {
                mode = Mode.COLLECT_PACKAGES_JDK8
                if (!line.endsWith(packageSuffix)) {
                    mode = Mode.COLLECT_PACKAGES_JDK9
                }
                processLine(line)
            }
            Mode.COLLECT_PACKAGES_JDK8 -> when {
                trimmedLine.endsWith(packageSuffix) -> packages.add(trimmedLine.substring(0, trimmedLine.length - packageSuffix.length))
                trimmedLine.startsWith("-> ") -> {
                    // ignore package detail lines, in the jdk8 format these start with arrows.
                }
                else -> throw RuntimeException("unexpected line while collecting packages: $line")
            }
            Mode.COLLECT_PACKAGES_JDK9 -> {
                val pkg = trimmedLine.split("\\s+".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
                packages.add(pkg[0])
            }
        }
    }

    companion object {
        fun pathSuffixMatchingPredicate(directory: Path, vararg jars: String): Predicate<String> {
            val suffixes = jars.map { directory.resolve(it).toString() }
            return Predicate { jar ->
                for (implicitJarsEnding in suffixes) {
                    if (jar.endsWith(implicitJarsEnding)) {
                        return@Predicate true
                    }
                }
                false
            }
        }

        fun parse(
            label: String,
            classJar: String,
            classPath: MutableList<String>,
            lines: List<String>,
            isImplicit: Predicate<String>
        ): Deps.Dependencies {
            val filename = Paths.get(classJar).fileName.toString()
            val jdepsParser = JdepsParser(filename, isImplicit)
            classPath.forEach { x -> jdepsParser.consumeJarLine(x, Deps.Dependency.Kind.UNUSED) }
            lines.forEach { jdepsParser.processLine(it) }

            val rootBuilder = Deps.Dependencies.newBuilder()
            rootBuilder.success = false
            rootBuilder.ruleLabel = label

            rootBuilder.addAllContainedPackage(jdepsParser.packages)
            jdepsParser.depMap.values.forEach { b -> rootBuilder.addDependency(b.build()) }

            rootBuilder.success = true
            return rootBuilder.build()
        }
    }
}