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

import (
	"fmt"
	"reflect"

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

// debug adds panic handlers to encode() and decode() so that incorrectly
// handled types can be more easily identified.
const debug = false

func unbox(v reflect.Value) reflect.Value {
	if v.Kind() == reflect.Interface {
		return v.Elem()
	}
	return v
}

// encode writes the value v to w, using the JDWP encoding scheme.
func (c *Connection) encode(w binary.Writer, v reflect.Value) error {
	if debug {
		defer func() {
			if r := recover(); r != nil {
				panic(fmt.Errorf("Type %T %v %v", v.Interface(), v.Type().Name(), v.Kind()))
			}
		}()
	}

	t := v.Type()
	o := v.Interface()

	switch v.Type() {
	case reflect.TypeOf((*EventModifier)(nil)).Elem():
		// EventModifier's are prefixed with their 1-byte modKind.
		w.Uint8(o.(EventModifier).modKind())

	case reflect.TypeOf((*Value)(nil)).Elem():
		// values are prefixed with their 1-tag type.
		switch o.(type) {
		case ArrayID:
			w.Uint8(uint8(TagArray))
		case byte:
			w.Uint8(uint8(TagByte))
		case Char:
			w.Uint8(uint8(TagChar))
		case ObjectID:
			w.Uint8(uint8(TagObject))
		case float32:
			w.Uint8(uint8(TagFloat))
		case float64:
			w.Uint8(uint8(TagDouble))
		case int, int32:
			w.Uint8(uint8(TagInt))
		case int16:
			w.Uint8(uint8(TagShort))
		case int64:
			w.Uint8(uint8(TagLong))
		case nil:
			w.Uint8(uint8(TagVoid))
		case bool:
			w.Uint8(uint8(TagBoolean))
		case StringID:
			w.Uint8(uint8(TagString))
		case ThreadID:
			w.Uint8(uint8(TagThread))
		case ThreadGroupID:
			w.Uint8(uint8(TagThreadGroup))
		case ClassLoaderID:
			w.Uint8(uint8(TagClassLoader))
		case ClassObjectID:
			w.Uint8(uint8(TagClassObject))
		default:
			panic(fmt.Errorf("Got Value of type %T", o))
		}
	}

	switch o := o.(type) {
	case ReferenceTypeID, ClassID, InterfaceID, ArrayTypeID:
		binary.WriteUint(w, c.idSizes.ReferenceTypeIDSize*8, unbox(v).Uint())

	case MethodID:
		binary.WriteUint(w, c.idSizes.MethodIDSize*8, unbox(v).Uint())

	case ObjectID, ThreadID, ThreadGroupID, StringID, ClassLoaderID, ClassObjectID, ArrayID:
		binary.WriteUint(w, c.idSizes.ObjectIDSize*8, unbox(v).Uint())

	case []byte: // Optimisation
		w.Uint32(uint32(len(o)))
		w.Data(o)

	default:
		switch t.Kind() {
		case reflect.Ptr, reflect.Interface:
			return c.encode(w, v.Elem())
		case reflect.String:
			w.Uint32(uint32(v.Len()))
			w.Data([]byte(v.String()))
		case reflect.Uint8:
			w.Uint8(uint8(v.Uint()))
		case reflect.Uint64:
			w.Uint64(uint64(v.Uint()))
		case reflect.Int8:
			w.Int8(int8(v.Int()))
		case reflect.Int16:
			w.Int16(int16(v.Int()))
		case reflect.Int32, reflect.Int:
			w.Int32(int32(v.Int()))
		case reflect.Int64:
			w.Int64(v.Int())
		case reflect.Float32:
			w.Float32(float32(v.Float()))
		case reflect.Float64:
			w.Float64(v.Float())
		case reflect.Struct:
			for i, count := 0, v.NumField(); i < count; i++ {
				c.encode(w, v.Field(i))
			}
		case reflect.Slice:
			count := v.Len()
			w.Uint32(uint32(count))
			for i := 0; i < count; i++ {
				c.encode(w, v.Index(i))
			}
		default:
			panic(fmt.Errorf("Unhandled type %T %v %v", o, t.Name(), t.Kind()))
		}
	}
	return w.Error()
}

// decode reads the value v from r, using the JDWP encoding scheme.
func (c *Connection) decode(r binary.Reader, v reflect.Value) error {
	if debug {
		defer func() {
			if r := recover(); r != nil {
				panic(fmt.Errorf("Type %T %v %v", v.Interface(), v.Type().Name(), v.Kind()))
			}
		}()
	}

	switch v.Type() {
	case reflect.TypeOf((*Event)(nil)).Elem():
		var kind EventKind
		if err := c.decode(r, reflect.ValueOf(&kind)); err != nil {
			return err
		}
		event := kind.event()
		v.Set(reflect.ValueOf(event))
		v = v.Elem()
		// Continue to decode event body below.

	case reflect.TypeOf((*Value)(nil)).Elem():
		tag := Tag(r.Uint8())
		var ty reflect.Type
		switch tag {
		case TagArray:
			ty = reflect.TypeOf(ArrayID(0))
		case TagByte:
			ty = reflect.TypeOf(byte(0))
		case TagChar:
			ty = reflect.TypeOf(Char(0))
		case TagObject:
			ty = reflect.TypeOf(ObjectID(0))
		case TagFloat:
			ty = reflect.TypeOf(float32(0))
		case TagDouble:
			ty = reflect.TypeOf(float64(0))
		case TagInt:
			ty = reflect.TypeOf(int(0))
		case TagShort:
			ty = reflect.TypeOf(int16(0))
		case TagLong:
			ty = reflect.TypeOf(int64(0))
		case TagBoolean:
			ty = reflect.TypeOf(false)
		case TagString:
			ty = reflect.TypeOf(StringID(0))
		case TagThread:
			ty = reflect.TypeOf(ThreadID(0))
		case TagThreadGroup:
			ty = reflect.TypeOf(ThreadGroupID(0))
		case TagClassLoader:
			ty = reflect.TypeOf(ClassLoaderID(0))
		case TagClassObject:
			ty = reflect.TypeOf(ClassObjectID(0))
		case TagVoid:
			v.Set(reflect.New(v.Type()).Elem())
			return r.Error()
		default:
			panic(fmt.Errorf("Unhandled value type %v", tag))
		}
		data := reflect.New(ty).Elem()
		c.decode(r, data)
		v.Set(data)
		return r.Error()
	}

	t := v.Type()
	o := v.Interface()
	switch o := o.(type) {
	case ReferenceTypeID, ClassID, InterfaceID, ArrayTypeID:
		v.Set(reflect.ValueOf(binary.ReadUint(r, c.idSizes.ReferenceTypeIDSize*8)).Convert(t))

	case MethodID:
		v.Set(reflect.ValueOf(binary.ReadUint(r, c.idSizes.MethodIDSize*8)).Convert(t))

	case ObjectID, ThreadID, ThreadGroupID, StringID, ClassLoaderID, ClassObjectID, ArrayID:
		v.Set(reflect.ValueOf(binary.ReadUint(r, c.idSizes.ObjectIDSize*8)).Convert(t))

	case EventModifier:
		panic("Cannot decode EventModifiers")

	default:
		switch t.Kind() {
		case reflect.Ptr, reflect.Interface:
			return c.decode(r, v.Elem())
		case reflect.String:
			data := make([]byte, r.Uint32())
			r.Data(data)
			v.Set(reflect.ValueOf(string(data)).Convert(t))
		case reflect.Bool:
			v.Set(reflect.ValueOf(r.Bool()).Convert(t))
		case reflect.Uint8:
			v.Set(reflect.ValueOf(r.Uint8()).Convert(t))
		case reflect.Uint64:
			v.Set(reflect.ValueOf(r.Uint64()).Convert(t))
		case reflect.Int8:
			v.Set(reflect.ValueOf(r.Int8()).Convert(t))
		case reflect.Int16:
			v.Set(reflect.ValueOf(r.Int16()).Convert(t))
		case reflect.Int32, reflect.Int:
			v.Set(reflect.ValueOf(r.Int32()).Convert(t))
		case reflect.Int64:
			v.Set(reflect.ValueOf(r.Int64()).Convert(t))
		case reflect.Struct:
			for i, count := 0, v.NumField(); i < count; i++ {
				c.decode(r, v.Field(i))
			}
		case reflect.Slice:
			count := int(r.Uint32())
			slice := reflect.MakeSlice(t, count, count)
			for i := 0; i < count; i++ {
				c.decode(r, slice.Index(i))
			}
			v.Set(slice)
		default:
			panic(fmt.Errorf("Unhandled type %T %v %v", o, t.Name(), t.Kind()))
		}
	}
	return r.Error()
}
