// Copyright 2020 The Monogon Project Authors.
//
// SPDX-License-Identifier: Apache-2.0
//
// 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 main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strings"

	"golang.org/x/mod/modfile"
)

// getTransitiveDeps is a hairy ball of heuristic used to find all recursively transitive dependencies of a given
// dependency.
// It downloads a given dependency using `go get`, and performs analysis of standard (go.mod/go.sum) and project-
// specific dependency management configuration/lock files in order to build a full view of all known, versioned
// transitive dependencies.
func (d *dependency) getTransitiveDeps() (map[string]*dependency, error) {
	// First, lock the dependency. Downloading it later will also return a sum, and we want to ensure both are the
	// same.
	err := d.lock()
	if err != nil {
		return nil, fmt.Errorf("could not lock: %v", err)
	}

	_, path, sum, err := d.download()
	if err != nil {
		return nil, fmt.Errorf("could not download: %v", err)
	}

	if sum != d.locked.sum {
		return nil, fmt.Errorf("inconsistent sum: %q downloaded, %q in shelf/lock", sum, d.locked.sum)
	}

	exists := func(p string) bool {
		full := fmt.Sprintf("%s/%s", path, p)
		if _, err := os.Stat(full); err == nil {
			return true
		}
		if err != nil && !os.IsExist(err) {
			panic(fmt.Sprintf("checking file %q: %v", full, err))
		}
		return false
	}

	read := func(p string) []byte {
		full := fmt.Sprintf("%s/%s", path, p)
		data, err := ioutil.ReadFile(full)
		if err != nil {
			panic(fmt.Sprintf("reading file %q: %v", full, err))
		}
		return data
	}

	requirements := make(map[string]*dependency)

	// Read & parse go.mod if present.
	var mf *modfile.File
	if exists("go.mod") {
		log.Printf("%q: parsing go.mod\n", d.importpath)
		data := read("go.mod")
		mf, err = modfile.Parse("go.mod", data, nil)
		if err != nil {
			return nil, fmt.Errorf("parsing go.mod in %s: %v", d.importpath, err)
		}
	}

	// If a go.mod file was present, interpret it to populate dependencies.
	if mf != nil {
		for _, req := range mf.Require {
			requirements[req.Mod.Path] = d.child(req.Mod.Path, req.Mod.Version)
		}
		for _, rep := range mf.Replace {
			// skip filesystem rewrites
			if rep.New.Version == "" {
				continue
			}

			requirements[rep.New.Path] = d.child(rep.New.Path, rep.New.Version)
		}
	}

	// Read parse, and interpret. go.sum if present.
	// This should bring into view all recursively transitive dependencies.
	if exists("go.sum") {
		log.Printf("%q: parsing go.sum", d.importpath)
		data := read("go.sum")
		for _, line := range strings.Split(string(data), "\n") {
			line = strings.TrimSpace(line)
			if line == "" {
				continue
			}

			parts := strings.Fields(line)
			if len(parts) != 3 {
				return nil, fmt.Errorf("parsing go.sum: unparseable line %q", line)
			}

			importpath, version := parts[0], parts[1]

			// Skip if already created from go.mod.
			// TODO(q3k): error if go.sum and go.mod disagree?
			if _, ok := requirements[importpath]; ok {
				continue
			}

			if strings.HasSuffix(version, "/go.mod") {
				version = strings.TrimSuffix(version, "/go.mod")
			}
			requirements[importpath] = d.child(importpath, version)
		}
	}

	// Special case: root Kubernetes repo - rewrite staging/ deps to k8s.io/ at correct versions, quit early.
	// Kubernetes vendors all dependencies into vendor/, and also contains sub-projects (components) in staging/.
	// This converts all staging dependencies into appropriately versioned k8s.io/<dep> paths.
	if d.importpath == "k8s.io/kubernetes" {
		log.Printf("%q: special case for Kubernetes main repository", d.importpath)
		if mf == nil {
			return nil, fmt.Errorf("k8s.io/kubernetes needs a go.mod")
		}
		// extract the version, turn into component version
		version := d.version
		if !strings.HasPrefix(version, "v") {
			return nil, fmt.Errorf("invalid version format for k8s: %q", version)
		}
		version = version[1:]
		componentVersion := fmt.Sprintf("kubernetes-%s", version)

		// find all k8s.io 'components'
		components := make(map[string]bool)
		for _, rep := range mf.Replace {
			if !strings.HasPrefix(rep.Old.Path, "k8s.io/") || !strings.HasPrefix(rep.New.Path, "./staging/src/") {
				continue
			}
			components[rep.Old.Path] = true
		}

		// add them to planner at the 'kubernetes-$ver' tag
		for component, _ := range components {
			requirements[component] = d.child(component, componentVersion)
		}
		return requirements, nil
	}

	// Special case: github.com/containerd/containerd: read vendor.conf.
	if d.importpath == "github.com/containerd/containerd" {
		log.Printf("%q: special case for containerd", d.importpath)
		if !exists("vendor.conf") {
			panic("containerd needs vendor.conf")
		}
		data := read("vendor.conf")
		for _, line := range strings.Split(string(data), "\n") {
			// strip comments
			parts := strings.SplitN(line, "#", 2)
			line = parts[0]

			// skip empty contents
			line = strings.TrimSpace(line)
			if line == "" {
				continue
			}

			// read dep/version pairs
			parts = strings.Fields(line)
			if len(parts) < 2 {
				return nil, fmt.Errorf("unparseable line in containerd vendor.conf: %q", line)
			}
			importpath, version := parts[0], parts[1]
			requirements[importpath] = d.child(importpath, version)
		}
		return requirements, nil
	}

	return requirements, nil
}
