// 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
}
