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

import (
	"iter"
	"path/filepath"

	"golang.org/x/tools/gopls/internal/file"
	"golang.org/x/tools/gopls/internal/protocol"
	"golang.org/x/tools/gopls/internal/util/persistent"
)

// A fileMap maps files in the snapshot, with some additional bookkeeping:
// It keeps track of overlays as well as directories containing any observed
// file.
type fileMap struct {
	files    *persistent.Map[protocol.DocumentURI, file.Handle]
	overlays *persistent.Map[protocol.DocumentURI, *overlay] // the subset of files that are overlays
	dirs     *persistent.Set[string]                         // all dirs containing files; if nil, dirs have not been initialized
}

func newFileMap() *fileMap {
	return &fileMap{
		files:    new(persistent.Map[protocol.DocumentURI, file.Handle]),
		overlays: new(persistent.Map[protocol.DocumentURI, *overlay]),
		dirs:     new(persistent.Set[string]),
	}
}

// clone creates a copy of the fileMap, incorporating the changes specified by
// the changes map.
func (m *fileMap) clone(changes map[protocol.DocumentURI]file.Handle) *fileMap {
	m2 := &fileMap{
		files:    m.files.Clone(),
		overlays: m.overlays.Clone(),
	}
	if m.dirs != nil {
		m2.dirs = m.dirs.Clone()
	}

	// Handle file changes.
	//
	// Note, we can't simply delete the file unconditionally and let it be
	// re-read by the snapshot, as (1) the snapshot must always observe all
	// overlays, and (2) deleting a file forces directories to be reevaluated, as
	// it may be the last file in a directory. We want to avoid that work in the
	// common case where a file has simply changed.
	//
	// For that reason, we also do this in two passes, processing deletions
	// first, as a set before a deletion would result in pointless work.
	for uri, fh := range changes {
		if !fileExists(fh) {
			m2.delete(uri)
		}
	}
	for uri, fh := range changes {
		if fileExists(fh) {
			m2.set(uri, fh)
		}
	}
	return m2
}

func (m *fileMap) destroy() {
	m.files.Destroy()
	m.overlays.Destroy()
	if m.dirs != nil {
		m.dirs.Destroy()
	}
}

// get returns the file handle mapped by the given key, or (nil, false) if the
// key is not present.
func (m *fileMap) get(key protocol.DocumentURI) (file.Handle, bool) {
	return m.files.Get(key)
}

// all returns the sequence of (uri, fh) entries in the map.
func (m *fileMap) all() iter.Seq2[protocol.DocumentURI, file.Handle] {
	return m.files.All()
}

// set stores the given file handle for key, updating overlays and directories
// accordingly.
func (m *fileMap) set(key protocol.DocumentURI, fh file.Handle) {
	m.files.Set(key, fh, nil)

	// update overlays
	if o, ok := fh.(*overlay); ok {
		m.overlays.Set(key, o, nil)
	} else {
		// Setting a non-overlay must delete the corresponding overlay, to preserve
		// the accuracy of the overlay set.
		m.overlays.Delete(key)
	}

	// update dirs, if they have been computed
	if m.dirs != nil {
		m.addDirs(key)
	}
}

// addDirs adds all directories containing u to the dirs set.
func (m *fileMap) addDirs(u protocol.DocumentURI) {
	dir := u.DirPath()
	for dir != "" && !m.dirs.Contains(dir) {
		m.dirs.Add(dir)
		dir = filepath.Dir(dir)
	}
}

// delete removes a file from the map, and updates overlays and dirs
// accordingly.
func (m *fileMap) delete(key protocol.DocumentURI) {
	m.files.Delete(key)
	m.overlays.Delete(key)

	// Deleting a file may cause the set of dirs to shrink; therefore we must
	// re-evaluate the dir set.
	//
	// Do this lazily, to avoid work if there are multiple deletions in a row.
	if m.dirs != nil {
		m.dirs.Destroy()
		m.dirs = nil
	}
}

// getOverlays returns a new unordered array of overlay files.
func (m *fileMap) getOverlays() []*overlay {
	var overlays []*overlay
	for _, o := range m.overlays.All() {
		overlays = append(overlays, o)
	}
	return overlays
}

// getDirs reports returns the set of dirs observed by the fileMap.
//
// This operation mutates the fileMap.
// The result must not be mutated by the caller.
func (m *fileMap) getDirs() *persistent.Set[string] {
	if m.dirs == nil {
		m.dirs = new(persistent.Set[string])
		for uri := range m.files.All() {
			m.addDirs(uri)
		}
	}
	return m.dirs
}
