// Copyright 2015 The Vanadium 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 transcoder

import (
	"encoding/binary"
	"fmt"
	"math"

	"v.io/v23/vdl"
)

type target struct {
	currentBitOffset uint8
	current          bytesRef
}

func (t target) allocator() *allocator {
	return t.current.allocator
}

func (t target) FromBool(src bool, tt *vdl.Type) error {
	if src {
		t.current.Bytes()[0] |= 1 << t.currentBitOffset
	}
	// shouldn't have to do anything for false
	return nil
}
func (t target) FromUint(src uint64, tt *vdl.Type) error {
	switch tt.Kind() {
	case vdl.Byte:
		t.current.Bytes()[0] = byte(src)
	case vdl.Uint16:
		binary.LittleEndian.PutUint16(t.current.Bytes(), uint16(src))
	case vdl.Uint32:
		binary.LittleEndian.PutUint32(t.current.Bytes(), uint32(src))
	case vdl.Uint64:
		binary.LittleEndian.PutUint64(t.current.Bytes(), src)
	default:
		return fmt.Errorf("invalid FromUint(%v, %v)", src, tt)
	}
	return nil
}
func (t target) FromInt(src int64, tt *vdl.Type) error {
	switch tt.Kind() {
	case vdl.Int8:
		t.current.Bytes()[0] = byte(src)
	case vdl.Int16:
		binary.LittleEndian.PutUint16(t.current.Bytes(), uint16(src))
	case vdl.Int32:
		binary.LittleEndian.PutUint32(t.current.Bytes(), uint32(src))
	case vdl.Int64:
		binary.LittleEndian.PutUint64(t.current.Bytes(), uint64(src))
	default:
		return fmt.Errorf("invalid FromInt(%v, %v)", src, tt)
	}
	return nil
}
func (t target) FromFloat(src float64, tt *vdl.Type) error {
	switch tt.Kind() {
	case vdl.Float32:
		binary.LittleEndian.PutUint32(t.current.Bytes(), math.Float32bits(float32(src)))
	case vdl.Float64:
		binary.LittleEndian.PutUint64(t.current.Bytes(), math.Float64bits(src))
	default:
		return fmt.Errorf("invalid FromFloat(%v, %v)", src, tt)
	}
	return nil
}
func (t target) FromComplex(src complex128, tt *vdl.Type) error {
	panic("UNIMPLEMENTED")
}
func (t target) writeBytes(src []byte) {
	block := t.allocator().Allocate(uint32(len(src)), uint32(len(src)))
	t.writePointer(block)
	copy(block.Bytes(), src)
}
func (t target) FromBytes(src []byte, tt *vdl.Type) error {
	t.writeBytes(src)
	return nil
}
func (t target) FromString(src string, tt *vdl.Type) error {
	t.writeBytes([]byte(src))
	return nil
}
func (t target) FromEnumLabel(src string, tt *vdl.Type) error {
	// enums in mojo are treated as an int32 on the wire (but have gaps in their values).
	// This implementation assumes that we will use generated VDL values and not have gaps.
	index := tt.EnumIndex(src)
	binary.LittleEndian.PutUint32(t.current.Bytes(), uint32(index))
	return nil
}
func (t target) FromTypeObject(src *vdl.Type) error {
	panic("UNIMPLEMENTED")

}
func (t target) FromNil(tt *vdl.Type) error {
	switch tt.Kind() {
	case vdl.Optional:
		elemType := tt.Elem()
		switch elemType.Kind() {
		case vdl.Union, vdl.Struct: // Array? String? Bytes? List? Set?
			// Note: for union, this zeros 16 bytes, but for others it does just 8.
			zeroBytes(t.current.Bytes())
		default:
			panic(fmt.Sprintf("Vdl type %v cannot be optional", tt))
		}
	case vdl.Any:
		panic("Any rep not yet determined")
	default:
		panic("Type cannot be nil")
	}
	return nil
}
func zeroBytes(dat []byte) {
	copy(dat, make([]byte, len(dat)))
}

func (t target) StartList(tt *vdl.Type, len int) (vdl.ListTarget, error) {
	if tt.Kind() == vdl.Optional {
		tt = tt.Elem()
	}
	bitsNeeded := baseTypeSizeBits(tt.Elem()) * uint32(len)
	block := t.allocator().Allocate((bitsNeeded+7)/8, uint32(len))
	t.writePointer(block)
	if tt.Elem().Kind() == vdl.Bool {
		return &bitListTarget{
			block: block,
		}, nil
	} else {
		return &listTarget{
			incrementSize: baseTypeSizeBits(tt.Elem()) / 8,
			block:         block,
		}, nil
	}
}
func (t target) FinishList(x vdl.ListTarget) error {
	return nil
}

// TODO(bprosnitz) This uses list, should we use map instead?
func (t target) StartSet(tt *vdl.Type, len int) (vdl.SetTarget, error) {
	if tt.Kind() == vdl.Optional {
		tt = tt.Elem()
	}
	bitsNeeded := baseTypeSizeBits(tt.Key()) * uint32(len)
	block := t.allocator().Allocate((bitsNeeded+7)/8, uint32(len))
	t.writePointer(block)
	if tt.Key().Kind() == vdl.Bool {
		return &bitListTarget{
			block: block,
		}, nil
	} else {
		return &listTarget{
			incrementSize: baseTypeSizeBits(tt.Key()) / 8,
			block:         block,
		}, nil
	}
}
func (t target) FinishSet(x vdl.SetTarget) error {
	return nil
}
func (t target) StartMap(tt *vdl.Type, len int) (vdl.MapTarget, error) {
	if tt.Kind() == vdl.Optional {
		tt = tt.Elem()
	}
	pointerBlock := t.allocator().Allocate(16, 0)
	t.writePointer(pointerBlock)

	st := target{
		current: pointerBlock.Slice(0, 8),
	}
	keys, err := st.StartSet(vdl.SetType(tt.Key()), len)
	if err != nil {
		return nil, err
	}
	valuePlaceholder := target{
		current: pointerBlock.Slice(8, 16),
	}
	return &mapTarget{
		keys:             keys,
		valuePlaceholder: valuePlaceholder,
		valueType:        tt.Elem(),
	}, nil
}
func (t target) FinishMap(x vdl.MapTarget) error {
	mt := x.(*mapTarget)
	listTarget, err := mt.valuePlaceholder.StartList(vdl.ListType(mt.valueType), len(mt.cachedValues))
	if err != nil {
		return err
	}
	for i, val := range mt.cachedValues {
		te, err := listTarget.StartElem(i)
		if err != nil {
			return err
		}
		if err := vdl.FromValue(te, val); err != nil {
			return err
		}
		if err := listTarget.FinishElem(te); err != nil {
			return err
		}
	}
	return nil
}
func (t target) StartFields(tt *vdl.Type) (vdl.FieldsTarget, error) {
	if tt.Kind() == vdl.Optional {
		tt = tt.Elem()
	}
	if tt.Kind() == vdl.Union {
		return unionFieldsTarget{
			vdlType: tt,
			block:   t.current,
		}, nil
	}
	block := t.allocator().Allocate(neededStructAllocationSize(tt), 0)
	t.writePointer(block)
	return fieldsTarget{
			vdlType: tt,
			block:   block,
		},
		nil
}
func (t target) FinishFields(x vdl.FieldsTarget) error {
	return nil
}

func (t target) writePointer(alloc bytesRef) {
	offset := alloc.AsPointer(t.current)
	binary.LittleEndian.PutUint64(t.current.Bytes(), uint64(offset))
}
