// Copyright 2017 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 pointer

import (
	"errors"
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"go/types"
	"strconv"
)

// An extendedQuery represents a sequence of destructuring operations
// applied to an ssa.Value (denoted by "x").
type extendedQuery struct {
	ops []interface{}
	ptr *Pointer
}

// indexValue returns the value of an integer literal used as an
// index.
func indexValue(expr ast.Expr) (int, error) {
	lit, ok := expr.(*ast.BasicLit)
	if !ok {
		return 0, fmt.Errorf("non-integer index (%T)", expr)
	}
	if lit.Kind != token.INT {
		return 0, fmt.Errorf("non-integer index %s", lit.Value)
	}
	return strconv.Atoi(lit.Value)
}

// parseExtendedQuery parses and validates a destructuring Go
// expression and returns the sequence of destructuring operations.
// See parseDestructuringExpr for details.
func parseExtendedQuery(typ types.Type, query string) ([]interface{}, types.Type, error) {
	expr, err := parser.ParseExpr(query)
	if err != nil {
		return nil, nil, err
	}
	ops, typ, err := destructuringOps(typ, expr)
	if err != nil {
		return nil, nil, err
	}
	if len(ops) == 0 {
		return nil, nil, errors.New("invalid query: must not be empty")
	}
	if ops[0] != "x" {
		return nil, nil, fmt.Errorf("invalid query: query operand must be named x")
	}
	if !CanPoint(typ) {
		return nil, nil, fmt.Errorf("query does not describe a pointer-like value: %s", typ)
	}
	return ops, typ, nil
}

// destructuringOps parses a Go expression consisting only of an
// identifier "x", field selections, indexing, channel receives, load
// operations and parens---for example: "<-(*x[i])[key]"--- and
// returns the sequence of destructuring operations on x.
func destructuringOps(typ types.Type, expr ast.Expr) ([]interface{}, types.Type, error) {
	switch expr := expr.(type) {
	case *ast.SelectorExpr:
		out, typ, err := destructuringOps(typ, expr.X)
		if err != nil {
			return nil, nil, err
		}

		var structT *types.Struct
		switch typ := typ.Underlying().(type) {
		case *types.Pointer:
			var ok bool
			structT, ok = typ.Elem().Underlying().(*types.Struct)
			if !ok {
				return nil, nil, fmt.Errorf("cannot access field %s of pointer to type %s", expr.Sel.Name, typ.Elem())
			}

			out = append(out, "load")
		case *types.Struct:
			structT = typ
		default:
			return nil, nil, fmt.Errorf("cannot access field %s of type %s", expr.Sel.Name, typ)
		}

		for i := 0; i < structT.NumFields(); i++ {
			field := structT.Field(i)
			if field.Name() == expr.Sel.Name {
				out = append(out, "field", i)
				return out, field.Type().Underlying(), nil
			}
		}
		// TODO(dh): supporting embedding would need something like
		// types.LookupFieldOrMethod, but without taking package
		// boundaries into account, because we may want to access
		// unexported fields. If we were only interested in one level
		// of unexported name, we could determine the appropriate
		// package and run LookupFieldOrMethod with that. However, a
		// single query may want to cross multiple package boundaries,
		// and at this point it's not really worth the complexity.
		return nil, nil, fmt.Errorf("no field %s in %s (embedded fields must be resolved manually)", expr.Sel.Name, structT)
	case *ast.Ident:
		return []interface{}{expr.Name}, typ, nil
	case *ast.BasicLit:
		return []interface{}{expr.Value}, nil, nil
	case *ast.IndexExpr:
		out, typ, err := destructuringOps(typ, expr.X)
		if err != nil {
			return nil, nil, err
		}
		switch typ := typ.Underlying().(type) {
		case *types.Array:
			out = append(out, "arrayelem")
			return out, typ.Elem().Underlying(), nil
		case *types.Slice:
			out = append(out, "sliceelem")
			return out, typ.Elem().Underlying(), nil
		case *types.Map:
			out = append(out, "mapelem")
			return out, typ.Elem().Underlying(), nil
		case *types.Tuple:
			out = append(out, "index")
			idx, err := indexValue(expr.Index)
			if err != nil {
				return nil, nil, err
			}
			out = append(out, idx)
			if idx >= typ.Len() || idx < 0 {
				return nil, nil, fmt.Errorf("tuple index %d out of bounds", idx)
			}
			return out, typ.At(idx).Type().Underlying(), nil
		default:
			return nil, nil, fmt.Errorf("cannot index type %s", typ)
		}

	case *ast.UnaryExpr:
		if expr.Op != token.ARROW {
			return nil, nil, fmt.Errorf("unsupported unary operator %s", expr.Op)
		}
		out, typ, err := destructuringOps(typ, expr.X)
		if err != nil {
			return nil, nil, err
		}
		ch, ok := typ.(*types.Chan)
		if !ok {
			return nil, nil, fmt.Errorf("cannot receive from value of type %s", typ)
		}
		out = append(out, "recv")
		return out, ch.Elem().Underlying(), err
	case *ast.ParenExpr:
		return destructuringOps(typ, expr.X)
	case *ast.StarExpr:
		out, typ, err := destructuringOps(typ, expr.X)
		if err != nil {
			return nil, nil, err
		}
		ptr, ok := typ.(*types.Pointer)
		if !ok {
			return nil, nil, fmt.Errorf("cannot dereference type %s", typ)
		}
		out = append(out, "load")
		return out, ptr.Elem().Underlying(), err
	default:
		return nil, nil, fmt.Errorf("unsupported expression %T", expr)
	}
}

func (a *analysis) evalExtendedQuery(t types.Type, id nodeid, ops []interface{}) (types.Type, nodeid) {
	pid := id
	// TODO(dh): we're allocating intermediary nodes each time
	// evalExtendedQuery is called. We should probably only generate
	// them once per (v, ops) pair.
	for i := 1; i < len(ops); i++ {
		var nid nodeid
		switch ops[i] {
		case "recv":
			t = t.(*types.Chan).Elem().Underlying()
			nid = a.addNodes(t, "query.extended")
			a.load(nid, pid, 0, a.sizeof(t))
		case "field":
			i++ // fetch field index
			tt := t.(*types.Struct)
			idx := ops[i].(int)
			offset := a.offsetOf(t, idx)
			t = tt.Field(idx).Type().Underlying()
			nid = a.addNodes(t, "query.extended")
			a.copy(nid, pid+nodeid(offset), a.sizeof(t))
		case "arrayelem":
			t = t.(*types.Array).Elem().Underlying()
			nid = a.addNodes(t, "query.extended")
			a.copy(nid, 1+pid, a.sizeof(t))
		case "sliceelem":
			t = t.(*types.Slice).Elem().Underlying()
			nid = a.addNodes(t, "query.extended")
			a.load(nid, pid, 1, a.sizeof(t))
		case "mapelem":
			tt := t.(*types.Map)
			t = tt.Elem()
			ksize := a.sizeof(tt.Key())
			vsize := a.sizeof(tt.Elem())
			nid = a.addNodes(t, "query.extended")
			a.load(nid, pid, ksize, vsize)
		case "index":
			i++ // fetch index
			tt := t.(*types.Tuple)
			idx := ops[i].(int)
			t = tt.At(idx).Type().Underlying()
			nid = a.addNodes(t, "query.extended")
			a.copy(nid, pid+nodeid(idx), a.sizeof(t))
		case "load":
			t = t.(*types.Pointer).Elem().Underlying()
			nid = a.addNodes(t, "query.extended")
			a.load(nid, pid, 0, a.sizeof(t))
		default:
			// shouldn't happen
			panic(fmt.Sprintf("unknown op %q", ops[i]))
		}
		pid = nid
	}

	return t, pid
}
