// Copyright (C) 2016 The Android Open Source Project
//
// 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 snippets

import (
	"fmt"

	"android.googlesource.com/platform/tools/gpu/framework/binary"
)

// pathway is way of finding a static component in a nested structure.
type Pathway interface {
	binary.Object
	isPath() // tag method

	// root returns the root of this pathway
	root() Pathway

	// getBase returns the base of this pathway or nil if it is the root.
	getBase() Pathway
}

// pathwayCast needed for generated code.
func PathwayCast(o binary.Object) Pathway {
	return o.(Pathway)
}

// namepath is a path representing a symbol name in a particular category
// (local, global, param). A namePath can be the root of a path.
type namePath struct {
	binary.Generate
	cat  SymbolCategory // category of this symbol (local, global, param)
	name string         // name of this symbol
}

func (*namePath) isPath() {}
func (n *namePath) root() Pathway {
	return n
}

func (n *namePath) getBase() Pathway {
	return nil
}

var _ Pathway = &namePath{}

// fieldPath is a path representing a field in an entity.
type fieldPath struct {
	binary.Generate
	base Pathway // Pathway to the entity.
	name string  // name of the field.
}

func (*fieldPath) isPath() {}
func (p *fieldPath) root() Pathway {
	return p.base.root()
}

func (p *fieldPath) getBase() Pathway {
	return p.base
}

var _ Pathway = &fieldPath{}

// partPath is a path representing a component of a container.
type partPath struct {
	binary.Generate
	base Pathway  // Pathway to the container.
	kind PartKind // kind of the component.
}

func (*partPath) isPath() {}
func (p *partPath) root() Pathway {
	return p.base.root()
}

func (p *partPath) getBase() Pathway {
	return p.base
}

var _ Pathway = &partPath{}

// relativePath is a path representing a symbol relative to a particular
// schema entity. A relativePath can be the root of a path.
type relativePath struct {
	binary.Generate

	// The name of the type as it is in the API file. The type of the global
	// state object is synthetic at determined by the tag "globals" in the
	// generated code.
	typeName string
}

func (*relativePath) isPath() {}
func (n *relativePath) root() Pathway {
	return n
}

func (n *relativePath) getBase() Pathway {
	return nil
}

var _ Pathway = &relativePath{}

func (n *namePath) String() string {
	return fmt.Sprintf("%s:%s", n.cat, n.name)
}

func (f *fieldPath) String() string {
	return fmt.Sprintf("%s.%s", f.base, f.name)
}

func (f *partPath) String() string {
	return fmt.Sprintf("%s.%s()", f.base, f.kind)
}

func (n *relativePath) String() string {
	return fmt.Sprintf("%s:", n.typeName)
}

// MakeRelative return a copy of p with the root replaced
// by a relative root for typeName.
func MakeRelative(p Pathway, typeName string) Pathway {
	switch p := p.(type) {
	case *partPath:
		return &partPath{base: MakeRelative(p.getBase(), typeName), kind: p.kind}
	case *fieldPath:
		return Field(MakeRelative(p.getBase(), typeName), p.name)
	case *namePath:
		return Field(Relative(typeName), p.name)
	case *relativePath:
		return Relative(typeName)
	default:
		panic(fmt.Errorf("Unexpected Pathway type %T in MakeRelative(%v, %s)", p, p, typeName))
	}
}

// Make a relative pathway for the API type named typeName
func Relative(typeName string) Pathway {
	return &relativePath{typeName: typeName}
}

// Variable returns a Pathway for a symbol named name in category cat.
func Variable(cat SymbolCategory, name string) Pathway {
	return &namePath{cat: cat, name: name}
}

// Elem returns a Pathway to the element of a collection.
func Elem(p Pathway) Pathway {
	return &partPath{base: p, kind: PartKind_Elem}
}

// Key returns a Pathway to the element of a collection.
func Key(p Pathway) Pathway {
	return &partPath{base: p, kind: PartKind_Key}
}

// Field returns a Pathway to a field of an entity.
func Field(p Pathway, name string) Pathway {
	return &fieldPath{base: p, name: name}
}

// Range returns a Pathway to a range of a slice or pointer.
func Range(p Pathway) Pathway {
	return &partPath{base: p, kind: PartKind_Range}
}

func Equal(left, right Pathway) bool {
	switch l := left.(type) {
	case *namePath:
		r, ok := right.(*namePath)
		return ok && *l == *r
	case *fieldPath:
		r, ok := right.(*fieldPath)
		return ok && l.name == r.name && Equal(l.base, r.base)
	case *partPath:
		r, ok := right.(*partPath)
		return ok && l.kind == r.kind && Equal(l.base, r.base)
	case *relativePath:
		r, ok := right.(*relativePath)
		return ok && l.typeName == r.typeName
	}
	return false
}

func IsGlobal(p Pathway) bool {
	switch root := p.root().(type) {
	case *namePath:
		return root.cat == SymbolCategory_Global
	case *relativePath:
		panic(fmt.Errorf("Relative path %v used with IsGlobal", p))
	default:
		panic(fmt.Errorf("Unexpected Pathway root type %T in IsGlobal(%v)", p, p))
	}
}
