// 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 builder

import (
	"fmt"
	"reflect"

	"android.googlesource.com/platform/tools/gpu/atom"
	"android.googlesource.com/platform/tools/gpu/database"
	"android.googlesource.com/platform/tools/gpu/log"
	"android.googlesource.com/platform/tools/gpu/service"
	"android.googlesource.com/platform/tools/gpu/service/path"
)

// BuildLazy creates a copy of the capture referenced by the request's path, but
// with the object, value or memory at p replaced with v. The path returned is
// identical to p, but with the base changed to refer to the new capture.
func (request *Set) BuildLazy(c interface{}, d database.Database, l log.Logger) (interface{}, error) {
	paths := path.Flatten(request.Path)
	v, err := resolveChain(paths, d, l)
	if err != nil {
		return nil, err
	}

	// Start by replacing the target value
	v[len(v)-1] = request.Value

	// Propagate changes back down to the root
	for i := len(v) - 1; i >= 0; i-- {
		switch p := paths[i].(type) {
		case *path.Capture:
			id, err := database.Store(v[i], d, l)
			if err != nil {
				return nil, err
			}
			// Return the path to the new capture
			newPath := request.Path.Clone()
			for p := newPath; p != nil; p = p.Base() {
				if root, ok := p.(*path.Capture); ok {
					root.ID = id
					return newPath, nil
				}
			}
			panic("Unreachable")

		case *path.Atoms:
			stream := v[i].(*atom.List)
			streamID, err := database.Store(stream, d, l)
			if err != nil {
				return nil, err
			}

			capture := *v[i-1].(*service.Capture)
			capture.Name = capture.Name + "*"
			capture.Atoms = service.AtomsID(streamID)
			v[i-1] = &capture

		case *path.Report:
			return nil, fmt.Errorf("Reports are immutable")

		case *path.Atom:
			if v[i] == nil {
				return nil, fmt.Errorf("Atom cannot be nil")
			}
			stream := v[i-1].(*atom.List).Clone()
			stream.Atoms[p.Index] = v[i].(atom.Atom)
			v[i-1] = stream

		case *path.State:
			return nil, fmt.Errorf("State can not currently be mutated")

		case *path.Field:
			obj, err := clone(reflect.ValueOf(v[i-1]))
			if err != nil {
				return nil, err
			}
			s := obj
			for s.Kind() == reflect.Ptr {
				s = s.Elem() // Deref
			}
			if err := assign(s.FieldByName(p.Name), reflect.ValueOf(v[i])); err != nil {
				return nil, err
			}
			v[i-1] = obj.Interface()

		case *path.ArrayIndex:
			a, err := clone(reflect.ValueOf(v[i-1]))
			if err != nil {
				return nil, err
			}
			val, ok := convert(reflect.ValueOf(v[i]), a.Type().Elem())
			if !ok {
				return nil, fmt.Errorf("Slice or array at %s has element of type %v, got type %v",
					paths[i-1].Path(), a.Type().Elem(), val.Type())
			}
			if err := assign(a.Index(int(p.Index)), reflect.ValueOf(v[i])); err != nil {
				return nil, err
			}
			v[i-1] = a.Interface()

		case *path.MapIndex:
			m, err := clone(reflect.ValueOf(v[i-1]))
			if err != nil {
				return nil, err
			}
			key, ok := convert(reflect.ValueOf(p.Key), m.Type().Key())
			if !ok {
				return nil, fmt.Errorf("Map at %s has key of type %v, got type %v",
					paths[i-1].Path(), m.Type().Key(), key.Type())
			}
			val, ok := convert(reflect.ValueOf(v[i]), m.Type().Elem())
			if !ok {
				return nil, fmt.Errorf("Map at %s has value of type %v, got type %v",
					paths[i-1].Path(), m.Type().Elem(), val.Type())
			}
			m.SetMapIndex(key, val)
			v[i-1] = m.Interface()

		default:
			return nil, fmt.Errorf("Unknown path type %T", p)
		}
	}

	panic("Unreachable")
}

func clone(v reflect.Value) (reflect.Value, error) {
	var o reflect.Value
	switch v.Kind() {
	case reflect.Slice:
		o = reflect.MakeSlice(v.Type(), v.Len(), v.Len())
	case reflect.Map:
		o = reflect.MakeMap(v.Type())
	default:
		o = reflect.New(v.Type()).Elem()
	}
	return o, shallowCopy(o, v)
}

func shallowCopy(dst, src reflect.Value) error {
	switch dst.Kind() {
	case reflect.Ptr, reflect.Interface:
		if !src.IsNil() {
			o := reflect.New(src.Elem().Type())
			shallowCopy(o.Elem(), src.Elem())
			dst.Set(o)
		}

	case reflect.Slice, reflect.Array:
		reflect.Copy(dst, src)

	case reflect.Map:
		for _, k := range src.MapKeys() {
			val := src.MapIndex(k)
			dst.SetMapIndex(k, val)
		}

	default:
		dst.Set(src)
	}
	return nil
}

func assign(dst, src reflect.Value) error {
	if !dst.CanSet() {
		return fmt.Errorf("Value is unassignable")
	}

	dstTy, srcTy := dst.Type(), src.Type()

	switch {
	case srcTy.AssignableTo(dstTy):
		dst.Set(src)
		return nil

	case srcTy.ConvertibleTo(dstTy):
		dst.Set(src.Convert(dstTy))
		return nil

	default:
		return fmt.Errorf("Cannot assign type %T to type %T", srcTy.Name(), dstTy.Name())
	}
}
