// Copyright 2017, OpenCensus Authors
//
// 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 tag

import (
	"encoding/binary"
	"fmt"
)

// KeyType defines the types of keys allowed. Currently only keyTypeString is
// supported.
type keyType byte

const (
	keyTypeString keyType = iota
	keyTypeInt64
	keyTypeTrue
	keyTypeFalse

	tagsVersionID = byte(0)
)

type encoderGRPC struct {
	buf               []byte
	writeIdx, readIdx int
}

// writeKeyString writes the fieldID '0' followed by the key string and value
// string.
func (eg *encoderGRPC) writeTagString(k, v string) {
	eg.writeByte(byte(keyTypeString))
	eg.writeStringWithVarintLen(k)
	eg.writeStringWithVarintLen(v)
}

func (eg *encoderGRPC) writeTagUint64(k string, i uint64) {
	eg.writeByte(byte(keyTypeInt64))
	eg.writeStringWithVarintLen(k)
	eg.writeUint64(i)
}

func (eg *encoderGRPC) writeTagTrue(k string) {
	eg.writeByte(byte(keyTypeTrue))
	eg.writeStringWithVarintLen(k)
}

func (eg *encoderGRPC) writeTagFalse(k string) {
	eg.writeByte(byte(keyTypeFalse))
	eg.writeStringWithVarintLen(k)
}

func (eg *encoderGRPC) writeBytesWithVarintLen(bytes []byte) {
	length := len(bytes)

	eg.growIfRequired(binary.MaxVarintLen64 + length)
	eg.writeIdx += binary.PutUvarint(eg.buf[eg.writeIdx:], uint64(length))
	copy(eg.buf[eg.writeIdx:], bytes)
	eg.writeIdx += length
}

func (eg *encoderGRPC) writeStringWithVarintLen(s string) {
	length := len(s)

	eg.growIfRequired(binary.MaxVarintLen64 + length)
	eg.writeIdx += binary.PutUvarint(eg.buf[eg.writeIdx:], uint64(length))
	copy(eg.buf[eg.writeIdx:], s)
	eg.writeIdx += length
}

func (eg *encoderGRPC) writeByte(v byte) {
	eg.growIfRequired(1)
	eg.buf[eg.writeIdx] = v
	eg.writeIdx++
}

func (eg *encoderGRPC) writeUint32(i uint32) {
	eg.growIfRequired(4)
	binary.LittleEndian.PutUint32(eg.buf[eg.writeIdx:], i)
	eg.writeIdx += 4
}

func (eg *encoderGRPC) writeUint64(i uint64) {
	eg.growIfRequired(8)
	binary.LittleEndian.PutUint64(eg.buf[eg.writeIdx:], i)
	eg.writeIdx += 8
}

func (eg *encoderGRPC) readByte() byte {
	b := eg.buf[eg.readIdx]
	eg.readIdx++
	return b
}

func (eg *encoderGRPC) readUint32() uint32 {
	i := binary.LittleEndian.Uint32(eg.buf[eg.readIdx:])
	eg.readIdx += 4
	return i
}

func (eg *encoderGRPC) readUint64() uint64 {
	i := binary.LittleEndian.Uint64(eg.buf[eg.readIdx:])
	eg.readIdx += 8
	return i
}

func (eg *encoderGRPC) readBytesWithVarintLen() ([]byte, error) {
	if eg.readEnded() {
		return nil, fmt.Errorf("unexpected end while readBytesWithVarintLen '%x' starting at idx '%v'", eg.buf, eg.readIdx)
	}
	length, valueStart := binary.Uvarint(eg.buf[eg.readIdx:])
	if valueStart <= 0 {
		return nil, fmt.Errorf("unexpected end while readBytesWithVarintLen '%x' starting at idx '%v'", eg.buf, eg.readIdx)
	}

	valueStart += eg.readIdx
	valueEnd := valueStart + int(length)
	if valueEnd > len(eg.buf) {
		return nil, fmt.Errorf("malformed encoding: length:%v, upper:%v, maxLength:%v", length, valueEnd, len(eg.buf))
	}

	eg.readIdx = valueEnd
	return eg.buf[valueStart:valueEnd], nil
}

func (eg *encoderGRPC) readStringWithVarintLen() (string, error) {
	bytes, err := eg.readBytesWithVarintLen()
	if err != nil {
		return "", err
	}
	return string(bytes), nil
}

func (eg *encoderGRPC) growIfRequired(expected int) {
	if len(eg.buf)-eg.writeIdx < expected {
		tmp := make([]byte, 2*(len(eg.buf)+1)+expected)
		copy(tmp, eg.buf)
		eg.buf = tmp
	}
}

func (eg *encoderGRPC) readEnded() bool {
	return eg.readIdx >= len(eg.buf)
}

func (eg *encoderGRPC) bytes() []byte {
	return eg.buf[:eg.writeIdx]
}

// Encode encodes the tag map into a []byte. It is useful to propagate
// the tag maps on wire in binary format.
func Encode(m *Map) []byte {
	eg := &encoderGRPC{
		buf: make([]byte, len(m.m)),
	}
	eg.writeByte(byte(tagsVersionID))
	for k, v := range m.m {
		eg.writeByte(byte(keyTypeString))
		eg.writeStringWithVarintLen(k.name)
		eg.writeBytesWithVarintLen([]byte(v))
	}
	return eg.bytes()
}

// Decode decodes the given []byte into a tag map.
func Decode(bytes []byte) (*Map, error) {
	ts := newMap()

	eg := &encoderGRPC{
		buf: bytes,
	}
	if len(eg.buf) == 0 {
		return ts, nil
	}

	version := eg.readByte()
	if version > tagsVersionID {
		return nil, fmt.Errorf("cannot decode: unsupported version: %q; supports only up to: %q", version, tagsVersionID)
	}

	for !eg.readEnded() {
		typ := keyType(eg.readByte())

		if typ != keyTypeString {
			return nil, fmt.Errorf("cannot decode: invalid key type: %q", typ)
		}

		k, err := eg.readBytesWithVarintLen()
		if err != nil {
			return nil, err
		}

		v, err := eg.readBytesWithVarintLen()
		if err != nil {
			return nil, err
		}

		key, err := NewKey(string(k))
		if err != nil {
			return nil, err // no partial failures
		}
		val := string(v)
		if !checkValue(val) {
			return nil, errInvalidValue // no partial failures
		}
		ts.upsert(key, val)
	}
	return ts, nil
}
