// Copyright 2018 The CUE Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package load

import (
	"fmt"
	"path/filepath"
	"strings"

	"cuelang.org/go/cue/build"
	"cuelang.org/go/cue/errors"
	"cuelang.org/go/cue/token"
)

func lastError(p *build.Instance) *PackageError {
	if p == nil {
		return nil
	}
	switch v := p.Err.(type) {
	case *PackageError:
		return v
	}
	return nil
}

func report(p *build.Instance, err *PackageError) {
	if err != nil {
		p.ReportError(err)
	}
}

// A PackageError describes an error loading information about a package.
type PackageError struct {
	ImportStack    []string  // shortest path from package named on command line to this one
	Pos            token.Pos // position of error
	errors.Message           // the error itself
	IsImportCycle  bool      // the error is an import cycle
}

func (p *PackageError) Position() token.Pos         { return p.Pos }
func (p *PackageError) InputPositions() []token.Pos { return nil }
func (p *PackageError) Path() []string              { return p.ImportStack }

func (l *loader) errPkgf(importPos []token.Pos, format string, args ...interface{}) *PackageError {
	err := &PackageError{
		ImportStack: l.stk.Copy(),
		Message:     errors.NewMessage(format, args),
	}
	err.fillPos(l.cfg.Dir, importPos)
	return err
}

func (p *PackageError) fillPos(cwd string, positions []token.Pos) {
	if len(positions) > 0 && !p.Pos.IsValid() {
		p.Pos = positions[0]
	}
}

// TODO(localize)
func (p *PackageError) Error() string {
	// Import cycles deserve special treatment.
	if p.IsImportCycle {
		return fmt.Sprintf("%s\npackage %s\n", p.Message, strings.Join(p.ImportStack, "\n\timports "))
	}
	if p.Pos.IsValid() {
		// Omit import stack. The full path to the file where the error
		// is the most important thing.
		return p.Pos.String() + ": " + p.Message.Error()
	}
	if len(p.ImportStack) == 0 {
		return p.Message.Error()
	}
	return "package " + strings.Join(p.ImportStack, "\n\timports ") + ": " + p.Message.Error()
}

// NoFilesError is the error used by Import to describe a directory
// containing no usable source files. (It may still contain
// tool files, files hidden by build tags, and so on.)
type NoFilesError struct {
	Package *build.Instance

	ignored bool // whether any Go files were ignored due to build tags
}

func (e *NoFilesError) Position() token.Pos         { return token.NoPos }
func (e *NoFilesError) InputPositions() []token.Pos { return nil }
func (e *NoFilesError) Path() []string              { return nil }

// TODO(localize)
func (e *NoFilesError) Msg() (string, []interface{}) { return e.Error(), nil }

// TODO(localize)
func (e *NoFilesError) Error() string {
	// Count files beginning with _, which we will pretend don't exist at all.
	dummy := 0
	for _, f := range e.Package.IgnoredFiles {
		if strings.HasPrefix(filepath.Base(f.Filename), "_") {
			dummy++
		}
	}

	// path := shortPath(e.Package.Root, e.Package.Dir)
	path := e.Package.DisplayPath

	if len(e.Package.IgnoredFiles) > dummy {
		b := strings.Builder{}
		b.WriteString("build constraints exclude all CUE files in ")
		b.WriteString(path)
		b.WriteString(":")
		// CUE files exist, but they were ignored due to build constraints.
		for _, f := range e.Package.IgnoredFiles {
			b.WriteString("\n    ")
			b.WriteString(filepath.ToSlash(e.Package.RelPath(f)))
			if f.ExcludeReason != nil {
				b.WriteString(": ")
				b.WriteString(f.ExcludeReason.Error())
			}
		}
		return b.String()
	}
	// if len(e.Package.TestCUEFiles) > 0 {
	// 	// Test CUE files exist, but we're not interested in them.
	// 	// The double-negative is unfortunate but we want e.Package.Dir
	// 	// to appear at the end of error message.
	// 	return "no non-test CUE files in " + e.Package.Dir
	// }
	return "no CUE files in " + path
}

// MultiplePackageError describes an attempt to build a package composed of
// CUE files from different packages.
type MultiplePackageError struct {
	Dir      string   // directory containing files
	Packages []string // package names found
	Files    []string // corresponding files: Files[i] declares package Packages[i]
}

func (e *MultiplePackageError) Position() token.Pos         { return token.NoPos }
func (e *MultiplePackageError) InputPositions() []token.Pos { return nil }
func (e *MultiplePackageError) Path() []string              { return nil }

func (e *MultiplePackageError) Msg() (string, []interface{}) {
	return "found packages %q (%s) and %s (%s) in %q", []interface{}{
		e.Packages[0],
		e.Files[0],
		e.Packages[1],
		e.Files[1],
		e.Dir,
	}
}

func (e *MultiplePackageError) Error() string {
	// Error string limited to two entries for compatibility.
	format, args := e.Msg()
	return fmt.Sprintf(format, args...)
}
