// Copyright 2020 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 (
	"context"
	"fmt"
	"reflect"
	"strings"
	"sync"
	"time"

	"golang.org/x/tools/internal/event"
	"golang.org/x/tools/internal/event/keys"
	"golang.org/x/tools/internal/gocommand"
	"golang.org/x/tools/internal/imports"
	"golang.org/x/tools/internal/lsp/source"
)

type importsState struct {
	ctx context.Context

	mu                   sync.Mutex
	processEnv           *imports.ProcessEnv
	cleanupProcessEnv    func()
	cacheRefreshDuration time.Duration
	cacheRefreshTimer    *time.Timer
	cachedModFileHash    string
	cachedBuildFlags     []string
}

func (s *importsState) runProcessEnvFunc(ctx context.Context, snapshot *snapshot, fn func(*imports.Options) error) error {
	s.mu.Lock()
	defer s.mu.Unlock()

	// Find the hash of the active mod file, if any. Using the unsaved content
	// is slightly wasteful, since we'll drop caches a little too often, but
	// the mod file shouldn't be changing while people are autocompleting.
	var modFileHash string
	if snapshot.workspaceMode()&usesWorkspaceModule == 0 {
		for m := range snapshot.workspace.getActiveModFiles() { // range to access the only element
			modFH, err := snapshot.GetFile(ctx, m)
			if err != nil {
				return err
			}
			modFileHash = modFH.FileIdentity().Hash
		}
	} else {
		modFile, err := snapshot.workspace.modFile(ctx, snapshot)
		if err != nil {
			return err
		}
		modBytes, err := modFile.Format()
		if err != nil {
			return err
		}
		modFileHash = hashContents(modBytes)
	}

	// view.goEnv is immutable -- changes make a new view. Options can change.
	// We can't compare build flags directly because we may add -modfile.
	snapshot.view.optionsMu.Lock()
	localPrefix := snapshot.view.options.Local
	currentBuildFlags := snapshot.view.options.BuildFlags
	changed := !reflect.DeepEqual(currentBuildFlags, s.cachedBuildFlags) ||
		snapshot.view.options.VerboseOutput != (s.processEnv.Logf != nil) ||
		modFileHash != s.cachedModFileHash
	snapshot.view.optionsMu.Unlock()

	// If anything relevant to imports has changed, clear caches and
	// update the processEnv. Clearing caches blocks on any background
	// scans.
	if changed {
		// As a special case, skip cleanup the first time -- we haven't fully
		// initialized the environment yet and calling GetResolver will do
		// unnecessary work and potentially mess up the go.mod file.
		if s.cleanupProcessEnv != nil {
			if resolver, err := s.processEnv.GetResolver(); err == nil {
				if modResolver, ok := resolver.(*imports.ModuleResolver); ok {
					modResolver.ClearForNewMod()
				}
			}
			s.cleanupProcessEnv()
		}
		s.cachedModFileHash = modFileHash
		s.cachedBuildFlags = currentBuildFlags
		var err error
		s.cleanupProcessEnv, err = s.populateProcessEnv(ctx, snapshot)
		if err != nil {
			return err
		}
	}

	// Run the user function.
	opts := &imports.Options{
		// Defaults.
		AllErrors:   true,
		Comments:    true,
		Fragment:    true,
		FormatOnly:  false,
		TabIndent:   true,
		TabWidth:    8,
		Env:         s.processEnv,
		LocalPrefix: localPrefix,
	}

	if err := fn(opts); err != nil {
		return err
	}

	if s.cacheRefreshTimer == nil {
		// Don't refresh more than twice per minute.
		delay := 30 * time.Second
		// Don't spend more than a couple percent of the time refreshing.
		if adaptive := 50 * s.cacheRefreshDuration; adaptive > delay {
			delay = adaptive
		}
		s.cacheRefreshTimer = time.AfterFunc(delay, s.refreshProcessEnv)
	}

	return nil
}

// populateProcessEnv sets the dynamically configurable fields for the view's
// process environment. Assumes that the caller is holding the s.view.importsMu.
func (s *importsState) populateProcessEnv(ctx context.Context, snapshot *snapshot) (cleanup func(), err error) {
	pe := s.processEnv

	if snapshot.view.Options().VerboseOutput {
		pe.Logf = func(format string, args ...interface{}) {
			event.Log(ctx, fmt.Sprintf(format, args...))
		}
	} else {
		pe.Logf = nil
	}

	// Take an extra reference to the snapshot so that its workspace directory
	// (if any) isn't destroyed while we're using it.
	release := snapshot.generation.Acquire(ctx)
	_, inv, cleanupInvocation, err := snapshot.goCommandInvocation(ctx, source.LoadWorkspace, &gocommand.Invocation{
		WorkingDir: snapshot.view.rootURI.Filename(),
	})
	if err != nil {
		return nil, err
	}
	pe.WorkingDir = inv.WorkingDir
	pe.BuildFlags = inv.BuildFlags
	pe.WorkingDir = inv.WorkingDir
	pe.ModFile = inv.ModFile
	pe.ModFlag = inv.ModFlag
	pe.Env = map[string]string{}
	for _, kv := range inv.Env {
		split := strings.SplitN(kv, "=", 2)
		if len(split) != 2 {
			continue
		}
		pe.Env[split[0]] = split[1]
	}

	return func() {
		cleanupInvocation()
		release()
	}, nil
}

func (s *importsState) refreshProcessEnv() {
	start := time.Now()

	s.mu.Lock()
	env := s.processEnv
	if resolver, err := s.processEnv.GetResolver(); err == nil {
		resolver.ClearForNewScan()
	}
	s.mu.Unlock()

	event.Log(s.ctx, "background imports cache refresh starting")
	if err := imports.PrimeCache(context.Background(), env); err == nil {
		event.Log(s.ctx, fmt.Sprintf("background refresh finished after %v", time.Since(start)))
	} else {
		event.Log(s.ctx, fmt.Sprintf("background refresh finished after %v", time.Since(start)), keys.Err.Of(err))
	}
	s.mu.Lock()
	s.cacheRefreshDuration = time.Since(start)
	s.cacheRefreshTimer = nil
	s.mu.Unlock()
}

func (s *importsState) destroy() {
	s.mu.Lock()
	if s.cleanupProcessEnv != nil {
		s.cleanupProcessEnv()
	}
	s.mu.Unlock()
}
