/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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 thrift

import (
	"context"
	"errors"
	"fmt"
)

const (
	VERSION_MASK = 0xffff0000
	VERSION_1    = 0x80010000
)

type TProtocol interface {
	WriteMessageBegin(ctx context.Context, name string, typeId TMessageType, seqid int32) error
	WriteMessageEnd(ctx context.Context) error
	WriteStructBegin(ctx context.Context, name string) error
	WriteStructEnd(ctx context.Context) error
	WriteFieldBegin(ctx context.Context, name string, typeId TType, id int16) error
	WriteFieldEnd(ctx context.Context) error
	WriteFieldStop(ctx context.Context) error
	WriteMapBegin(ctx context.Context, keyType TType, valueType TType, size int) error
	WriteMapEnd(ctx context.Context) error
	WriteListBegin(ctx context.Context, elemType TType, size int) error
	WriteListEnd(ctx context.Context) error
	WriteSetBegin(ctx context.Context, elemType TType, size int) error
	WriteSetEnd(ctx context.Context) error
	WriteBool(ctx context.Context, value bool) error
	WriteByte(ctx context.Context, value int8) error
	WriteI16(ctx context.Context, value int16) error
	WriteI32(ctx context.Context, value int32) error
	WriteI64(ctx context.Context, value int64) error
	WriteDouble(ctx context.Context, value float64) error
	WriteString(ctx context.Context, value string) error
	WriteBinary(ctx context.Context, value []byte) error
	WriteUUID(ctx context.Context, value Tuuid) error

	ReadMessageBegin(ctx context.Context) (name string, typeId TMessageType, seqid int32, err error)
	ReadMessageEnd(ctx context.Context) error
	ReadStructBegin(ctx context.Context) (name string, err error)
	ReadStructEnd(ctx context.Context) error
	ReadFieldBegin(ctx context.Context) (name string, typeId TType, id int16, err error)
	ReadFieldEnd(ctx context.Context) error
	ReadMapBegin(ctx context.Context) (keyType TType, valueType TType, size int, err error)
	ReadMapEnd(ctx context.Context) error
	ReadListBegin(ctx context.Context) (elemType TType, size int, err error)
	ReadListEnd(ctx context.Context) error
	ReadSetBegin(ctx context.Context) (elemType TType, size int, err error)
	ReadSetEnd(ctx context.Context) error
	ReadBool(ctx context.Context) (value bool, err error)
	ReadByte(ctx context.Context) (value int8, err error)
	ReadI16(ctx context.Context) (value int16, err error)
	ReadI32(ctx context.Context) (value int32, err error)
	ReadI64(ctx context.Context) (value int64, err error)
	ReadDouble(ctx context.Context) (value float64, err error)
	ReadString(ctx context.Context) (value string, err error)
	ReadBinary(ctx context.Context) (value []byte, err error)
	ReadUUID(ctx context.Context) (value Tuuid, err error)

	Skip(ctx context.Context, fieldType TType) (err error)
	Flush(ctx context.Context) (err error)

	Transport() TTransport
}

// The maximum recursive depth the skip() function will traverse
const DEFAULT_RECURSION_DEPTH = 64

// Skips over the next data element from the provided input TProtocol object.
func SkipDefaultDepth(ctx context.Context, prot TProtocol, typeId TType) (err error) {
	return Skip(ctx, prot, typeId, DEFAULT_RECURSION_DEPTH)
}

// Skips over the next data element from the provided input TProtocol object.
func Skip(ctx context.Context, self TProtocol, fieldType TType, maxDepth int) (err error) {

	if maxDepth <= 0 {
		return NewTProtocolExceptionWithType(DEPTH_LIMIT, errors.New("Depth limit exceeded"))
	}

	switch fieldType {
	case BOOL:
		_, err = self.ReadBool(ctx)
		return
	case BYTE:
		_, err = self.ReadByte(ctx)
		return
	case I16:
		_, err = self.ReadI16(ctx)
		return
	case I32:
		_, err = self.ReadI32(ctx)
		return
	case I64:
		_, err = self.ReadI64(ctx)
		return
	case DOUBLE:
		_, err = self.ReadDouble(ctx)
		return
	case STRING:
		_, err = self.ReadString(ctx)
		return
	case UUID:
		_, err = self.ReadUUID(ctx)
		return
	case STRUCT:
		if _, err = self.ReadStructBegin(ctx); err != nil {
			return err
		}
		for {
			_, typeId, _, err := self.ReadFieldBegin(ctx)
			if err != nil {
				return err
			}
			if typeId == STOP {
				break
			}
			err = Skip(ctx, self, typeId, maxDepth-1)
			if err != nil {
				return err
			}
			self.ReadFieldEnd(ctx)
		}
		return self.ReadStructEnd(ctx)
	case MAP:
		keyType, valueType, size, err := self.ReadMapBegin(ctx)
		if err != nil {
			return err
		}
		for i := 0; i < size; i++ {
			err := Skip(ctx, self, keyType, maxDepth-1)
			if err != nil {
				return err
			}

			err = Skip(ctx, self, valueType, maxDepth-1)
			if err != nil {
				return err
			}
		}
		return self.ReadMapEnd(ctx)
	case SET:
		elemType, size, err := self.ReadSetBegin(ctx)
		if err != nil {
			return err
		}
		for i := 0; i < size; i++ {
			err := Skip(ctx, self, elemType, maxDepth-1)
			if err != nil {
				return err
			}
		}
		return self.ReadSetEnd(ctx)
	case LIST:
		elemType, size, err := self.ReadListBegin(ctx)
		if err != nil {
			return err
		}
		for i := 0; i < size; i++ {
			err := Skip(ctx, self, elemType, maxDepth-1)
			if err != nil {
				return err
			}
		}
		return self.ReadListEnd(ctx)
	default:
		return NewTProtocolExceptionWithType(INVALID_DATA, fmt.Errorf("Unknown data type %d", fieldType))
	}
}
