// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

// This file contains functions and apis that support merging of
// meta-data information.  It helps implement the "merge", "subtract",
// and "intersect" subcommands.

import (
	"crypto/md5"
	"fmt"
	"internal/coverage"
	"internal/coverage/calloc"
	"internal/coverage/cmerge"
	"internal/coverage/decodecounter"
	"internal/coverage/decodemeta"
	"internal/coverage/encodecounter"
	"internal/coverage/encodemeta"
	"internal/coverage/slicewriter"
	"io"
	"os"
	"path/filepath"
	"sort"
	"time"
	"unsafe"
)

// metaMerge provides state and methods to help manage the process
// of selecting or merging meta data files. There are three cases
// of interest here: the "-pcombine" flag provided by merge, the
// "-pkg" option provided by all merge/subtract/intersect, and
// a regular vanilla merge with no package selection
//
// In the -pcombine case, we're essentially glomming together all the
// meta-data for all packages and all functions, meaning that
// everything we see in a given package needs to be added into the
// meta-data file builder; we emit a single meta-data file at the end
// of the run.
//
// In the -pkg case, we will typically emit a single meta-data file
// per input pod, where that new meta-data file contains entries for
// just the selected packages.
//
// In the third case (vanilla merge with no combining or package
// selection) we can carry over meta-data files without touching them
// at all (only counter data files will be merged).
type metaMerge struct {
	calloc.BatchCounterAlloc
	cmerge.Merger
	// maps package import path to package state
	pkm map[string]*pkstate
	// list of packages
	pkgs []*pkstate
	// current package state
	p *pkstate
	// current pod state
	pod *podstate
	// counter data file osargs/goos/goarch state
	astate *argstate
}

// pkstate
type pkstate struct {
	// index of package within meta-data file.
	pkgIdx uint32
	// this maps function index within the package to counter data payload
	ctab map[uint32]decodecounter.FuncPayload
	// pointer to meta-data blob for package
	mdblob []byte
	// filled in only for -pcombine merges
	*pcombinestate
}

type podstate struct {
	pmm      map[pkfunc]decodecounter.FuncPayload
	mdf      string
	mfr      *decodemeta.CoverageMetaFileReader
	fileHash [16]byte
}

type pkfunc struct {
	pk, fcn uint32
}

// pcombinestate
type pcombinestate struct {
	// Meta-data builder for the package.
	cmdb *encodemeta.CoverageMetaDataBuilder
	// Maps function meta-data hash to new function index in the
	// new version of the package we're building.
	ftab map[[16]byte]uint32
}

func newMetaMerge() *metaMerge {
	return &metaMerge{
		pkm:    make(map[string]*pkstate),
		astate: &argstate{},
	}
}

func (mm *metaMerge) visitMetaDataFile(mdf string, mfr *decodemeta.CoverageMetaFileReader) {
	dbgtrace(2, "visitMetaDataFile(mdf=%s)", mdf)

	// Record meta-data file name.
	mm.pod.mdf = mdf
	// Keep a pointer to the file-level reader.
	mm.pod.mfr = mfr
	// Record file hash.
	mm.pod.fileHash = mfr.FileHash()
	// Counter mode and granularity -- detect and record clashes here.
	newgran := mfr.CounterGranularity()
	newmode := mfr.CounterMode()
	if err := mm.SetModeAndGranularity(mdf, newmode, newgran); err != nil {
		fatal("%v", err)
	}
}

func (mm *metaMerge) beginCounterDataFile(cdr *decodecounter.CounterDataReader) {
	state := argvalues{
		osargs: cdr.OsArgs(),
		goos:   cdr.Goos(),
		goarch: cdr.Goarch(),
	}
	mm.astate.Merge(state)
}

func copyMetaDataFile(inpath, outpath string) {
	inf, err := os.Open(inpath)
	if err != nil {
		fatal("opening input meta-data file %s: %v", inpath, err)
	}
	defer inf.Close()

	fi, err := inf.Stat()
	if err != nil {
		fatal("accessing input meta-data file %s: %v", inpath, err)
	}

	outf, err := os.OpenFile(outpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, fi.Mode())
	if err != nil {
		fatal("opening output meta-data file %s: %v", outpath, err)
	}

	_, err = io.Copy(outf, inf)
	outf.Close()
	if err != nil {
		fatal("writing output meta-data file %s: %v", outpath, err)
	}
}

func (mm *metaMerge) beginPod() {
	mm.pod = &podstate{
		pmm: make(map[pkfunc]decodecounter.FuncPayload),
	}
}

// metaEndPod handles actions needed when we're done visiting all of
// the things in a pod -- counter files and meta-data file. There are
// three cases of interest here:
//
// Case 1: in an unconditional merge (we're not selecting a specific set of
// packages using "-pkg", and the "-pcombine" option is not in use),
// we can simply copy over the meta-data file from input to output.
//
// Case 2: if this is a select merge (-pkg is in effect), then at
// this point we write out a new smaller meta-data file that includes
// only the packages of interest. At this point we also emit a merged
// counter data file as well.
//
// Case 3: if "-pcombine" is in effect, we don't write anything at
// this point (all writes will happen at the end of the run).
func (mm *metaMerge) endPod(pcombine bool) {
	if pcombine {
		// Just clear out the pod data, we'll do all the
		// heavy lifting at the end.
		mm.pod = nil
		return
	}

	finalHash := mm.pod.fileHash
	if matchpkg != nil {
		// Emit modified meta-data file for this pod.
		finalHash = mm.emitMeta(*outdirflag, pcombine)
	} else {
		// Copy meta-data file for this pod to the output directory.
		inpath := mm.pod.mdf
		mdfbase := filepath.Base(mm.pod.mdf)
		outpath := filepath.Join(*outdirflag, mdfbase)
		copyMetaDataFile(inpath, outpath)
	}

	// Emit accumulated counter data for this pod.
	mm.emitCounters(*outdirflag, finalHash)

	// Reset package state.
	mm.pkm = make(map[string]*pkstate)
	mm.pkgs = nil
	mm.pod = nil

	// Reset counter mode and granularity
	mm.ResetModeAndGranularity()
}

// emitMeta encodes and writes out a new coverage meta-data file as
// part of a merge operation, specifically a merge with the
// "-pcombine" flag.
func (mm *metaMerge) emitMeta(outdir string, pcombine bool) [16]byte {
	fh := md5.New()
	blobs := [][]byte{}
	tlen := uint64(unsafe.Sizeof(coverage.MetaFileHeader{}))
	for _, p := range mm.pkgs {
		var blob []byte
		if pcombine {
			mdw := &slicewriter.WriteSeeker{}
			p.cmdb.Emit(mdw)
			blob = mdw.BytesWritten()
		} else {
			blob = p.mdblob
		}
		ph := md5.Sum(blob)
		blobs = append(blobs, blob)
		if _, err := fh.Write(ph[:]); err != nil {
			panic(fmt.Sprintf("internal error: md5 sum failed: %v", err))
		}
		tlen += uint64(len(blob))
	}
	var finalHash [16]byte
	fhh := fh.Sum(nil)
	copy(finalHash[:], fhh)

	// Open meta-file for writing.
	fn := fmt.Sprintf("%s.%x", coverage.MetaFilePref, finalHash)
	fpath := filepath.Join(outdir, fn)
	mf, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
	if err != nil {
		fatal("unable to open output meta-data file %s: %v", fpath, err)
	}

	// Encode and write.
	mfw := encodemeta.NewCoverageMetaFileWriter(fpath, mf)
	err = mfw.Write(finalHash, blobs, mm.Mode(), mm.Granularity())
	if err != nil {
		fatal("error writing %s: %v\n", fpath, err)
	}
	return finalHash
}

func (mm *metaMerge) emitCounters(outdir string, metaHash [16]byte) {
	// Open output file. The file naming scheme is intended to mimic
	// that used when running a coverage-instrumented binary, for
	// consistency (however the process ID is not meaningful here, so
	// use a value of zero).
	var dummyPID int
	fn := fmt.Sprintf(coverage.CounterFileTempl, coverage.CounterFilePref, metaHash, dummyPID, time.Now().UnixNano())
	fpath := filepath.Join(outdir, fn)
	cf, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
	if err != nil {
		fatal("opening counter data file %s: %v", fpath, err)
	}
	defer func() {
		if err := cf.Close(); err != nil {
			fatal("error closing output meta-data file %s: %v", fpath, err)
		}
	}()

	args := mm.astate.ArgsSummary()
	cfw := encodecounter.NewCoverageDataWriter(cf, coverage.CtrULeb128)
	if err := cfw.Write(metaHash, args, mm); err != nil {
		fatal("counter file write failed: %v", err)
	}
	mm.astate = &argstate{}
}

// VisitFuncs is used while writing the counter data files; it
// implements the 'VisitFuncs' method required by the interface
// internal/coverage/encodecounter/CounterVisitor.
func (mm *metaMerge) VisitFuncs(f encodecounter.CounterVisitorFn) error {
	if *verbflag >= 4 {
		fmt.Printf("counterVisitor invoked\n")
	}
	// For each package, for each function, construct counter
	// array and then call "f" on it.
	for pidx, p := range mm.pkgs {
		fids := make([]int, 0, len(p.ctab))
		for fid := range p.ctab {
			fids = append(fids, int(fid))
		}
		sort.Ints(fids)
		if *verbflag >= 4 {
			fmt.Printf("fids for pk=%d: %+v\n", pidx, fids)
		}
		for _, fid := range fids {
			fp := p.ctab[uint32(fid)]
			if *verbflag >= 4 {
				fmt.Printf("counter write for pk=%d fid=%d len(ctrs)=%d\n", pidx, fid, len(fp.Counters))
			}
			if err := f(uint32(pidx), uint32(fid), fp.Counters); err != nil {
				return err
			}
		}
	}
	return nil
}

func (mm *metaMerge) visitPackage(pd *decodemeta.CoverageMetaDataDecoder, pkgIdx uint32, pcombine bool) {
	p, ok := mm.pkm[pd.PackagePath()]
	if !ok {
		p = &pkstate{
			pkgIdx: uint32(len(mm.pkgs)),
		}
		mm.pkgs = append(mm.pkgs, p)
		mm.pkm[pd.PackagePath()] = p
		if pcombine {
			p.pcombinestate = new(pcombinestate)
			cmdb, err := encodemeta.NewCoverageMetaDataBuilder(pd.PackagePath(), pd.PackageName(), pd.ModulePath())
			if err != nil {
				fatal("fatal error creating meta-data builder: %v", err)
			}
			dbgtrace(2, "install new pkm entry for package %s pk=%d", pd.PackagePath(), pkgIdx)
			p.cmdb = cmdb
			p.ftab = make(map[[16]byte]uint32)
		} else {
			var err error
			p.mdblob, err = mm.pod.mfr.GetPackagePayload(pkgIdx, nil)
			if err != nil {
				fatal("error extracting package %d payload from %s: %v",
					pkgIdx, mm.pod.mdf, err)
			}
		}
		p.ctab = make(map[uint32]decodecounter.FuncPayload)
	}
	mm.p = p
}

func (mm *metaMerge) visitFuncCounterData(data decodecounter.FuncPayload) {
	key := pkfunc{pk: data.PkgIdx, fcn: data.FuncIdx}
	val := mm.pod.pmm[key]
	// FIXME: in theory either A) len(val.Counters) is zero, or B)
	// the two lengths are equal. Assert if not? Of course, we could
	// see odd stuff if there is source file skew.
	if *verbflag > 4 {
		fmt.Printf("visit pk=%d fid=%d len(counters)=%d\n", data.PkgIdx, data.FuncIdx, len(data.Counters))
	}
	if len(val.Counters) < len(data.Counters) {
		t := val.Counters
		val.Counters = mm.AllocateCounters(len(data.Counters))
		copy(val.Counters, t)
	}
	err, overflow := mm.MergeCounters(val.Counters, data.Counters)
	if err != nil {
		fatal("%v", err)
	}
	if overflow {
		warn("uint32 overflow during counter merge")
	}
	mm.pod.pmm[key] = val
}

func (mm *metaMerge) visitFunc(pkgIdx uint32, fnIdx uint32, fd *coverage.FuncDesc, verb string, pcombine bool) {
	if *verbflag >= 3 {
		fmt.Printf("visit pk=%d fid=%d func %s\n", pkgIdx, fnIdx, fd.Funcname)
	}

	var counters []uint32
	key := pkfunc{pk: pkgIdx, fcn: fnIdx}
	v, haveCounters := mm.pod.pmm[key]
	if haveCounters {
		counters = v.Counters
	}

	if pcombine {
		// If the merge is running in "combine programs" mode, then hash
		// the function and look it up in the package ftab to see if we've
		// encountered it before. If we haven't, then register it with the
		// meta-data builder.
		fnhash := encodemeta.HashFuncDesc(fd)
		gfidx, ok := mm.p.ftab[fnhash]
		if !ok {
			// We haven't seen this function before, need to add it to
			// the meta data.
			gfidx = uint32(mm.p.cmdb.AddFunc(*fd))
			mm.p.ftab[fnhash] = gfidx
			if *verbflag >= 3 {
				fmt.Printf("new meta entry for fn %s fid=%d\n", fd.Funcname, gfidx)
			}
		}
		fnIdx = gfidx
	}
	if !haveCounters {
		return
	}

	// Install counters in package ctab.
	gfp, ok := mm.p.ctab[fnIdx]
	if ok {
		if verb == "subtract" || verb == "intersect" {
			panic("should never see this for intersect/subtract")
		}
		if *verbflag >= 3 {
			fmt.Printf("counter merge for %s fidx=%d\n", fd.Funcname, fnIdx)
		}
		// Merge.
		err, overflow := mm.MergeCounters(gfp.Counters, counters)
		if err != nil {
			fatal("%v", err)
		}
		if overflow {
			warn("uint32 overflow during counter merge")
		}
		mm.p.ctab[fnIdx] = gfp
	} else {
		if *verbflag >= 3 {
			fmt.Printf("null merge for %s fidx %d\n", fd.Funcname, fnIdx)
		}
		gfp := v
		gfp.PkgIdx = mm.p.pkgIdx
		gfp.FuncIdx = fnIdx
		mm.p.ctab[fnIdx] = gfp
	}
}
