// Copyright 2014 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.

// This file implements writing of types. The functionality is lifted
// directly from go/types, but now contains various modifications for
// nicer output.
//
// TODO(gri) back-port once we have a fixed interface and once the
// go/types API is not frozen anymore for the 1.3 release; and remove
// this implementation if possible.

package main

import (
	"go/types"

	"golang.org/x/tools/internal/aliases"
)

func (p *printer) writeType(this *types.Package, typ types.Type) {
	p.writeTypeInternal(this, typ, make([]types.Type, 8))
}

// From go/types - leave for now to ease back-porting this code.
const GcCompatibilityMode = false

func (p *printer) writeTypeInternal(this *types.Package, typ types.Type, visited []types.Type) {
	// Theoretically, this is a quadratic lookup algorithm, but in
	// practice deeply nested composite types with unnamed component
	// types are uncommon. This code is likely more efficient than
	// using a map.
	for _, t := range visited {
		if t == typ {
			p.printf("○%T", typ) // cycle to typ
			return
		}
	}
	visited = append(visited, typ)

	switch t := typ.(type) {
	case nil:
		p.print("<nil>")

	case *types.Basic:
		if t.Kind() == types.UnsafePointer {
			p.print("unsafe.")
		}
		if GcCompatibilityMode {
			// forget the alias names
			switch t.Kind() {
			case types.Byte:
				t = types.Typ[types.Uint8]
			case types.Rune:
				t = types.Typ[types.Int32]
			}
		}
		p.print(t.Name())

	case *types.Array:
		p.printf("[%d]", t.Len())
		p.writeTypeInternal(this, t.Elem(), visited)

	case *types.Slice:
		p.print("[]")
		p.writeTypeInternal(this, t.Elem(), visited)

	case *types.Struct:
		n := t.NumFields()
		if n == 0 {
			p.print("struct{}")
			return
		}

		p.print("struct {\n")
		p.indent++
		for i := 0; i < n; i++ {
			f := t.Field(i)
			if !f.Anonymous() {
				p.printf("%s ", f.Name())
			}
			p.writeTypeInternal(this, f.Type(), visited)
			if tag := t.Tag(i); tag != "" {
				p.printf(" %q", tag)
			}
			p.print("\n")
		}
		p.indent--
		p.print("}")

	case *types.Pointer:
		p.print("*")
		p.writeTypeInternal(this, t.Elem(), visited)

	case *types.Tuple:
		p.writeTuple(this, t, false, visited)

	case *types.Signature:
		p.print("func")
		p.writeSignatureInternal(this, t, visited)

	case *types.Interface:
		// We write the source-level methods and embedded types rather
		// than the actual method set since resolved method signatures
		// may have non-printable cycles if parameters have anonymous
		// interface types that (directly or indirectly) embed the
		// current interface. For instance, consider the result type
		// of m:
		//
		//     type T interface{
		//         m() interface{ T }
		//     }
		//
		n := t.NumMethods()
		if n == 0 {
			p.print("interface{}")
			return
		}

		p.print("interface {\n")
		p.indent++
		if GcCompatibilityMode {
			// print flattened interface
			// (useful to compare against gc-generated interfaces)
			for i := 0; i < n; i++ {
				m := t.Method(i)
				p.print(m.Name())
				p.writeSignatureInternal(this, m.Type().(*types.Signature), visited)
				p.print("\n")
			}
		} else {
			// print explicit interface methods and embedded types
			for i, n := 0, t.NumExplicitMethods(); i < n; i++ {
				m := t.ExplicitMethod(i)
				p.print(m.Name())
				p.writeSignatureInternal(this, m.Type().(*types.Signature), visited)
				p.print("\n")
			}
			for i, n := 0, t.NumEmbeddeds(); i < n; i++ {
				typ := t.EmbeddedType(i)
				p.writeTypeInternal(this, typ, visited)
				p.print("\n")
			}
		}
		p.indent--
		p.print("}")

	case *types.Map:
		p.print("map[")
		p.writeTypeInternal(this, t.Key(), visited)
		p.print("]")
		p.writeTypeInternal(this, t.Elem(), visited)

	case *types.Chan:
		var s string
		var parens bool
		switch t.Dir() {
		case types.SendRecv:
			s = "chan "
			// chan (<-chan T) requires parentheses
			if c, _ := t.Elem().(*types.Chan); c != nil && c.Dir() == types.RecvOnly {
				parens = true
			}
		case types.SendOnly:
			s = "chan<- "
		case types.RecvOnly:
			s = "<-chan "
		default:
			panic("unreachable")
		}
		p.print(s)
		if parens {
			p.print("(")
		}
		p.writeTypeInternal(this, t.Elem(), visited)
		if parens {
			p.print(")")
		}

	case *aliases.Alias:
		// TODO(adonovan): display something aliasy.
		p.writeTypeInternal(this, aliases.Unalias(t), visited)

	case *types.Named:
		s := "<Named w/o object>"
		if obj := t.Obj(); obj != nil {
			if pkg := obj.Pkg(); pkg != nil {
				if pkg != this {
					p.print(pkg.Path())
					p.print(".")
				}
				// TODO(gri): function-local named types should be displayed
				// differently from named types at package level to avoid
				// ambiguity.
			}
			s = obj.Name()
		}
		p.print(s)

	default:
		// For externally defined implementations of Type.
		p.print(t.String())
	}
}

func (p *printer) writeTuple(this *types.Package, tup *types.Tuple, variadic bool, visited []types.Type) {
	p.print("(")
	for i, n := 0, tup.Len(); i < n; i++ {
		if i > 0 {
			p.print(", ")
		}
		v := tup.At(i)
		if name := v.Name(); name != "" {
			p.print(name)
			p.print(" ")
		}
		typ := v.Type()
		if variadic && i == n-1 {
			p.print("...")
			typ = typ.(*types.Slice).Elem()
		}
		p.writeTypeInternal(this, typ, visited)
	}
	p.print(")")
}

func (p *printer) writeSignature(this *types.Package, sig *types.Signature) {
	p.writeSignatureInternal(this, sig, make([]types.Type, 8))
}

func (p *printer) writeSignatureInternal(this *types.Package, sig *types.Signature, visited []types.Type) {
	p.writeTuple(this, sig.Params(), sig.Variadic(), visited)

	res := sig.Results()
	n := res.Len()
	if n == 0 {
		// no result
		return
	}

	p.print(" ")
	if n == 1 && res.At(0).Name() == "" {
		// single unnamed result
		p.writeTypeInternal(this, res.At(0).Type(), visited)
		return
	}

	// multiple or named result(s)
	p.writeTuple(this, res, false, visited)
}
