// Copyright 2019 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 server

import (
	"context"
	"fmt"
	"reflect"
	"sync"

	"golang.org/x/tools/gopls/internal/cache"
	"golang.org/x/tools/gopls/internal/protocol"
	"golang.org/x/tools/gopls/internal/settings"
	"golang.org/x/tools/internal/event"
)

func (s *server) DidChangeWorkspaceFolders(ctx context.Context, params *protocol.DidChangeWorkspaceFoldersParams) error {
	for _, folder := range params.Event.Removed {
		dir, err := protocol.ParseDocumentURI(folder.URI)
		if err != nil {
			return fmt.Errorf("invalid folder %q: %v", folder.URI, err)
		}
		if !s.session.RemoveView(dir) {
			return fmt.Errorf("view %q for %v not found", folder.Name, folder.URI)
		}
	}
	s.addFolders(ctx, params.Event.Added)
	return nil
}

// addView returns a Snapshot and a release function that must be
// called when it is no longer needed.
func (s *server) addView(ctx context.Context, name string, dir protocol.DocumentURI) (*cache.Snapshot, func(), error) {
	s.stateMu.Lock()
	state := s.state
	s.stateMu.Unlock()
	if state < serverInitialized {
		return nil, nil, fmt.Errorf("addView called before server initialized")
	}
	opts, err := s.fetchFolderOptions(ctx, dir)
	if err != nil {
		return nil, nil, err
	}
	folder, err := s.newFolder(ctx, dir, name, opts)
	if err != nil {
		return nil, nil, err
	}
	_, snapshot, release, err := s.session.NewView(ctx, folder)
	return snapshot, release, err
}

func (s *server) DidChangeConfiguration(ctx context.Context, _ *protocol.DidChangeConfigurationParams) error {
	ctx, done := event.Start(ctx, "lsp.Server.didChangeConfiguration")
	defer done()

	var wg sync.WaitGroup
	wg.Add(1)
	defer wg.Done()
	if s.Options().VerboseWorkDoneProgress {
		work := s.progress.Start(ctx, DiagnosticWorkTitle(FromDidChangeConfiguration), "Calculating diagnostics...", nil, nil)
		go func() {
			wg.Wait()
			work.End(ctx, "Done.")
		}()
	}

	// Apply any changes to the session-level settings.
	options, err := s.fetchFolderOptions(ctx, "")
	if err != nil {
		return err
	}
	s.SetOptions(options)

	// Collect options for all workspace folders.
	// If none have changed, this is a no op.
	folderOpts := make(map[protocol.DocumentURI]*settings.Options)
	changed := false
	// The set of views is implicitly guarded by the fact that gopls processes
	// didChange notifications synchronously.
	//
	// TODO(rfindley): investigate this assumption: perhaps we should hold viewMu
	// here.
	views := s.session.Views()
	for _, view := range views {
		folder := view.Folder()
		if folderOpts[folder.Dir] != nil {
			continue
		}
		opts, err := s.fetchFolderOptions(ctx, folder.Dir)
		if err != nil {
			return err
		}

		// Ignore hooks for the purposes of equality.
		sameOptions := reflect.DeepEqual(folder.Options.ClientOptions, opts.ClientOptions) &&
			reflect.DeepEqual(folder.Options.ServerOptions, opts.ServerOptions) &&
			reflect.DeepEqual(folder.Options.UserOptions, opts.UserOptions) &&
			reflect.DeepEqual(folder.Options.InternalOptions, opts.InternalOptions)

		if !sameOptions {
			changed = true
		}
		folderOpts[folder.Dir] = opts
	}
	if !changed {
		return nil
	}

	var newFolders []*cache.Folder
	for _, view := range views {
		folder := view.Folder()
		opts := folderOpts[folder.Dir]
		newFolder, err := s.newFolder(ctx, folder.Dir, folder.Name, opts)
		if err != nil {
			return err
		}
		newFolders = append(newFolders, newFolder)
	}
	s.session.UpdateFolders(ctx, newFolders)

	// The view set may have been updated above.
	viewsToDiagnose := make(map[*cache.View][]protocol.DocumentURI)
	for _, view := range s.session.Views() {
		viewsToDiagnose[view] = nil
	}

	modCtx, modID := s.needsDiagnosis(ctx, viewsToDiagnose)
	wg.Add(1)
	go func() {
		s.diagnoseChangedViews(modCtx, modID, viewsToDiagnose, FromDidChangeConfiguration)
		wg.Done()
	}()

	// An options change may have affected the detected Go version.
	s.checkViewGoVersions()

	return nil
}
