// 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 (
	"golang.org/x/tools/gopls/internal/lsp/source"
	"golang.org/x/tools/gopls/internal/span"
	"golang.org/x/tools/internal/persistent"
)

type filesMap struct {
	impl       *persistent.Map[span.URI, source.FileHandle]
	overlayMap map[span.URI]*Overlay // the subset that are overlays
}

func newFilesMap() filesMap {
	return filesMap{
		impl:       new(persistent.Map[span.URI, source.FileHandle]),
		overlayMap: make(map[span.URI]*Overlay),
	}
}

func (m filesMap) Clone() filesMap {
	overlays := make(map[span.URI]*Overlay, len(m.overlayMap))
	for k, v := range m.overlayMap {
		overlays[k] = v
	}
	return filesMap{
		impl:       m.impl.Clone(),
		overlayMap: overlays,
	}
}

func (m filesMap) Destroy() {
	m.impl.Destroy()
}

func (m filesMap) Get(key span.URI) (source.FileHandle, bool) {
	value, ok := m.impl.Get(key)
	if !ok {
		return nil, false
	}
	return value.(source.FileHandle), true
}

func (m filesMap) Range(do func(key span.URI, value source.FileHandle)) {
	m.impl.Range(do)
}

func (m filesMap) Set(key span.URI, value source.FileHandle) {
	m.impl.Set(key, value, nil)

	if o, ok := value.(*Overlay); ok {
		m.overlayMap[key] = o
	} else {
		// Setting a non-overlay must delete the corresponding overlay, to preserve
		// the accuracy of the overlay set.
		delete(m.overlayMap, key)
	}
}

func (m *filesMap) Delete(key span.URI) {
	m.impl.Delete(key)
	delete(m.overlayMap, key)
}

// overlays returns a new unordered array of overlay files.
func (m filesMap) overlays() []*Overlay {
	// In practice we will always have at least one overlay, so there is no need
	// to optimize for the len=0 case by returning a nil slice.
	overlays := make([]*Overlay, 0, len(m.overlayMap))
	for _, o := range m.overlayMap {
		overlays = append(overlays, o)
	}
	return overlays
}

type knownDirsSet struct {
	impl *persistent.Map[span.URI, struct{}]
}

func newKnownDirsSet() knownDirsSet {
	return knownDirsSet{
		impl: new(persistent.Map[span.URI, struct{}]),
	}
}

func (s knownDirsSet) Clone() knownDirsSet {
	return knownDirsSet{
		impl: s.impl.Clone(),
	}
}

func (s knownDirsSet) Destroy() {
	s.impl.Destroy()
}

func (s knownDirsSet) Contains(key span.URI) bool {
	_, ok := s.impl.Get(key)
	return ok
}

func (s knownDirsSet) Range(do func(key span.URI)) {
	s.impl.Range(func(key span.URI, value struct{}) {
		do(key)
	})
}

func (s knownDirsSet) SetAll(other knownDirsSet) {
	s.impl.SetAll(other.impl)
}

func (s knownDirsSet) Insert(key span.URI) {
	s.impl.Set(key, struct{}{}, nil)
}

func (s knownDirsSet) Remove(key span.URI) {
	s.impl.Delete(key)
}
