package codec

import (
	

	

	
)

// IntermediateClientStart is starting bytes sent by client in Intermediate mode.
//
// Note that server does not respond with it.
var IntermediateClientStart = [4]byte{0xee, 0xee, 0xee, 0xee}

// Intermediate is intermediate MTProto transport.
//
// See https://core.telegram.org/mtproto/mtproto-transports#intermediate
type Intermediate struct{}

var (
	_ TaggedCodec = Intermediate{}
)

// WriteHeader sends protocol tag.
func ( Intermediate) ( io.Writer) ( error) {
	if ,  := .Write(IntermediateClientStart[:]);  != nil {
		return errors.Wrap(, "write intermediate header")
	}

	return nil
}

// ReadHeader reads protocol tag.
func ( Intermediate) ( io.Reader) ( error) {
	var  [4]byte
	if ,  := io.ReadFull(, [:]);  != nil {
		return errors.Wrap(, "read intermediate header")
	}

	if  != IntermediateClientStart {
		return ErrProtocolHeaderMismatch
	}

	return nil
}

// ObfuscatedTag returns protocol tag for obfuscation.
func ( Intermediate) () [4]byte {
	return IntermediateClientStart
}

// Write encode to writer message from given buffer.
func ( Intermediate) ( io.Writer,  *bin.Buffer) error {
	if  := checkOutgoingMessage();  != nil {
		return 
	}

	if  := checkAlign(, 4);  != nil {
		return 
	}

	if  := writeIntermediate(, );  != nil {
		return errors.Wrap(, "write intermediate")
	}

	return nil
}

// Read fills buffer with received message.
func ( Intermediate) ( io.Reader,  *bin.Buffer) error {
	if  := readIntermediate(, , false);  != nil {
		return errors.Wrap(, "read intermediate")
	}

	return checkProtocolError()
}

// writeIntermediate encodes b as payload to w.
func ( io.Writer,  *bin.Buffer) error {
	 := .Len()
	// Re-using b.Buf if possible to reduce allocations.
	.Expand(4)
	.Buf = .Buf[:]

	 := bin.Buffer{Buf: .Buf[:]}
	.PutInt(.Len())
	if ,  := .Write(.Buf);  != nil {
		return 
	}
	if ,  := .Write(.Buf);  != nil {
		return 
	}
	return nil
}

// readIntermediate reads payload from r to b.
func ( io.Reader,  *bin.Buffer,  bool) error {
	,  := readLen(, )
	if  != nil {
		return 
	}

	.ResetN()
	if ,  := io.ReadFull(, .Buf);  != nil {
		return errors.Wrap(, "read payload")
	}

	if  {
		 :=  % 4
		.Buf = .Buf[:-]
	}

	return nil
}