// Copyright 2021 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 frontend

import (
	"context"
	"sort"
	"strings"

	"golang.org/x/pkgsite/internal"
	"golang.org/x/pkgsite/internal/stdlib"
	"golang.org/x/pkgsite/internal/version"
)

// Directories is the directory listing for all directories in the unit,
// which is listed in the directories section of the main page.
type Directories struct {
	// External contains all of the non-internal directories for the unit.
	External []*Directory

	// Internal contains the top level internal directory for the unit, if any.
	Internal *Directory
}

// Directory is either a nested module or subdirectory of a unit, organized in
// a two level tree structure. This content is used in the
// directories section of the unit page.
type Directory struct {
	// Prefix is the prefix of the unit path for the subdirectories.
	Prefix string

	// Root is the package located at prefix, nil for a directory.
	Root *DirectoryInfo

	// Subdirectories contains subdirectories with prefix trimmed from their suffix.
	Subdirectories []*DirectoryInfo
}

// DirectoryInfo contains information about a package or nested module,
// relative to the path of a given unit. This content is used in the
// Directories section of the unit page.
type DirectoryInfo struct {
	Suffix   string
	URL      string
	Synopsis string
	IsModule bool
}

// unitDirectories zips the subdirectories and nested modules together in a two
// level tree hierarchy.
func unitDirectories(directories []*DirectoryInfo) *Directories {
	if len(directories) == 0 {
		return nil
	}
	// Organize the subdirectories into a two level tree hierarchy. The first part of
	// the unit path suffix for a subdirectory becomes the prefix under which matching
	// subdirectories are grouped.
	mappedDirs := make(map[string]*Directory)
	for _, d := range directories {
		prefix, _, _ := internal.Cut(d.Suffix, "/")

		// Skip internal directories that are not in the top level internal
		// directory. For example, foo/internal and foo/internal/bar should
		// be skipped, but internal/foo should be included.
		if prefix != "internal" && (strings.HasSuffix(d.Suffix, "/internal") ||
			strings.Contains(d.Suffix, "/internal/")) {
			continue
		}
		if _, ok := mappedDirs[prefix]; !ok {
			mappedDirs[prefix] = &Directory{Prefix: prefix}
		}
		d.Suffix = strings.TrimPrefix(d.Suffix, prefix+"/")
		if prefix == d.Suffix {
			mappedDirs[prefix].Root = d
		} else {
			mappedDirs[prefix].Subdirectories = append(mappedDirs[prefix].Subdirectories, d)
		}
	}

	section := &Directories{}
	for prefix, dir := range mappedDirs {
		if prefix == "internal" {
			section.Internal = dir
		} else {
			section.External = append(section.External, dir)
		}
	}
	sort.Slice(section.External, func(i, j int) bool {
		return section.External[i].Prefix < section.External[j].Prefix
	})
	return section
}

func getNestedModules(ctx context.Context, ds internal.DataSource, um *internal.UnitMeta, sds []*DirectoryInfo) ([]*DirectoryInfo, error) {
	nestedModules, err := ds.GetNestedModules(ctx, um.ModulePath)
	if err != nil {
		return nil, err
	}
	// Build a map of existing suffixes in subdirectories to filter out nested modules
	// which have the same suffix.
	excludedSuffixes := make(map[string]bool)
	for _, dir := range sds {
		excludedSuffixes[dir.Suffix] = true
	}
	var mods []*DirectoryInfo
	for _, m := range nestedModules {
		if m.SeriesPath() == internal.SeriesPathForModule(um.ModulePath) {
			continue
		}
		if !strings.HasPrefix(m.ModulePath, um.Path+"/") {
			continue
		}
		suffix := internal.Suffix(m.SeriesPath(), um.Path)
		if excludedSuffixes[suffix] {
			continue
		}
		mods = append(mods, &DirectoryInfo{
			URL:      constructUnitURL(m.ModulePath, m.ModulePath, version.Latest),
			Suffix:   suffix,
			IsModule: true,
		})
	}
	return mods, nil
}

func getSubdirectories(um *internal.UnitMeta, pkgs []*internal.PackageMeta, requestedVersion string) []*DirectoryInfo {
	var sdirs []*DirectoryInfo
	for _, pm := range pkgs {
		if um.Path == pm.Path {
			continue
		}
		if um.Path == stdlib.ModulePath && strings.HasPrefix(pm.Path, "cmd/") {
			// Omit "cmd" from the directory listing on
			// pkg.go.dev/std, since go list std does not
			// list them.
			continue
		}
		sdirs = append(sdirs, &DirectoryInfo{
			URL: constructUnitURL(pm.Path, um.ModulePath,
				linkVersion(um.ModulePath, requestedVersion, um.Version)),
			Suffix:   internal.Suffix(pm.Path, um.Path),
			Synopsis: pm.Synopsis,
		})
	}
	sort.Slice(sdirs, func(i, j int) bool { return sdirs[i].Suffix < sdirs[j].Suffix })
	return sdirs
}
