// 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 localdatasource implements an in-memory internal.DataSource used to load
// and display documentation for local modules that are not available via a proxy.
// Similar to proxydatasource, search and other tabs are not supported in this mode.
package localdatasource

import (
	"context"
	"fmt"
	"os"
	"path"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"golang.org/x/pkgsite/internal"
	"golang.org/x/pkgsite/internal/derrors"
	"golang.org/x/pkgsite/internal/fetch"
	"golang.org/x/pkgsite/internal/source"
)

// DataSource implements an in-memory internal.DataSource used to display documentation
// locally. DataSource is not backed by a database or a proxy instance.
type DataSource struct {
	sourceClient *source.Client

	mu            sync.Mutex
	loadedModules map[string]*internal.Module
}

// New creates and returns a new local datasource that bypasses license
// checks by default.
func New() *DataSource {
	return &DataSource{
		sourceClient:  source.NewClient(1 * time.Minute),
		loadedModules: make(map[string]*internal.Module),
	}
}

// Load loads a module from the given local path. Loading is required before
// being able to display the module.
func (ds *DataSource) Load(ctx context.Context, localPath string) (err error) {
	defer derrors.Wrap(&err, "Load(%q)", localPath)
	return ds.fetch(ctx, "", localPath)
}

// LoadFromGOPATH loads a module from GOPATH using the given import path. The full
// path of the module should be GOPATH/src/importPath. If several GOPATHs exist, the
// module is loaded from the first one that contains the import path. Loading is required
// before being able to display the module.
func (ds *DataSource) LoadFromGOPATH(ctx context.Context, importPath string) (err error) {
	defer derrors.Wrap(&err, "LoadFromGOPATH(%q)", importPath)

	path := getFullPath(importPath)
	if path == "" {
		return fmt.Errorf("path %s doesn't exist: %w", importPath, derrors.NotFound)
	}

	return ds.fetch(ctx, importPath, path)
}

// fetch fetches a module using FetchLocalModule and adds it to the datasource.
// If the fetching fails, an error is returned.
func (ds *DataSource) fetch(ctx context.Context, modulePath, localPath string) error {
	fr := fetch.FetchLocalModule(ctx, modulePath, localPath, ds.sourceClient)
	if fr.Error != nil {
		return fr.Error
	}

	fr.Module.IsRedistributable = true
	for _, unit := range fr.Module.Units {
		unit.IsRedistributable = true
	}

	for _, unit := range fr.Module.Units {
		for _, d := range unit.Documentation {
			unit.BuildContexts = append(unit.BuildContexts, internal.BuildContext{
				GOOS:   d.GOOS,
				GOARCH: d.GOARCH,
			})
		}
	}

	ds.mu.Lock()
	defer ds.mu.Unlock()
	ds.loadedModules[fr.ModulePath] = fr.Module
	return nil
}

// getFullPath takes an import path, tests it relative to each GOPATH, and returns
// a full path to the module. If the given import path doesn't exist in any GOPATH,
// an empty string is returned.
func getFullPath(modulePath string) string {
	gopaths := filepath.SplitList(os.Getenv("GOPATH"))
	for _, gopath := range gopaths {
		path := filepath.Join(gopath, "src", modulePath)
		info, err := os.Stat(path)
		if err == nil && info.IsDir() {
			return path
		}
	}
	return ""
}

// GetUnit returns information about a unit. Both the module path and package
// path must be known.
func (ds *DataSource) GetUnit(ctx context.Context, pathInfo *internal.UnitMeta, fields internal.FieldSet, bc internal.BuildContext) (_ *internal.Unit, err error) {
	defer derrors.Wrap(&err, "GetUnit(%q, %q)", pathInfo.Path, pathInfo.ModulePath)

	modulepath := pathInfo.ModulePath
	path := pathInfo.Path

	ds.mu.Lock()
	defer ds.mu.Unlock()
	if ds.loadedModules[modulepath] == nil {
		return nil, fmt.Errorf("%s not loaded: %w", modulepath, derrors.NotFound)
	}

	module := ds.loadedModules[modulepath]
	for _, unit := range module.Units {
		if unit.Path == path {
			return unit, nil
		}
	}

	return nil, fmt.Errorf("%s not found: %w", path, derrors.NotFound)
}

// GetUnitMeta returns information about a path.
func (ds *DataSource) GetUnitMeta(ctx context.Context, path, requestedModulePath, requestedVersion string) (_ *internal.UnitMeta, err error) {
	defer derrors.Wrap(&err, "GetUnitMeta(%q, %q, %q)", path, requestedModulePath, requestedVersion)

	if requestedModulePath == internal.UnknownModulePath {
		requestedModulePath, err = ds.findModule(path)
		if err != nil {
			return nil, err
		}
	}

	ds.mu.Lock()
	module := ds.loadedModules[requestedModulePath]
	ds.mu.Unlock()
	if module == nil {
		return nil, fmt.Errorf("%s not loaded: %w", requestedModulePath, derrors.NotFound)
	}

	um := &internal.UnitMeta{
		Path: path,
		ModuleInfo: internal.ModuleInfo{
			ModulePath:        requestedModulePath,
			Version:           fetch.LocalVersion,
			CommitTime:        fetch.LocalCommitTime,
			IsRedistributable: module.IsRedistributable,
		},
	}

	for _, u := range module.Units {
		if u.Path == path {
			um.Name = u.Name
			um.IsRedistributable = u.IsRedistributable
		}
	}

	return um, nil
}

// findModule finds the longest module path in loadedModules containing the given
// package path. It iteratively checks parent directories to find an import path.
// Returns an error if no module is found.
func (ds *DataSource) findModule(pkgPath string) (_ string, err error) {
	defer derrors.Wrap(&err, "findModule(%q)", pkgPath)

	pkgPath = strings.TrimLeft(pkgPath, "/")

	ds.mu.Lock()
	defer ds.mu.Unlock()
	for modulePath := pkgPath; modulePath != "" && modulePath != "."; modulePath = path.Dir(modulePath) {
		if ds.loadedModules[modulePath] != nil {
			return modulePath, nil
		}
	}

	return "", fmt.Errorf("%s not loaded: %w", pkgPath, derrors.NotFound)
}

// GetLatestInfo is not implemented.
func (ds *DataSource) GetLatestInfo(ctx context.Context, unitPath, modulePath string, latestUnitMeta *internal.UnitMeta) (internal.LatestInfo, error) {
	return internal.LatestInfo{}, nil
}

// GetNestedModules is not implemented.
func (ds *DataSource) GetNestedModules(ctx context.Context, modulePath string) ([]*internal.ModuleInfo, error) {
	return nil, nil
}

// GetModuleReadme is not implemented.
func (*DataSource) GetModuleReadme(ctx context.Context, modulePath, resolvedVersion string) (*internal.Readme, error) {
	return nil, nil
}
