package source

import (
	"context"
	"go/ast"
	"go/token"
	"sort"

	"golang.org/x/tools/internal/lsp/protocol"
	"golang.org/x/tools/internal/span"
)

type FoldingRangeInfo struct {
	mappedRange
	Kind protocol.FoldingRangeKind
}

// FoldingRange gets all of the folding range for f.
func FoldingRange(ctx context.Context, view View, f File, lineFoldingOnly bool) (ranges []*FoldingRangeInfo, err error) {
	// TODO(suzmue): consider limiting the number of folding ranges returned, and
	// implement a way to prioritize folding ranges in that case.
	s := view.Snapshot()
	fh := s.Handle(ctx, f)
	ph := view.Session().Cache().ParseGoHandle(fh, ParseFull)
	file, m, _, err := ph.Parse(ctx)
	if err != nil {
		return nil, err
	}

	// Get folding ranges for comments separately as they are not walked by ast.Inspect.
	ranges = append(ranges, commentsFoldingRange(view, m, file)...)

	foldingFunc := foldingRange
	if lineFoldingOnly {
		foldingFunc = lineFoldingRange
	}

	visit := func(n ast.Node) bool {
		rng := foldingFunc(view, m, n)
		if rng != nil {
			ranges = append(ranges, rng)
		}
		return true
	}
	// Walk the ast and collect folding ranges.
	ast.Inspect(file, visit)

	sort.Slice(ranges, func(i, j int) bool {
		irng, _ := ranges[i].Range()
		jrng, _ := ranges[j].Range()
		return protocol.CompareRange(irng, jrng) < 0
	})

	return ranges, nil
}

// foldingRange calculates the folding range for n.
func foldingRange(view View, m *protocol.ColumnMapper, n ast.Node) *FoldingRangeInfo {
	var kind protocol.FoldingRangeKind
	var start, end token.Pos
	switch n := n.(type) {
	case *ast.BlockStmt:
		// Fold from position of "{" to position of "}".
		start, end = n.Lbrace+1, n.Rbrace
	case *ast.CaseClause:
		// Fold from position of ":" to end.
		start, end = n.Colon+1, n.End()
	case *ast.CallExpr:
		// Fold from position of "(" to position of ")".
		start, end = n.Lparen+1, n.Rparen
	case *ast.FieldList:
		// Fold from position of opening parenthesis/brace, to position of
		// closing parenthesis/brace.
		start, end = n.Opening+1, n.Closing
	case *ast.GenDecl:
		// If this is an import declaration, set the kind to be protocol.Imports.
		if n.Tok == token.IMPORT {
			kind = protocol.Imports
		}
		start, end = n.Lparen+1, n.Rparen
	}
	if !start.IsValid() || !end.IsValid() {
		return nil
	}
	return &FoldingRangeInfo{
		mappedRange: mappedRange{
			m:         m,
			spanRange: span.NewRange(view.Session().Cache().FileSet(), start, end),
		},
		Kind: kind,
	}
}

// lineFoldingRange calculates the line folding range for n.
func lineFoldingRange(view View, m *protocol.ColumnMapper, n ast.Node) *FoldingRangeInfo {
	fset := view.Session().Cache().FileSet()

	// TODO(suzmue): include trailing empty lines before the closing
	// parenthesis/brace.
	var kind protocol.FoldingRangeKind
	var start, end token.Pos
	switch n := n.(type) {
	case *ast.BlockStmt:
		// Fold lines between "{" and "}".
		if !n.Lbrace.IsValid() || !n.Rbrace.IsValid() {
			break
		}
		nStmts := len(n.List)
		if nStmts == 0 {
			break
		}
		// Don't want to fold if the start is on the same line as the brace.
		if fset.Position(n.Lbrace).Line == fset.Position(n.List[0].Pos()).Line {
			break
		}
		// Don't want to fold if the end is on the same line as the brace.
		if fset.Position(n.Rbrace).Line == fset.Position(n.List[nStmts-1].End()).Line {
			break
		}
		start, end = n.Lbrace+1, n.List[nStmts-1].End()
	case *ast.CaseClause:
		// Fold from position of ":" to end.
		start, end = n.Colon+1, n.End()
	case *ast.FieldList:
		// Fold lines between opening parenthesis/brace and closing parenthesis/brace.
		if !n.Opening.IsValid() || !n.Closing.IsValid() {
			break
		}
		nFields := len(n.List)
		if nFields == 0 {
			break
		}
		// Don't want to fold if the start is on the same line as the parenthesis/brace.
		if fset.Position(n.Opening).Line == fset.Position(n.List[nFields-1].End()).Line {
			break
		}
		// Don't want to fold if the end is on the same line as the parenthesis/brace.
		if fset.Position(n.Closing).Line == fset.Position(n.List[nFields-1].End()).Line {
			break
		}
		start, end = n.Opening+1, n.List[nFields-1].End()
	case *ast.GenDecl:
		// If this is an import declaration, set the kind to be protocol.Imports.
		if n.Tok == token.IMPORT {
			kind = protocol.Imports
		}
		// Fold from position of "(" to position of ")".
		if !n.Lparen.IsValid() || !n.Rparen.IsValid() {
			break
		}
		nSpecs := len(n.Specs)
		if nSpecs == 0 {
			break
		}
		// Don't want to fold if the end is on the same line as the parenthesis/brace.
		if fset.Position(n.Lparen).Line == fset.Position(n.Specs[0].Pos()).Line {
			break
		}
		// Don't want to fold if the end is on the same line as the parenthesis/brace.
		if fset.Position(n.Rparen).Line == fset.Position(n.Specs[nSpecs-1].End()).Line {
			break
		}
		start, end = n.Lparen+1, n.Specs[nSpecs-1].End()
	}

	// Check that folding positions are valid.
	if !start.IsValid() || !end.IsValid() {
		return nil
	}
	// Do not fold if the start and end lines are the same.
	if fset.Position(start).Line == fset.Position(end).Line {
		return nil
	}
	return &FoldingRangeInfo{
		mappedRange: mappedRange{
			m:         m,
			spanRange: span.NewRange(fset, start, end),
		},
		Kind: kind,
	}
}

// commentsFoldingRange returns the folding ranges for all comment blocks in file.
// The folding range starts at the end of the first comment, and ends at the end of the
// comment block and has kind protocol.Comment.
func commentsFoldingRange(view View, m *protocol.ColumnMapper, file *ast.File) (comments []*FoldingRangeInfo) {
	for _, commentGrp := range file.Comments {
		// Don't fold single comments.
		if len(commentGrp.List) <= 1 {
			continue
		}
		comments = append(comments, &FoldingRangeInfo{
			mappedRange: mappedRange{
				m: m,
				// Fold from the end of the first line comment to the end of the comment block.
				spanRange: span.NewRange(view.Session().Cache().FileSet(), commentGrp.List[0].End(), commentGrp.End()),
			},
			Kind: protocol.Comment,
		})
	}
	return comments
}
