// Copyright (C) 2015 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 client

import (
	"fmt"
	"reflect"
	"sort"

	"android.googlesource.com/platform/tools/gpu/binary/schema"
	"android.googlesource.com/platform/tools/gpu/service/path"
	"github.com/google/gxui"
	"github.com/google/gxui/math"
)

const kStateAdapterNodeHeight = 18

func createControls(appCtx *ApplicationContext, name string, p path.Path, v interface{}) gxui.Control {
	layout := appCtx.theme.CreateLinearLayout()
	layout.SetDirection(gxui.LeftToRight)

	addLabel := func(format string, args ...interface{}) gxui.Label {
		label := appCtx.theme.CreateLabel()
		label.SetText(fmt.Sprintf(format, args...))
		label.SetMargin(math.ZeroSpacing)
		label.SetMultiline(false)
		layout.AddChild(label)
		return label
	}

	label := addLabel("%s: ", name)
	appCtx.toolTipController.AddToolTip(label, 0.7, func(math.Point) gxui.Control {
		return createLabel(appCtx, p.Path(), gxui.White)
	})

	if v != nil {
		c := createField(appCtx, p, nil, v)
		if c != nil {
			layout.AddChild(c)
		}
	}

	return layout
}

type StateAdapterNode struct {
	appCtx   *ApplicationContext
	name     string
	value    interface{}
	path     path.Value
	item     string
	children StateAdapterNodeList
	parent   *StateAdapterNode
}

type StateAdapterNodeList []*StateAdapterNode

func (l StateAdapterNodeList) Len() int           { return len(l) }
func (l StateAdapterNodeList) Less(a, b int) bool { return l[a].name < l[b].name }
func (l StateAdapterNodeList) Swap(a, b int)      { l[a], l[b] = l[b], l[a] }

func (n *StateAdapterNode) add(name string, value interface{}, path path.Value) {
	n.children = append(n.children, &StateAdapterNode{
		appCtx: n.appCtx,
		name:   name,
		value:  value,
		path:   path,
		item:   path.Path(),
		parent: n,
	})
}

func (n *StateAdapterNode) init() {
	n.children = nil
	if v, ok := n.value.(*schema.Object); ok {
		for i := range v.Fields {
			name := v.Type.Fields[i].Name()
			n.add(name, v.Fields[i], n.path.Field(name))
		}
	} else {
		v := reflect.ValueOf(n.value)
		switch v.Kind() {
		case reflect.Array, reflect.Slice:
			for i, c := 0, v.Len(); i < c; i++ {
				name := fmt.Sprintf("%d", i)
				v := v.Index(i)
				n.add(name, v.Interface(), n.path.ArrayIndex(uint64(i)))
			}
		case reflect.Map:
			for _, k := range v.MapKeys() {
				v := v.MapIndex(k)
				k := k.Interface()
				name := fmt.Sprintf("%v", k)
				n.add(name, v.Interface(), n.path.MapIndex(k))
			}
			sort.Sort(n.children)
		}
	}

	for _, c := range n.children {
		c.init()
	}
}

func (n *StateAdapterNode) Count() int {
	return len(n.children)
}

func (n *StateAdapterNode) NodeAt(index int) gxui.TreeNode {
	return n.children[index]
}

func (n *StateAdapterNode) ItemIndex(item gxui.AdapterItem) int {
	// Brute-force search
	for i, c := range n.children {
		if c.item == item {
			return i
		}
		if c.ItemIndex(item) >= 0 {
			return i
		}
	}
	return -1
}

func (n *StateAdapterNode) Item() gxui.AdapterItem {
	return n.item
}

func (n *StateAdapterNode) Create(t gxui.Theme) gxui.Control {
	if len(n.children) > 0 {
		return createControls(n.appCtx, n.name, n.path, nil)
	} else {
		return createControls(n.appCtx, n.name, n.path, n.value)
	}
}

type StateAdapter struct {
	StateAdapterNode
	gxui.AdapterBase
}

func (r *StateAdapter) Size(theme gxui.Theme) math.Size {
	return math.Size{W: math.MaxSize.W, H: kStateAdapterNodeHeight}
}

func NewStateAdapter(appCtx *ApplicationContext) *StateAdapter {
	return &StateAdapter{
		StateAdapterNode: StateAdapterNode{appCtx: appCtx},
	}
}

func (a *StateAdapter) Update(value interface{}, path *path.State) {
	a.value = value
	a.path = path
	a.init()
	a.DataReplaced()
}
