// Copyright 2021 The Fuchsia 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 summarize

import (
	"fmt"
	"strings"

	"go.fuchsia.dev/fuchsia/tools/fidl/lib/fidlgen"
)

type typePrinter = func(t fidlgen.Type) Type

// structPayload is a wrapper for implementing parameterizer on fidlgen.Struct.
type structPayload struct {
	fidlgen.Struct
}

// identifierPayload is a wrapper for implementing parameterizer on fidlgen.EncodedCompoundIdentifier.
type identifierPayload struct {
	identifier    fidlgen.EncodedCompoundIdentifier
	isResultUnion bool
}

// symbolTable knows how to represent a symbol's type as a string.
//
// In the RFC-0050 compatible syntax, knowledge of identifier types is required
// for this to be possible.
type symbolTable struct {
	// protocolNames contains all protocol names defined in the FIDL IR.  Used
	// for resolving server and client end references.
	protocolNames map[fidlgen.EncodedCompoundIdentifier]struct{}

	// structDecls contain all struct names from the FIDL IR.  Used for
	// resolving optional structs which have a different syntax
	// (box<Foo> instead of Foo:optional).
	structDecls map[fidlgen.EncodedCompoundIdentifier]*fidlgen.Struct
}

// addProtocol registers that name corresponds to a FIDL protocol.
func (n *symbolTable) addProtocol(name fidlgen.EncodedCompoundIdentifier) {
	if n.protocolNames == nil {
		n.protocolNames = make(map[fidlgen.EncodedCompoundIdentifier]struct{})
	}
	n.protocolNames[name] = struct{}{}
}

// isProtocol returns true if name is a known protocol.
func (n *symbolTable) isProtocol(name fidlgen.EncodedCompoundIdentifier) bool {
	_, ok := n.protocolNames[name]
	return ok
}

// addStruct registers that `name` corresponds to a FIDL struct.
func (n *symbolTable) addStruct(name fidlgen.EncodedCompoundIdentifier, def *fidlgen.Struct) {
	if n.structDecls == nil {
		n.structDecls = make(map[fidlgen.EncodedCompoundIdentifier]*fidlgen.Struct)
	}
	n.structDecls[name] = def
}

// isStruct returns true if name is a known struct.
func (n *symbolTable) isStruct(name fidlgen.EncodedCompoundIdentifier) bool {
	_, ok := n.structDecls[name]
	return ok
}

// fidlTypeString converts the FIDL type declaration into a string per RFC-0050.
func (n *symbolTable) fidlTypeString(t fidlgen.Type) Type {
	var ret typeString
	switch t.Kind {
	case fidlgen.PrimitiveType:
		ret.setLayout(string(t.PrimitiveSubtype))
	case fidlgen.StringType:
		ret.setLayout("string")
	case fidlgen.ArrayType:
		ret.setLayout("array")
		ret.addParam(string(n.fidlTypeString(*t.ElementType)))
	case fidlgen.VectorType:
		ret.setLayout("vector")
		ret.addParam(string(n.fidlTypeString(*t.ElementType)))
	case fidlgen.HandleType:
		if t.HandleSubtype != fidlgen.HandleSubtypeNone {
			ret.setLayout("zx/Handle")
			ret.addConstraint(strings.ToUpper(string(t.HandleSubtype)))
		} else {
			ret.setLayout("zx/Handle")
		}
		ret.addHandleRights(t.HandleRights)
	case fidlgen.IdentifierType: // E.g. struct, enum, bits, etc.
		ret.setLayout(string(t.Identifier))
	case fidlgen.EndpointType: // E.g. client_end, server_end
		switch t.Role {
		case fidlgen.ClientRole:
			// TODO(https://fxbug.dev/42149402): Reimplement a bug from a
			// previous implementation. When an endpoint doesn't refer to a
			// "known protocol", we treat it like a regular identifier and omit
			// the `client_end:` layout. Fix this separately.
			if n.isProtocol(t.Protocol) {
				ret.setLayout("client_end")
				ret.addConstraint(string(t.Protocol))
			} else {
				ret.setLayout(string(t.Protocol))
			}

		case fidlgen.ServerRole:
			ret.setLayout("server_end")
			ret.addConstraint(string(t.Protocol))
		default:
			panic(fmt.Sprintf("unexpected fidlgen.EndpointRole: %#v", t.Role))
		}
	case fidlgen.ZxExperimentalPointerType:
		ret.setLayout("experimental_pointer")
		ret.addParam(string(n.fidlTypeString(*t.PointeeType)))
	case fidlgen.StringArray:
		ret.setLayout("string_array")
	default:
		ret.setLayout(fmt.Sprintf("<not_implemented:%#v>", t))
	}
	// ,N
	if t.ElementCount != nil {
		if t.Kind == fidlgen.ArrayType {
			ret.addParam(fmt.Sprintf("%d", *t.ElementCount))
		} else {
			ret.addConstraint(fmt.Sprintf("%d", *t.ElementCount))
		}
	}
	// :optional
	if t.Nullable {
		if n.isStruct(t.Identifier) {
			ret.addParam(ret.layout)
			ret.setLayout("box")
		} else {
			ret.addConstraint("optional")
		}
	}
	return Type(ret.String())
}

// typeString contains a declaration of a FIDL type, and knows how to print it
// out.
//
// See
// https://fuchsia.dev/fuchsia-src/contribute/governance/rfcs/0050_syntax_revamp?hl=en
type typeString struct {
	layout      string
	params      []string
	constraints []string
}

func (t *typeString) setLayout(layout string) {
	t.layout = layout
}

func (t *typeString) addParam(param string) {
	if param == "" {
		return
	}
	t.params = append(t.params, param)
}

func (t *typeString) addConstraint(constraint string) {
	if constraint == "" {
		return
	}
	t.constraints = append(t.constraints, constraint)
}

// String writes out the typeString based on the RFC-0050 syntax rules.
func (t typeString) String() string {
	var ret []string
	if t.layout == "" {
		panic(fmt.Sprintf("layout not set: %#v", t))
	}
	ret = append(ret, t.layout)
	// <> omitted if no params.
	if len(t.params) != 0 {
		ret = append(ret, "<", strings.Join(t.params, ","), ">")
	}
	lc := len(t.constraints)
	if lc != 0 {
		ret = append(ret, ":")
		if lc > 1 {
			// "<>" omitted if one constraint or no constraints.
			ret = append(ret, "<")
		}
		ret = append(ret, strings.Join(t.constraints, ","))
		if lc > 1 {
			ret = append(ret, ">")
		}
	}
	return strings.Join(ret, "")
}

// handleRightsNames maps each individual HandleRights bit to a name.
var handleRightsNames map[fidlgen.HandleRights]string = map[fidlgen.HandleRights]string{
	fidlgen.HandleRightsNone:          "zx.NONE",
	fidlgen.HandleRightsDuplicate:     "zx.DUPLICATE",
	fidlgen.HandleRightsTransfer:      "zx.TRANSFER",
	fidlgen.HandleRightsRead:          "zx.READ",
	fidlgen.HandleRightsWrite:         "zx.WRITE",
	fidlgen.HandleRightsExecute:       "zx.EXECUTE",
	fidlgen.HandleRightsMap:           "zx.MAP",
	fidlgen.HandleRightsGetProperty:   "zx.GET_PROPERTY",
	fidlgen.HandleRightsSetProperty:   "zx.SET_PROPERTY",
	fidlgen.HandleRightsEnumerate:     "zx.ENUMERATE",
	fidlgen.HandleRightsDestroy:       "zx.DESTROY",
	fidlgen.HandleRightsSetPolicy:     "zx.SET_POLICY",
	fidlgen.HandleRightsGetPolicy:     "zx.GET_POLICY",
	fidlgen.HandleRightsSignal:        "zx.SIGNAL",
	fidlgen.HandleRightsSignalPeer:    "zx.SIGNAL_PEER",
	fidlgen.HandleRightsWait:          "zx.WAIT",
	fidlgen.HandleRightsInspect:       "zx.INSPECT",
	fidlgen.HandleRightsManageJob:     "zx.MANAGE_JOB",
	fidlgen.HandleRightsManageProcess: "zx.MANAGE_PROCESS",
	fidlgen.HandleRightsManageThread:  "zx.MANAGE_THREAD",
	fidlgen.HandleRightsApplyProfile:  "zx.APPLY_PROFILE",
}

// addHandleRights adds string representation of handle rights r into the type
// representation.
func (t *typeString) addHandleRights(r fidlgen.HandleRights) {
	var right fidlgen.HandleRights
	for right = 1; right != 0; right = right << 1 {
		if right&r != 0 {
			// While not all HandleRights bits have a name, ostensibly the ones that
			// are used do have a name, and the code below will work.  If ever there
			// is a new bit introduced without giving it a name, this will fail. But
			// since unnamed but used bit is a bug, failing is OK.  Fix by adding the
			// missing name to handleRightsNames above.
			t.addConstraint(handleRightsNames[right])
		}
	}
}
