// Code generated by gotdgen, DO NOT EDIT.

package tdapi

import (
	"context"
	"errors"
	"fmt"
	"sort"
	"strings"

	"go.uber.org/multierr"

	"go.mau.fi/mautrix-telegram/pkg/gotd/bin"
	"go.mau.fi/mautrix-telegram/pkg/gotd/tdjson"
	"go.mau.fi/mautrix-telegram/pkg/gotd/tdp"
	"go.mau.fi/mautrix-telegram/pkg/gotd/tgerr"
)

// No-op definition for keeping imports.
var (
	_ = bin.Buffer{}
	_ = context.Background()
	_ = fmt.Stringer(nil)
	_ = strings.Builder{}
	_ = errors.Is
	_ = multierr.AppendInto
	_ = sort.Ints
	_ = tdp.Format
	_ = tgerr.Error{}
	_ = tdjson.Encoder{}
)

// CallStatePending represents TL type `callStatePending#3ff56c2c`.
type CallStatePending struct {
	// True, if the call has already been created by the server
	IsCreated bool
	// True, if the call has already been received by the other party
	IsReceived bool
}

// CallStatePendingTypeID is TL type id of CallStatePending.
const CallStatePendingTypeID = 0x3ff56c2c

// construct implements constructor of CallStateClass.
func (c CallStatePending) construct() CallStateClass { return &c }

// Ensuring interfaces in compile-time for CallStatePending.
var (
	_ bin.Encoder     = &CallStatePending{}
	_ bin.Decoder     = &CallStatePending{}
	_ bin.BareEncoder = &CallStatePending{}
	_ bin.BareDecoder = &CallStatePending{}

	_ CallStateClass = &CallStatePending{}
)

func (c *CallStatePending) Zero() bool {
	if c == nil {
		return true
	}
	if !(c.IsCreated == false) {
		return false
	}
	if !(c.IsReceived == false) {
		return false
	}

	return true
}

// String implements fmt.Stringer.
func (c *CallStatePending) String() string {
	if c == nil {
		return "CallStatePending(nil)"
	}
	type Alias CallStatePending
	return fmt.Sprintf("CallStatePending%+v", Alias(*c))
}

// TypeID returns type id in TL schema.
//
// See https://core.telegram.org/mtproto/TL-tl#remarks.
func (*CallStatePending) TypeID() uint32 {
	return CallStatePendingTypeID
}

// TypeName returns name of type in TL schema.
func (*CallStatePending) TypeName() string {
	return "callStatePending"
}

// TypeInfo returns info about TL type.
func (c *CallStatePending) TypeInfo() tdp.Type {
	typ := tdp.Type{
		Name: "callStatePending",
		ID:   CallStatePendingTypeID,
	}
	if c == nil {
		typ.Null = true
		return typ
	}
	typ.Fields = []tdp.Field{
		{
			Name:       "IsCreated",
			SchemaName: "is_created",
		},
		{
			Name:       "IsReceived",
			SchemaName: "is_received",
		},
	}
	return typ
}

// Encode implements bin.Encoder.
func (c *CallStatePending) Encode(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't encode callStatePending#3ff56c2c as nil")
	}
	b.PutID(CallStatePendingTypeID)
	return c.EncodeBare(b)
}

// EncodeBare implements bin.BareEncoder.
func (c *CallStatePending) EncodeBare(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't encode callStatePending#3ff56c2c as nil")
	}
	b.PutBool(c.IsCreated)
	b.PutBool(c.IsReceived)
	return nil
}

// Decode implements bin.Decoder.
func (c *CallStatePending) Decode(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't decode callStatePending#3ff56c2c to nil")
	}
	if err := b.ConsumeID(CallStatePendingTypeID); err != nil {
		return fmt.Errorf("unable to decode callStatePending#3ff56c2c: %w", err)
	}
	return c.DecodeBare(b)
}

// DecodeBare implements bin.BareDecoder.
func (c *CallStatePending) DecodeBare(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't decode callStatePending#3ff56c2c to nil")
	}
	{
		value, err := b.Bool()
		if err != nil {
			return fmt.Errorf("unable to decode callStatePending#3ff56c2c: field is_created: %w", err)
		}
		c.IsCreated = value
	}
	{
		value, err := b.Bool()
		if err != nil {
			return fmt.Errorf("unable to decode callStatePending#3ff56c2c: field is_received: %w", err)
		}
		c.IsReceived = value
	}
	return nil
}

// EncodeTDLibJSON implements tdjson.TDLibEncoder.
func (c *CallStatePending) EncodeTDLibJSON(b tdjson.Encoder) error {
	if c == nil {
		return fmt.Errorf("can't encode callStatePending#3ff56c2c as nil")
	}
	b.ObjStart()
	b.PutID("callStatePending")
	b.Comma()
	b.FieldStart("is_created")
	b.PutBool(c.IsCreated)
	b.Comma()
	b.FieldStart("is_received")
	b.PutBool(c.IsReceived)
	b.Comma()
	b.StripComma()
	b.ObjEnd()
	return nil
}

// DecodeTDLibJSON implements tdjson.TDLibDecoder.
func (c *CallStatePending) DecodeTDLibJSON(b tdjson.Decoder) error {
	if c == nil {
		return fmt.Errorf("can't decode callStatePending#3ff56c2c to nil")
	}

	return b.Obj(func(b tdjson.Decoder, key []byte) error {
		switch string(key) {
		case tdjson.TypeField:
			if err := b.ConsumeID("callStatePending"); err != nil {
				return fmt.Errorf("unable to decode callStatePending#3ff56c2c: %w", err)
			}
		case "is_created":
			value, err := b.Bool()
			if err != nil {
				return fmt.Errorf("unable to decode callStatePending#3ff56c2c: field is_created: %w", err)
			}
			c.IsCreated = value
		case "is_received":
			value, err := b.Bool()
			if err != nil {
				return fmt.Errorf("unable to decode callStatePending#3ff56c2c: field is_received: %w", err)
			}
			c.IsReceived = value
		default:
			return b.Skip()
		}
		return nil
	})
}

// GetIsCreated returns value of IsCreated field.
func (c *CallStatePending) GetIsCreated() (value bool) {
	if c == nil {
		return
	}
	return c.IsCreated
}

// GetIsReceived returns value of IsReceived field.
func (c *CallStatePending) GetIsReceived() (value bool) {
	if c == nil {
		return
	}
	return c.IsReceived
}

// CallStateExchangingKeys represents TL type `callStateExchangingKeys#91d77a65`.
type CallStateExchangingKeys struct {
}

// CallStateExchangingKeysTypeID is TL type id of CallStateExchangingKeys.
const CallStateExchangingKeysTypeID = 0x91d77a65

// construct implements constructor of CallStateClass.
func (c CallStateExchangingKeys) construct() CallStateClass { return &c }

// Ensuring interfaces in compile-time for CallStateExchangingKeys.
var (
	_ bin.Encoder     = &CallStateExchangingKeys{}
	_ bin.Decoder     = &CallStateExchangingKeys{}
	_ bin.BareEncoder = &CallStateExchangingKeys{}
	_ bin.BareDecoder = &CallStateExchangingKeys{}

	_ CallStateClass = &CallStateExchangingKeys{}
)

func (c *CallStateExchangingKeys) Zero() bool {
	if c == nil {
		return true
	}

	return true
}

// String implements fmt.Stringer.
func (c *CallStateExchangingKeys) String() string {
	if c == nil {
		return "CallStateExchangingKeys(nil)"
	}
	type Alias CallStateExchangingKeys
	return fmt.Sprintf("CallStateExchangingKeys%+v", Alias(*c))
}

// TypeID returns type id in TL schema.
//
// See https://core.telegram.org/mtproto/TL-tl#remarks.
func (*CallStateExchangingKeys) TypeID() uint32 {
	return CallStateExchangingKeysTypeID
}

// TypeName returns name of type in TL schema.
func (*CallStateExchangingKeys) TypeName() string {
	return "callStateExchangingKeys"
}

// TypeInfo returns info about TL type.
func (c *CallStateExchangingKeys) TypeInfo() tdp.Type {
	typ := tdp.Type{
		Name: "callStateExchangingKeys",
		ID:   CallStateExchangingKeysTypeID,
	}
	if c == nil {
		typ.Null = true
		return typ
	}
	typ.Fields = []tdp.Field{}
	return typ
}

// Encode implements bin.Encoder.
func (c *CallStateExchangingKeys) Encode(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't encode callStateExchangingKeys#91d77a65 as nil")
	}
	b.PutID(CallStateExchangingKeysTypeID)
	return c.EncodeBare(b)
}

// EncodeBare implements bin.BareEncoder.
func (c *CallStateExchangingKeys) EncodeBare(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't encode callStateExchangingKeys#91d77a65 as nil")
	}
	return nil
}

// Decode implements bin.Decoder.
func (c *CallStateExchangingKeys) Decode(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't decode callStateExchangingKeys#91d77a65 to nil")
	}
	if err := b.ConsumeID(CallStateExchangingKeysTypeID); err != nil {
		return fmt.Errorf("unable to decode callStateExchangingKeys#91d77a65: %w", err)
	}
	return c.DecodeBare(b)
}

// DecodeBare implements bin.BareDecoder.
func (c *CallStateExchangingKeys) DecodeBare(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't decode callStateExchangingKeys#91d77a65 to nil")
	}
	return nil
}

// EncodeTDLibJSON implements tdjson.TDLibEncoder.
func (c *CallStateExchangingKeys) EncodeTDLibJSON(b tdjson.Encoder) error {
	if c == nil {
		return fmt.Errorf("can't encode callStateExchangingKeys#91d77a65 as nil")
	}
	b.ObjStart()
	b.PutID("callStateExchangingKeys")
	b.Comma()
	b.StripComma()
	b.ObjEnd()
	return nil
}

// DecodeTDLibJSON implements tdjson.TDLibDecoder.
func (c *CallStateExchangingKeys) DecodeTDLibJSON(b tdjson.Decoder) error {
	if c == nil {
		return fmt.Errorf("can't decode callStateExchangingKeys#91d77a65 to nil")
	}

	return b.Obj(func(b tdjson.Decoder, key []byte) error {
		switch string(key) {
		case tdjson.TypeField:
			if err := b.ConsumeID("callStateExchangingKeys"); err != nil {
				return fmt.Errorf("unable to decode callStateExchangingKeys#91d77a65: %w", err)
			}
		default:
			return b.Skip()
		}
		return nil
	})
}

// CallStateReady represents TL type `callStateReady#dfc6b953`.
type CallStateReady struct {
	// Call protocols supported by the other call participant
	Protocol CallProtocol
	// List of available call servers
	Servers []CallServer
	// A JSON-encoded call config
	Config string
	// Call encryption key
	EncryptionKey []byte
	// Encryption key fingerprint represented as 4 emoji
	Emojis []string
	// True, if peer-to-peer connection is allowed by users privacy settings
	AllowP2P bool
	// True, if the other party supports upgrading of the call to a group call
	IsGroupCallSupported bool
	// Custom JSON-encoded call parameters to be passed to tgcalls
	CustomParameters string
}

// CallStateReadyTypeID is TL type id of CallStateReady.
const CallStateReadyTypeID = 0xdfc6b953

// construct implements constructor of CallStateClass.
func (c CallStateReady) construct() CallStateClass { return &c }

// Ensuring interfaces in compile-time for CallStateReady.
var (
	_ bin.Encoder     = &CallStateReady{}
	_ bin.Decoder     = &CallStateReady{}
	_ bin.BareEncoder = &CallStateReady{}
	_ bin.BareDecoder = &CallStateReady{}

	_ CallStateClass = &CallStateReady{}
)

func (c *CallStateReady) Zero() bool {
	if c == nil {
		return true
	}
	if !(c.Protocol.Zero()) {
		return false
	}
	if !(c.Servers == nil) {
		return false
	}
	if !(c.Config == "") {
		return false
	}
	if !(c.EncryptionKey == nil) {
		return false
	}
	if !(c.Emojis == nil) {
		return false
	}
	if !(c.AllowP2P == false) {
		return false
	}
	if !(c.IsGroupCallSupported == false) {
		return false
	}
	if !(c.CustomParameters == "") {
		return false
	}

	return true
}

// String implements fmt.Stringer.
func (c *CallStateReady) String() string {
	if c == nil {
		return "CallStateReady(nil)"
	}
	type Alias CallStateReady
	return fmt.Sprintf("CallStateReady%+v", Alias(*c))
}

// TypeID returns type id in TL schema.
//
// See https://core.telegram.org/mtproto/TL-tl#remarks.
func (*CallStateReady) TypeID() uint32 {
	return CallStateReadyTypeID
}

// TypeName returns name of type in TL schema.
func (*CallStateReady) TypeName() string {
	return "callStateReady"
}

// TypeInfo returns info about TL type.
func (c *CallStateReady) TypeInfo() tdp.Type {
	typ := tdp.Type{
		Name: "callStateReady",
		ID:   CallStateReadyTypeID,
	}
	if c == nil {
		typ.Null = true
		return typ
	}
	typ.Fields = []tdp.Field{
		{
			Name:       "Protocol",
			SchemaName: "protocol",
		},
		{
			Name:       "Servers",
			SchemaName: "servers",
		},
		{
			Name:       "Config",
			SchemaName: "config",
		},
		{
			Name:       "EncryptionKey",
			SchemaName: "encryption_key",
		},
		{
			Name:       "Emojis",
			SchemaName: "emojis",
		},
		{
			Name:       "AllowP2P",
			SchemaName: "allow_p2p",
		},
		{
			Name:       "IsGroupCallSupported",
			SchemaName: "is_group_call_supported",
		},
		{
			Name:       "CustomParameters",
			SchemaName: "custom_parameters",
		},
	}
	return typ
}

// Encode implements bin.Encoder.
func (c *CallStateReady) Encode(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't encode callStateReady#dfc6b953 as nil")
	}
	b.PutID(CallStateReadyTypeID)
	return c.EncodeBare(b)
}

// EncodeBare implements bin.BareEncoder.
func (c *CallStateReady) EncodeBare(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't encode callStateReady#dfc6b953 as nil")
	}
	if err := c.Protocol.Encode(b); err != nil {
		return fmt.Errorf("unable to encode callStateReady#dfc6b953: field protocol: %w", err)
	}
	b.PutInt(len(c.Servers))
	for idx, v := range c.Servers {
		if err := v.EncodeBare(b); err != nil {
			return fmt.Errorf("unable to encode bare callStateReady#dfc6b953: field servers element with index %d: %w", idx, err)
		}
	}
	b.PutString(c.Config)
	b.PutBytes(c.EncryptionKey)
	b.PutInt(len(c.Emojis))
	for _, v := range c.Emojis {
		b.PutString(v)
	}
	b.PutBool(c.AllowP2P)
	b.PutBool(c.IsGroupCallSupported)
	b.PutString(c.CustomParameters)
	return nil
}

// Decode implements bin.Decoder.
func (c *CallStateReady) Decode(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't decode callStateReady#dfc6b953 to nil")
	}
	if err := b.ConsumeID(CallStateReadyTypeID); err != nil {
		return fmt.Errorf("unable to decode callStateReady#dfc6b953: %w", err)
	}
	return c.DecodeBare(b)
}

// DecodeBare implements bin.BareDecoder.
func (c *CallStateReady) DecodeBare(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't decode callStateReady#dfc6b953 to nil")
	}
	{
		if err := c.Protocol.Decode(b); err != nil {
			return fmt.Errorf("unable to decode callStateReady#dfc6b953: field protocol: %w", err)
		}
	}
	{
		headerLen, err := b.Int()
		if err != nil {
			return fmt.Errorf("unable to decode callStateReady#dfc6b953: field servers: %w", err)
		}

		if headerLen > 0 {
			c.Servers = make([]CallServer, 0, headerLen%bin.PreallocateLimit)
		}
		for idx := 0; idx < headerLen; idx++ {
			var value CallServer
			if err := value.DecodeBare(b); err != nil {
				return fmt.Errorf("unable to decode bare callStateReady#dfc6b953: field servers: %w", err)
			}
			c.Servers = append(c.Servers, value)
		}
	}
	{
		value, err := b.String()
		if err != nil {
			return fmt.Errorf("unable to decode callStateReady#dfc6b953: field config: %w", err)
		}
		c.Config = value
	}
	{
		value, err := b.Bytes()
		if err != nil {
			return fmt.Errorf("unable to decode callStateReady#dfc6b953: field encryption_key: %w", err)
		}
		c.EncryptionKey = value
	}
	{
		headerLen, err := b.Int()
		if err != nil {
			return fmt.Errorf("unable to decode callStateReady#dfc6b953: field emojis: %w", err)
		}

		if headerLen > 0 {
			c.Emojis = make([]string, 0, headerLen%bin.PreallocateLimit)
		}
		for idx := 0; idx < headerLen; idx++ {
			value, err := b.String()
			if err != nil {
				return fmt.Errorf("unable to decode callStateReady#dfc6b953: field emojis: %w", err)
			}
			c.Emojis = append(c.Emojis, value)
		}
	}
	{
		value, err := b.Bool()
		if err != nil {
			return fmt.Errorf("unable to decode callStateReady#dfc6b953: field allow_p2p: %w", err)
		}
		c.AllowP2P = value
	}
	{
		value, err := b.Bool()
		if err != nil {
			return fmt.Errorf("unable to decode callStateReady#dfc6b953: field is_group_call_supported: %w", err)
		}
		c.IsGroupCallSupported = value
	}
	{
		value, err := b.String()
		if err != nil {
			return fmt.Errorf("unable to decode callStateReady#dfc6b953: field custom_parameters: %w", err)
		}
		c.CustomParameters = value
	}
	return nil
}

// EncodeTDLibJSON implements tdjson.TDLibEncoder.
func (c *CallStateReady) EncodeTDLibJSON(b tdjson.Encoder) error {
	if c == nil {
		return fmt.Errorf("can't encode callStateReady#dfc6b953 as nil")
	}
	b.ObjStart()
	b.PutID("callStateReady")
	b.Comma()
	b.FieldStart("protocol")
	if err := c.Protocol.EncodeTDLibJSON(b); err != nil {
		return fmt.Errorf("unable to encode callStateReady#dfc6b953: field protocol: %w", err)
	}
	b.Comma()
	b.FieldStart("servers")
	b.ArrStart()
	for idx, v := range c.Servers {
		if err := v.EncodeTDLibJSON(b); err != nil {
			return fmt.Errorf("unable to encode callStateReady#dfc6b953: field servers element with index %d: %w", idx, err)
		}
		b.Comma()
	}
	b.StripComma()
	b.ArrEnd()
	b.Comma()
	b.FieldStart("config")
	b.PutString(c.Config)
	b.Comma()
	b.FieldStart("encryption_key")
	b.PutBytes(c.EncryptionKey)
	b.Comma()
	b.FieldStart("emojis")
	b.ArrStart()
	for _, v := range c.Emojis {
		b.PutString(v)
		b.Comma()
	}
	b.StripComma()
	b.ArrEnd()
	b.Comma()
	b.FieldStart("allow_p2p")
	b.PutBool(c.AllowP2P)
	b.Comma()
	b.FieldStart("is_group_call_supported")
	b.PutBool(c.IsGroupCallSupported)
	b.Comma()
	b.FieldStart("custom_parameters")
	b.PutString(c.CustomParameters)
	b.Comma()
	b.StripComma()
	b.ObjEnd()
	return nil
}

// DecodeTDLibJSON implements tdjson.TDLibDecoder.
func (c *CallStateReady) DecodeTDLibJSON(b tdjson.Decoder) error {
	if c == nil {
		return fmt.Errorf("can't decode callStateReady#dfc6b953 to nil")
	}

	return b.Obj(func(b tdjson.Decoder, key []byte) error {
		switch string(key) {
		case tdjson.TypeField:
			if err := b.ConsumeID("callStateReady"); err != nil {
				return fmt.Errorf("unable to decode callStateReady#dfc6b953: %w", err)
			}
		case "protocol":
			if err := c.Protocol.DecodeTDLibJSON(b); err != nil {
				return fmt.Errorf("unable to decode callStateReady#dfc6b953: field protocol: %w", err)
			}
		case "servers":
			if err := b.Arr(func(b tdjson.Decoder) error {
				var value CallServer
				if err := value.DecodeTDLibJSON(b); err != nil {
					return fmt.Errorf("unable to decode callStateReady#dfc6b953: field servers: %w", err)
				}
				c.Servers = append(c.Servers, value)
				return nil
			}); err != nil {
				return fmt.Errorf("unable to decode callStateReady#dfc6b953: field servers: %w", err)
			}
		case "config":
			value, err := b.String()
			if err != nil {
				return fmt.Errorf("unable to decode callStateReady#dfc6b953: field config: %w", err)
			}
			c.Config = value
		case "encryption_key":
			value, err := b.Bytes()
			if err != nil {
				return fmt.Errorf("unable to decode callStateReady#dfc6b953: field encryption_key: %w", err)
			}
			c.EncryptionKey = value
		case "emojis":
			if err := b.Arr(func(b tdjson.Decoder) error {
				value, err := b.String()
				if err != nil {
					return fmt.Errorf("unable to decode callStateReady#dfc6b953: field emojis: %w", err)
				}
				c.Emojis = append(c.Emojis, value)
				return nil
			}); err != nil {
				return fmt.Errorf("unable to decode callStateReady#dfc6b953: field emojis: %w", err)
			}
		case "allow_p2p":
			value, err := b.Bool()
			if err != nil {
				return fmt.Errorf("unable to decode callStateReady#dfc6b953: field allow_p2p: %w", err)
			}
			c.AllowP2P = value
		case "is_group_call_supported":
			value, err := b.Bool()
			if err != nil {
				return fmt.Errorf("unable to decode callStateReady#dfc6b953: field is_group_call_supported: %w", err)
			}
			c.IsGroupCallSupported = value
		case "custom_parameters":
			value, err := b.String()
			if err != nil {
				return fmt.Errorf("unable to decode callStateReady#dfc6b953: field custom_parameters: %w", err)
			}
			c.CustomParameters = value
		default:
			return b.Skip()
		}
		return nil
	})
}

// GetProtocol returns value of Protocol field.
func (c *CallStateReady) GetProtocol() (value CallProtocol) {
	if c == nil {
		return
	}
	return c.Protocol
}

// GetServers returns value of Servers field.
func (c *CallStateReady) GetServers() (value []CallServer) {
	if c == nil {
		return
	}
	return c.Servers
}

// GetConfig returns value of Config field.
func (c *CallStateReady) GetConfig() (value string) {
	if c == nil {
		return
	}
	return c.Config
}

// GetEncryptionKey returns value of EncryptionKey field.
func (c *CallStateReady) GetEncryptionKey() (value []byte) {
	if c == nil {
		return
	}
	return c.EncryptionKey
}

// GetEmojis returns value of Emojis field.
func (c *CallStateReady) GetEmojis() (value []string) {
	if c == nil {
		return
	}
	return c.Emojis
}

// GetAllowP2P returns value of AllowP2P field.
func (c *CallStateReady) GetAllowP2P() (value bool) {
	if c == nil {
		return
	}
	return c.AllowP2P
}

// GetIsGroupCallSupported returns value of IsGroupCallSupported field.
func (c *CallStateReady) GetIsGroupCallSupported() (value bool) {
	if c == nil {
		return
	}
	return c.IsGroupCallSupported
}

// GetCustomParameters returns value of CustomParameters field.
func (c *CallStateReady) GetCustomParameters() (value string) {
	if c == nil {
		return
	}
	return c.CustomParameters
}

// CallStateHangingUp represents TL type `callStateHangingUp#80d0f2aa`.
type CallStateHangingUp struct {
}

// CallStateHangingUpTypeID is TL type id of CallStateHangingUp.
const CallStateHangingUpTypeID = 0x80d0f2aa

// construct implements constructor of CallStateClass.
func (c CallStateHangingUp) construct() CallStateClass { return &c }

// Ensuring interfaces in compile-time for CallStateHangingUp.
var (
	_ bin.Encoder     = &CallStateHangingUp{}
	_ bin.Decoder     = &CallStateHangingUp{}
	_ bin.BareEncoder = &CallStateHangingUp{}
	_ bin.BareDecoder = &CallStateHangingUp{}

	_ CallStateClass = &CallStateHangingUp{}
)

func (c *CallStateHangingUp) Zero() bool {
	if c == nil {
		return true
	}

	return true
}

// String implements fmt.Stringer.
func (c *CallStateHangingUp) String() string {
	if c == nil {
		return "CallStateHangingUp(nil)"
	}
	type Alias CallStateHangingUp
	return fmt.Sprintf("CallStateHangingUp%+v", Alias(*c))
}

// TypeID returns type id in TL schema.
//
// See https://core.telegram.org/mtproto/TL-tl#remarks.
func (*CallStateHangingUp) TypeID() uint32 {
	return CallStateHangingUpTypeID
}

// TypeName returns name of type in TL schema.
func (*CallStateHangingUp) TypeName() string {
	return "callStateHangingUp"
}

// TypeInfo returns info about TL type.
func (c *CallStateHangingUp) TypeInfo() tdp.Type {
	typ := tdp.Type{
		Name: "callStateHangingUp",
		ID:   CallStateHangingUpTypeID,
	}
	if c == nil {
		typ.Null = true
		return typ
	}
	typ.Fields = []tdp.Field{}
	return typ
}

// Encode implements bin.Encoder.
func (c *CallStateHangingUp) Encode(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't encode callStateHangingUp#80d0f2aa as nil")
	}
	b.PutID(CallStateHangingUpTypeID)
	return c.EncodeBare(b)
}

// EncodeBare implements bin.BareEncoder.
func (c *CallStateHangingUp) EncodeBare(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't encode callStateHangingUp#80d0f2aa as nil")
	}
	return nil
}

// Decode implements bin.Decoder.
func (c *CallStateHangingUp) Decode(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't decode callStateHangingUp#80d0f2aa to nil")
	}
	if err := b.ConsumeID(CallStateHangingUpTypeID); err != nil {
		return fmt.Errorf("unable to decode callStateHangingUp#80d0f2aa: %w", err)
	}
	return c.DecodeBare(b)
}

// DecodeBare implements bin.BareDecoder.
func (c *CallStateHangingUp) DecodeBare(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't decode callStateHangingUp#80d0f2aa to nil")
	}
	return nil
}

// EncodeTDLibJSON implements tdjson.TDLibEncoder.
func (c *CallStateHangingUp) EncodeTDLibJSON(b tdjson.Encoder) error {
	if c == nil {
		return fmt.Errorf("can't encode callStateHangingUp#80d0f2aa as nil")
	}
	b.ObjStart()
	b.PutID("callStateHangingUp")
	b.Comma()
	b.StripComma()
	b.ObjEnd()
	return nil
}

// DecodeTDLibJSON implements tdjson.TDLibDecoder.
func (c *CallStateHangingUp) DecodeTDLibJSON(b tdjson.Decoder) error {
	if c == nil {
		return fmt.Errorf("can't decode callStateHangingUp#80d0f2aa to nil")
	}

	return b.Obj(func(b tdjson.Decoder, key []byte) error {
		switch string(key) {
		case tdjson.TypeField:
			if err := b.ConsumeID("callStateHangingUp"); err != nil {
				return fmt.Errorf("unable to decode callStateHangingUp#80d0f2aa: %w", err)
			}
		default:
			return b.Skip()
		}
		return nil
	})
}

// CallStateDiscarded represents TL type `callStateDiscarded#531b7c45`.
type CallStateDiscarded struct {
	// The reason why the call has ended
	Reason CallDiscardReasonClass
	// True, if the call rating must be sent to the server
	NeedRating bool
	// True, if the call debug information must be sent to the server
	NeedDebugInformation bool
	// True, if the call log must be sent to the server
	NeedLog bool
}

// CallStateDiscardedTypeID is TL type id of CallStateDiscarded.
const CallStateDiscardedTypeID = 0x531b7c45

// construct implements constructor of CallStateClass.
func (c CallStateDiscarded) construct() CallStateClass { return &c }

// Ensuring interfaces in compile-time for CallStateDiscarded.
var (
	_ bin.Encoder     = &CallStateDiscarded{}
	_ bin.Decoder     = &CallStateDiscarded{}
	_ bin.BareEncoder = &CallStateDiscarded{}
	_ bin.BareDecoder = &CallStateDiscarded{}

	_ CallStateClass = &CallStateDiscarded{}
)

func (c *CallStateDiscarded) Zero() bool {
	if c == nil {
		return true
	}
	if !(c.Reason == nil) {
		return false
	}
	if !(c.NeedRating == false) {
		return false
	}
	if !(c.NeedDebugInformation == false) {
		return false
	}
	if !(c.NeedLog == false) {
		return false
	}

	return true
}

// String implements fmt.Stringer.
func (c *CallStateDiscarded) String() string {
	if c == nil {
		return "CallStateDiscarded(nil)"
	}
	type Alias CallStateDiscarded
	return fmt.Sprintf("CallStateDiscarded%+v", Alias(*c))
}

// TypeID returns type id in TL schema.
//
// See https://core.telegram.org/mtproto/TL-tl#remarks.
func (*CallStateDiscarded) TypeID() uint32 {
	return CallStateDiscardedTypeID
}

// TypeName returns name of type in TL schema.
func (*CallStateDiscarded) TypeName() string {
	return "callStateDiscarded"
}

// TypeInfo returns info about TL type.
func (c *CallStateDiscarded) TypeInfo() tdp.Type {
	typ := tdp.Type{
		Name: "callStateDiscarded",
		ID:   CallStateDiscardedTypeID,
	}
	if c == nil {
		typ.Null = true
		return typ
	}
	typ.Fields = []tdp.Field{
		{
			Name:       "Reason",
			SchemaName: "reason",
		},
		{
			Name:       "NeedRating",
			SchemaName: "need_rating",
		},
		{
			Name:       "NeedDebugInformation",
			SchemaName: "need_debug_information",
		},
		{
			Name:       "NeedLog",
			SchemaName: "need_log",
		},
	}
	return typ
}

// Encode implements bin.Encoder.
func (c *CallStateDiscarded) Encode(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't encode callStateDiscarded#531b7c45 as nil")
	}
	b.PutID(CallStateDiscardedTypeID)
	return c.EncodeBare(b)
}

// EncodeBare implements bin.BareEncoder.
func (c *CallStateDiscarded) EncodeBare(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't encode callStateDiscarded#531b7c45 as nil")
	}
	if c.Reason == nil {
		return fmt.Errorf("unable to encode callStateDiscarded#531b7c45: field reason is nil")
	}
	if err := c.Reason.Encode(b); err != nil {
		return fmt.Errorf("unable to encode callStateDiscarded#531b7c45: field reason: %w", err)
	}
	b.PutBool(c.NeedRating)
	b.PutBool(c.NeedDebugInformation)
	b.PutBool(c.NeedLog)
	return nil
}

// Decode implements bin.Decoder.
func (c *CallStateDiscarded) Decode(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't decode callStateDiscarded#531b7c45 to nil")
	}
	if err := b.ConsumeID(CallStateDiscardedTypeID); err != nil {
		return fmt.Errorf("unable to decode callStateDiscarded#531b7c45: %w", err)
	}
	return c.DecodeBare(b)
}

// DecodeBare implements bin.BareDecoder.
func (c *CallStateDiscarded) DecodeBare(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't decode callStateDiscarded#531b7c45 to nil")
	}
	{
		value, err := DecodeCallDiscardReason(b)
		if err != nil {
			return fmt.Errorf("unable to decode callStateDiscarded#531b7c45: field reason: %w", err)
		}
		c.Reason = value
	}
	{
		value, err := b.Bool()
		if err != nil {
			return fmt.Errorf("unable to decode callStateDiscarded#531b7c45: field need_rating: %w", err)
		}
		c.NeedRating = value
	}
	{
		value, err := b.Bool()
		if err != nil {
			return fmt.Errorf("unable to decode callStateDiscarded#531b7c45: field need_debug_information: %w", err)
		}
		c.NeedDebugInformation = value
	}
	{
		value, err := b.Bool()
		if err != nil {
			return fmt.Errorf("unable to decode callStateDiscarded#531b7c45: field need_log: %w", err)
		}
		c.NeedLog = value
	}
	return nil
}

// EncodeTDLibJSON implements tdjson.TDLibEncoder.
func (c *CallStateDiscarded) EncodeTDLibJSON(b tdjson.Encoder) error {
	if c == nil {
		return fmt.Errorf("can't encode callStateDiscarded#531b7c45 as nil")
	}
	b.ObjStart()
	b.PutID("callStateDiscarded")
	b.Comma()
	b.FieldStart("reason")
	if c.Reason == nil {
		return fmt.Errorf("unable to encode callStateDiscarded#531b7c45: field reason is nil")
	}
	if err := c.Reason.EncodeTDLibJSON(b); err != nil {
		return fmt.Errorf("unable to encode callStateDiscarded#531b7c45: field reason: %w", err)
	}
	b.Comma()
	b.FieldStart("need_rating")
	b.PutBool(c.NeedRating)
	b.Comma()
	b.FieldStart("need_debug_information")
	b.PutBool(c.NeedDebugInformation)
	b.Comma()
	b.FieldStart("need_log")
	b.PutBool(c.NeedLog)
	b.Comma()
	b.StripComma()
	b.ObjEnd()
	return nil
}

// DecodeTDLibJSON implements tdjson.TDLibDecoder.
func (c *CallStateDiscarded) DecodeTDLibJSON(b tdjson.Decoder) error {
	if c == nil {
		return fmt.Errorf("can't decode callStateDiscarded#531b7c45 to nil")
	}

	return b.Obj(func(b tdjson.Decoder, key []byte) error {
		switch string(key) {
		case tdjson.TypeField:
			if err := b.ConsumeID("callStateDiscarded"); err != nil {
				return fmt.Errorf("unable to decode callStateDiscarded#531b7c45: %w", err)
			}
		case "reason":
			value, err := DecodeTDLibJSONCallDiscardReason(b)
			if err != nil {
				return fmt.Errorf("unable to decode callStateDiscarded#531b7c45: field reason: %w", err)
			}
			c.Reason = value
		case "need_rating":
			value, err := b.Bool()
			if err != nil {
				return fmt.Errorf("unable to decode callStateDiscarded#531b7c45: field need_rating: %w", err)
			}
			c.NeedRating = value
		case "need_debug_information":
			value, err := b.Bool()
			if err != nil {
				return fmt.Errorf("unable to decode callStateDiscarded#531b7c45: field need_debug_information: %w", err)
			}
			c.NeedDebugInformation = value
		case "need_log":
			value, err := b.Bool()
			if err != nil {
				return fmt.Errorf("unable to decode callStateDiscarded#531b7c45: field need_log: %w", err)
			}
			c.NeedLog = value
		default:
			return b.Skip()
		}
		return nil
	})
}

// GetReason returns value of Reason field.
func (c *CallStateDiscarded) GetReason() (value CallDiscardReasonClass) {
	if c == nil {
		return
	}
	return c.Reason
}

// GetNeedRating returns value of NeedRating field.
func (c *CallStateDiscarded) GetNeedRating() (value bool) {
	if c == nil {
		return
	}
	return c.NeedRating
}

// GetNeedDebugInformation returns value of NeedDebugInformation field.
func (c *CallStateDiscarded) GetNeedDebugInformation() (value bool) {
	if c == nil {
		return
	}
	return c.NeedDebugInformation
}

// GetNeedLog returns value of NeedLog field.
func (c *CallStateDiscarded) GetNeedLog() (value bool) {
	if c == nil {
		return
	}
	return c.NeedLog
}

// CallStateError represents TL type `callStateError#c5df6495`.
type CallStateError struct {
	// Error. An error with the code 4005000 will be returned if an outgoing call is missed
	// because of an expired timeout
	Error Error
}

// CallStateErrorTypeID is TL type id of CallStateError.
const CallStateErrorTypeID = 0xc5df6495

// construct implements constructor of CallStateClass.
func (c CallStateError) construct() CallStateClass { return &c }

// Ensuring interfaces in compile-time for CallStateError.
var (
	_ bin.Encoder     = &CallStateError{}
	_ bin.Decoder     = &CallStateError{}
	_ bin.BareEncoder = &CallStateError{}
	_ bin.BareDecoder = &CallStateError{}

	_ CallStateClass = &CallStateError{}
)

func (c *CallStateError) Zero() bool {
	if c == nil {
		return true
	}
	if !(c.Error.Zero()) {
		return false
	}

	return true
}

// String implements fmt.Stringer.
func (c *CallStateError) String() string {
	if c == nil {
		return "CallStateError(nil)"
	}
	type Alias CallStateError
	return fmt.Sprintf("CallStateError%+v", Alias(*c))
}

// TypeID returns type id in TL schema.
//
// See https://core.telegram.org/mtproto/TL-tl#remarks.
func (*CallStateError) TypeID() uint32 {
	return CallStateErrorTypeID
}

// TypeName returns name of type in TL schema.
func (*CallStateError) TypeName() string {
	return "callStateError"
}

// TypeInfo returns info about TL type.
func (c *CallStateError) TypeInfo() tdp.Type {
	typ := tdp.Type{
		Name: "callStateError",
		ID:   CallStateErrorTypeID,
	}
	if c == nil {
		typ.Null = true
		return typ
	}
	typ.Fields = []tdp.Field{
		{
			Name:       "Error",
			SchemaName: "error",
		},
	}
	return typ
}

// Encode implements bin.Encoder.
func (c *CallStateError) Encode(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't encode callStateError#c5df6495 as nil")
	}
	b.PutID(CallStateErrorTypeID)
	return c.EncodeBare(b)
}

// EncodeBare implements bin.BareEncoder.
func (c *CallStateError) EncodeBare(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't encode callStateError#c5df6495 as nil")
	}
	if err := c.Error.Encode(b); err != nil {
		return fmt.Errorf("unable to encode callStateError#c5df6495: field error: %w", err)
	}
	return nil
}

// Decode implements bin.Decoder.
func (c *CallStateError) Decode(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't decode callStateError#c5df6495 to nil")
	}
	if err := b.ConsumeID(CallStateErrorTypeID); err != nil {
		return fmt.Errorf("unable to decode callStateError#c5df6495: %w", err)
	}
	return c.DecodeBare(b)
}

// DecodeBare implements bin.BareDecoder.
func (c *CallStateError) DecodeBare(b *bin.Buffer) error {
	if c == nil {
		return fmt.Errorf("can't decode callStateError#c5df6495 to nil")
	}
	{
		if err := c.Error.Decode(b); err != nil {
			return fmt.Errorf("unable to decode callStateError#c5df6495: field error: %w", err)
		}
	}
	return nil
}

// EncodeTDLibJSON implements tdjson.TDLibEncoder.
func (c *CallStateError) EncodeTDLibJSON(b tdjson.Encoder) error {
	if c == nil {
		return fmt.Errorf("can't encode callStateError#c5df6495 as nil")
	}
	b.ObjStart()
	b.PutID("callStateError")
	b.Comma()
	b.FieldStart("error")
	if err := c.Error.EncodeTDLibJSON(b); err != nil {
		return fmt.Errorf("unable to encode callStateError#c5df6495: field error: %w", err)
	}
	b.Comma()
	b.StripComma()
	b.ObjEnd()
	return nil
}

// DecodeTDLibJSON implements tdjson.TDLibDecoder.
func (c *CallStateError) DecodeTDLibJSON(b tdjson.Decoder) error {
	if c == nil {
		return fmt.Errorf("can't decode callStateError#c5df6495 to nil")
	}

	return b.Obj(func(b tdjson.Decoder, key []byte) error {
		switch string(key) {
		case tdjson.TypeField:
			if err := b.ConsumeID("callStateError"); err != nil {
				return fmt.Errorf("unable to decode callStateError#c5df6495: %w", err)
			}
		case "error":
			if err := c.Error.DecodeTDLibJSON(b); err != nil {
				return fmt.Errorf("unable to decode callStateError#c5df6495: field error: %w", err)
			}
		default:
			return b.Skip()
		}
		return nil
	})
}

// GetError returns value of Error field.
func (c *CallStateError) GetError() (value Error) {
	if c == nil {
		return
	}
	return c.Error
}

// CallStateClassName is schema name of CallStateClass.
const CallStateClassName = "CallState"

// CallStateClass represents CallState generic type.
//
// Example:
//
//	g, err := tdapi.DecodeCallState(buf)
//	if err != nil {
//	    panic(err)
//	}
//	switch v := g.(type) {
//	case *tdapi.CallStatePending: // callStatePending#3ff56c2c
//	case *tdapi.CallStateExchangingKeys: // callStateExchangingKeys#91d77a65
//	case *tdapi.CallStateReady: // callStateReady#dfc6b953
//	case *tdapi.CallStateHangingUp: // callStateHangingUp#80d0f2aa
//	case *tdapi.CallStateDiscarded: // callStateDiscarded#531b7c45
//	case *tdapi.CallStateError: // callStateError#c5df6495
//	default: panic(v)
//	}
type CallStateClass interface {
	bin.Encoder
	bin.Decoder
	bin.BareEncoder
	bin.BareDecoder
	construct() CallStateClass

	// TypeID returns type id in TL schema.
	//
	// See https://core.telegram.org/mtproto/TL-tl#remarks.
	TypeID() uint32
	// TypeName returns name of type in TL schema.
	TypeName() string
	// String implements fmt.Stringer.
	String() string
	// Zero returns true if current object has a zero value.
	Zero() bool

	EncodeTDLibJSON(b tdjson.Encoder) error
	DecodeTDLibJSON(b tdjson.Decoder) error
}

// DecodeCallState implements binary de-serialization for CallStateClass.
func DecodeCallState(buf *bin.Buffer) (CallStateClass, error) {
	id, err := buf.PeekID()
	if err != nil {
		return nil, err
	}
	switch id {
	case CallStatePendingTypeID:
		// Decoding callStatePending#3ff56c2c.
		v := CallStatePending{}
		if err := v.Decode(buf); err != nil {
			return nil, fmt.Errorf("unable to decode CallStateClass: %w", err)
		}
		return &v, nil
	case CallStateExchangingKeysTypeID:
		// Decoding callStateExchangingKeys#91d77a65.
		v := CallStateExchangingKeys{}
		if err := v.Decode(buf); err != nil {
			return nil, fmt.Errorf("unable to decode CallStateClass: %w", err)
		}
		return &v, nil
	case CallStateReadyTypeID:
		// Decoding callStateReady#dfc6b953.
		v := CallStateReady{}
		if err := v.Decode(buf); err != nil {
			return nil, fmt.Errorf("unable to decode CallStateClass: %w", err)
		}
		return &v, nil
	case CallStateHangingUpTypeID:
		// Decoding callStateHangingUp#80d0f2aa.
		v := CallStateHangingUp{}
		if err := v.Decode(buf); err != nil {
			return nil, fmt.Errorf("unable to decode CallStateClass: %w", err)
		}
		return &v, nil
	case CallStateDiscardedTypeID:
		// Decoding callStateDiscarded#531b7c45.
		v := CallStateDiscarded{}
		if err := v.Decode(buf); err != nil {
			return nil, fmt.Errorf("unable to decode CallStateClass: %w", err)
		}
		return &v, nil
	case CallStateErrorTypeID:
		// Decoding callStateError#c5df6495.
		v := CallStateError{}
		if err := v.Decode(buf); err != nil {
			return nil, fmt.Errorf("unable to decode CallStateClass: %w", err)
		}
		return &v, nil
	default:
		return nil, fmt.Errorf("unable to decode CallStateClass: %w", bin.NewUnexpectedID(id))
	}
}

// DecodeTDLibJSONCallState implements binary de-serialization for CallStateClass.
func DecodeTDLibJSONCallState(buf tdjson.Decoder) (CallStateClass, error) {
	id, err := buf.FindTypeID()
	if err != nil {
		return nil, err
	}
	switch id {
	case "callStatePending":
		// Decoding callStatePending#3ff56c2c.
		v := CallStatePending{}
		if err := v.DecodeTDLibJSON(buf); err != nil {
			return nil, fmt.Errorf("unable to decode CallStateClass: %w", err)
		}
		return &v, nil
	case "callStateExchangingKeys":
		// Decoding callStateExchangingKeys#91d77a65.
		v := CallStateExchangingKeys{}
		if err := v.DecodeTDLibJSON(buf); err != nil {
			return nil, fmt.Errorf("unable to decode CallStateClass: %w", err)
		}
		return &v, nil
	case "callStateReady":
		// Decoding callStateReady#dfc6b953.
		v := CallStateReady{}
		if err := v.DecodeTDLibJSON(buf); err != nil {
			return nil, fmt.Errorf("unable to decode CallStateClass: %w", err)
		}
		return &v, nil
	case "callStateHangingUp":
		// Decoding callStateHangingUp#80d0f2aa.
		v := CallStateHangingUp{}
		if err := v.DecodeTDLibJSON(buf); err != nil {
			return nil, fmt.Errorf("unable to decode CallStateClass: %w", err)
		}
		return &v, nil
	case "callStateDiscarded":
		// Decoding callStateDiscarded#531b7c45.
		v := CallStateDiscarded{}
		if err := v.DecodeTDLibJSON(buf); err != nil {
			return nil, fmt.Errorf("unable to decode CallStateClass: %w", err)
		}
		return &v, nil
	case "callStateError":
		// Decoding callStateError#c5df6495.
		v := CallStateError{}
		if err := v.DecodeTDLibJSON(buf); err != nil {
			return nil, fmt.Errorf("unable to decode CallStateClass: %w", err)
		}
		return &v, nil
	default:
		return nil, fmt.Errorf("unable to decode CallStateClass: %w", tdjson.NewUnexpectedID(id))
	}
}

// CallState boxes the CallStateClass providing a helper.
type CallStateBox struct {
	CallState CallStateClass
}

// Decode implements bin.Decoder for CallStateBox.
func (b *CallStateBox) Decode(buf *bin.Buffer) error {
	if b == nil {
		return fmt.Errorf("unable to decode CallStateBox to nil")
	}
	v, err := DecodeCallState(buf)
	if err != nil {
		return fmt.Errorf("unable to decode boxed value: %w", err)
	}
	b.CallState = v
	return nil
}

// Encode implements bin.Encode for CallStateBox.
func (b *CallStateBox) Encode(buf *bin.Buffer) error {
	if b == nil || b.CallState == nil {
		return fmt.Errorf("unable to encode CallStateClass as nil")
	}
	return b.CallState.Encode(buf)
}

// DecodeTDLibJSON implements bin.Decoder for CallStateBox.
func (b *CallStateBox) DecodeTDLibJSON(buf tdjson.Decoder) error {
	if b == nil {
		return fmt.Errorf("unable to decode CallStateBox to nil")
	}
	v, err := DecodeTDLibJSONCallState(buf)
	if err != nil {
		return fmt.Errorf("unable to decode boxed value: %w", err)
	}
	b.CallState = v
	return nil
}

// EncodeTDLibJSON implements bin.Encode for CallStateBox.
func (b *CallStateBox) EncodeTDLibJSON(buf tdjson.Encoder) error {
	if b == nil || b.CallState == nil {
		return fmt.Errorf("unable to encode CallStateClass as nil")
	}
	return b.CallState.EncodeTDLibJSON(buf)
}
