// Copyright 2024 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 modindex

import (
	"bufio"
	"encoding/csv"
	"errors"
	"fmt"
	"hash/crc64"
	"io"
	"io/fs"
	"log"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"
)

/*
The on-disk index is a text file.
The first 3 lines are header information containing CurrentVersion,
the value of GOMODCACHE, and the validity date of the index.
(This is when the code started building the index.)
Following the header are sections of lines, one section for each
import path. These sections are sorted by package name.
The first line of each section, marked by a leading :, contains
the package name, the import path, the name of the directory relative
to GOMODCACHE, and its semantic version.
The rest of each section consists of one line per exported symbol.
The lines are sorted by the symbol's name and contain the name,
an indication of its lexical type (C, T, V, F), and if it is the
name of a function, information about the signature.

The fields in the section header lines are separated by commas, and
in the unlikely event this would be confusing, the csv package is used
to write (and read) them.

In the lines containing exported names, C=const, V=var, T=type, F=func.
If it is a func, the next field is the number of returned values,
followed by pairs consisting of formal parameter names and types.
All these fields are separated by spaces. Any spaces in a type
(e.g., chan struct{}) are replaced by $s on the disk. The $s are
turned back into spaces when read.

Here is an index header (the comments are not part of the index):
0                                      // version (of the index format)
/usr/local/google/home/pjw/go/pkg/mod  // GOMODCACHE
2024-09-11 18:55:09                    // validity date of the index

Here is an index section:
:yaml,gopkg.in/yaml.v1,gopkg.in/yaml.v1@v1.0.0-20140924161607-9f9df34309c0,v1.0.0-20140924161607-9f9df34309c0
Getter T
Marshal F 2 in interface{}
Setter T
Unmarshal F 1 in []byte out interface{}

The package name is yaml, the import path is gopkg.in/yaml.v1.
Getter and Setter are types, and Marshal and Unmarshal are functions.
The latter returns one value and has two arguments, 'in' and 'out'
whose types are []byte and interface{}.
*/

// CurrentVersion tells readers about the format of the index.
const CurrentVersion int = 0

// Index is returned by ReadIndex().
type Index struct {
	Version  int
	Cachedir Abspath   // The directory containing the module cache
	Changed  time.Time // The index is up to date as of Changed
	Entries  []Entry
}

// An Entry contains information for an import path.
type Entry struct {
	Dir        Relpath // directory in modcache
	ImportPath string
	PkgName    string
	Version    string
	//ModTime    STime    // is this useful?
	Names []string // exported names and information
}

// ReadIndex reads the latest version of the on-disk index
// for the cache directory cd.
// It returns (nil, nil) if there is no index, but returns
// a non-nil error if the index exists but could not be read.
func ReadIndex(cachedir string) (*Index, error) {
	cachedir, err := filepath.Abs(cachedir)
	if err != nil {
		return nil, err
	}
	cd := Abspath(cachedir)
	dir, err := IndexDir()
	if err != nil {
		return nil, err
	}
	base := indexNameBase(cd)
	iname := filepath.Join(dir, base)
	buf, err := os.ReadFile(iname)
	if err != nil {
		if errors.Is(err, fs.ErrNotExist) {
			return nil, nil
		}
		return nil, fmt.Errorf("cannot read %s: %w", iname, err)
	}
	fname := filepath.Join(dir, string(buf))
	fd, err := os.Open(fname)
	if err != nil {
		return nil, err
	}
	defer fd.Close()
	r := bufio.NewReader(fd)
	ix, err := readIndexFrom(cd, r)
	if err != nil {
		return nil, err
	}
	return ix, nil
}

func readIndexFrom(cd Abspath, bx io.Reader) (*Index, error) {
	b := bufio.NewScanner(bx)
	var ans Index
	// header
	ok := b.Scan()
	if !ok {
		return nil, fmt.Errorf("unexpected scan error")
	}
	l := b.Text()
	var err error
	ans.Version, err = strconv.Atoi(l)
	if err != nil {
		return nil, err
	}
	if ans.Version != CurrentVersion {
		return nil, fmt.Errorf("got version %d, expected %d", ans.Version, CurrentVersion)
	}
	if ok := b.Scan(); !ok {
		return nil, fmt.Errorf("scanner error reading cachedir")
	}
	ans.Cachedir = Abspath(b.Text())
	if ok := b.Scan(); !ok {
		return nil, fmt.Errorf("scanner error reading index creation time")
	}
	// TODO(pjw): need to check that this is the expected cachedir
	// so the tag should be passed in to this function
	ans.Changed, err = time.ParseInLocation(time.DateTime, b.Text(), time.Local)
	if err != nil {
		return nil, err
	}
	var curEntry *Entry
	for b.Scan() {
		v := b.Text()
		if v[0] == ':' {
			if curEntry != nil {
				ans.Entries = append(ans.Entries, *curEntry)
			}
			// as directories may contain commas and quotes, they need to be read as csv.
			rdr := strings.NewReader(v[1:])
			cs := csv.NewReader(rdr)
			flds, err := cs.Read()
			if err != nil {
				return nil, err
			}
			if len(flds) != 4 {
				return nil, fmt.Errorf("header contains %d fields, not 4: %q", len(v), v)
			}
			curEntry = &Entry{PkgName: flds[0], ImportPath: flds[1], Dir: toRelpath(cd, flds[2]), Version: flds[3]}
			continue
		}
		curEntry.Names = append(curEntry.Names, v)
	}
	if curEntry != nil {
		ans.Entries = append(ans.Entries, *curEntry)
	}
	if err := b.Err(); err != nil {
		return nil, fmt.Errorf("scanner failed %v", err)
	}
	return &ans, nil
}

// write the index as a text file
func writeIndex(cachedir Abspath, ix *Index) error {
	dir, err := IndexDir()
	if err != nil {
		return err
	}
	ipat := fmt.Sprintf("index-%d-*", CurrentVersion)
	fd, err := os.CreateTemp(dir, ipat)
	if err != nil {
		return err // can this happen?
	}
	defer fd.Close()
	if err := writeIndexToFile(ix, fd); err != nil {
		return err
	}
	content := fd.Name()
	content = filepath.Base(content)
	base := indexNameBase(cachedir)
	nm := filepath.Join(dir, base)
	err = os.WriteFile(nm, []byte(content), 0666)
	if err != nil {
		return err
	}
	return nil
}

func writeIndexToFile(x *Index, fd *os.File) error {
	cnt := 0
	w := bufio.NewWriter(fd)
	fmt.Fprintf(w, "%d\n", x.Version)
	fmt.Fprintf(w, "%s\n", x.Cachedir)
	// round the time down
	tm := x.Changed.Add(-time.Second / 2)
	fmt.Fprintf(w, "%s\n", tm.Format(time.DateTime))
	for _, e := range x.Entries {
		if e.ImportPath == "" {
			continue // shouldn't happen
		}
		// PJW: maybe always write these headers as csv?
		if strings.ContainsAny(string(e.Dir), ",\"") {
			log.Printf("DIR: %s", e.Dir)
			cw := csv.NewWriter(w)
			cw.Write([]string{":" + e.PkgName, e.ImportPath, string(e.Dir), e.Version})
			cw.Flush()
		} else {
			fmt.Fprintf(w, ":%s,%s,%s,%s\n", e.PkgName, e.ImportPath, e.Dir, e.Version)
		}
		for _, x := range e.Names {
			fmt.Fprintf(w, "%s\n", x)
			cnt++
		}
	}
	if err := w.Flush(); err != nil {
		return err
	}
	return nil
}

// tests can override this
var IndexDir = indexDir

// IndexDir computes the directory containing the index
func indexDir() (string, error) {
	dir, err := os.UserCacheDir()
	if err != nil {
		return "", fmt.Errorf("cannot open UserCacheDir, %w", err)
	}
	return filepath.Join(dir, "go", "imports"), nil
}

// return the base name of the file containing the name of the current index
func indexNameBase(cachedir Abspath) string {
	// crc64 is a way to convert path names into 16 hex digits.
	h := crc64.Checksum([]byte(cachedir), crc64.MakeTable(crc64.ECMA))
	fname := fmt.Sprintf("index-name-%d-%016x", CurrentVersion, h)
	return fname
}
