// Code generated by gotdgen, DO NOT EDIT.

package tg

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{}
)

// PaymentsPaymentForm represents TL type `payments.paymentForm#a0058751`.
// Payment form
//
// See https://core.telegram.org/constructor/payments.paymentForm for reference.
type PaymentsPaymentForm struct {
	// Flags, see TL conditional fields¹
	//
	// Links:
	//  1) https://core.telegram.org/mtproto/TL-combinators#conditional-fields
	Flags bin.Fields
	// Whether the user can choose to save credentials.
	CanSaveCredentials bool
	// Indicates that the user can save payment credentials, but only after setting up a 2FA
	// password¹ (currently the account doesn't have a 2FA password²)
	//
	// Links:
	//  1) https://core.telegram.org/api/srp
	//  2) https://core.telegram.org/api/srp
	PasswordMissing bool
	// Form ID
	FormID int64
	// Bot ID
	BotID int64
	// Form title
	Title string
	// Description
	Description string
	// Product photo
	//
	// Use SetPhoto and GetPhoto helpers.
	Photo WebDocumentClass
	// Invoice
	Invoice Invoice
	// Payment provider ID.
	ProviderID int64
	// Payment form URL
	URL string
	// Payment provider name.One of the following:- stripe
	//
	// Use SetNativeProvider and GetNativeProvider helpers.
	NativeProvider string
	// Contains information about the payment provider, if available, to support it natively
	// without the need for opening the URL.A JSON object that can contain the following
	// fields:- apple_pay_merchant_id: Apple Pay merchant ID- google_pay_public_key: Google
	// Pay public key- need_country: True, if the user country must be provided,- need_zip:
	// True, if the user ZIP/postal code must be provided,- need_cardholder_name: True, if
	// the cardholder name must be provided
	//
	// Use SetNativeParams and GetNativeParams helpers.
	NativeParams DataJSON
	// Additional payment methods
	//
	// Use SetAdditionalMethods and GetAdditionalMethods helpers.
	AdditionalMethods []PaymentFormMethod
	// Saved server-side order information
	//
	// Use SetSavedInfo and GetSavedInfo helpers.
	SavedInfo PaymentRequestedInfo
	// Contains information about saved card credentials
	//
	// Use SetSavedCredentials and GetSavedCredentials helpers.
	SavedCredentials []PaymentSavedCredentialsCard
	// Users
	Users []UserClass
}

// PaymentsPaymentFormTypeID is TL type id of PaymentsPaymentForm.
const PaymentsPaymentFormTypeID = 0xa0058751

// construct implements constructor of PaymentsPaymentFormClass.
func (p PaymentsPaymentForm) construct() PaymentsPaymentFormClass { return &p }

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

	_ PaymentsPaymentFormClass = &PaymentsPaymentForm{}
)

func (p *PaymentsPaymentForm) Zero() bool {
	if p == nil {
		return true
	}
	if !(p.Flags.Zero()) {
		return false
	}
	if !(p.CanSaveCredentials == false) {
		return false
	}
	if !(p.PasswordMissing == false) {
		return false
	}
	if !(p.FormID == 0) {
		return false
	}
	if !(p.BotID == 0) {
		return false
	}
	if !(p.Title == "") {
		return false
	}
	if !(p.Description == "") {
		return false
	}
	if !(p.Photo == nil) {
		return false
	}
	if !(p.Invoice.Zero()) {
		return false
	}
	if !(p.ProviderID == 0) {
		return false
	}
	if !(p.URL == "") {
		return false
	}
	if !(p.NativeProvider == "") {
		return false
	}
	if !(p.NativeParams.Zero()) {
		return false
	}
	if !(p.AdditionalMethods == nil) {
		return false
	}
	if !(p.SavedInfo.Zero()) {
		return false
	}
	if !(p.SavedCredentials == nil) {
		return false
	}
	if !(p.Users == nil) {
		return false
	}

	return true
}

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

// FillFrom fills PaymentsPaymentForm from given interface.
func (p *PaymentsPaymentForm) FillFrom(from interface {
	GetCanSaveCredentials() (value bool)
	GetPasswordMissing() (value bool)
	GetFormID() (value int64)
	GetBotID() (value int64)
	GetTitle() (value string)
	GetDescription() (value string)
	GetPhoto() (value WebDocumentClass, ok bool)
	GetInvoice() (value Invoice)
	GetProviderID() (value int64)
	GetURL() (value string)
	GetNativeProvider() (value string, ok bool)
	GetNativeParams() (value DataJSON, ok bool)
	GetAdditionalMethods() (value []PaymentFormMethod, ok bool)
	GetSavedInfo() (value PaymentRequestedInfo, ok bool)
	GetSavedCredentials() (value []PaymentSavedCredentialsCard, ok bool)
	GetUsers() (value []UserClass)
}) {
	p.CanSaveCredentials = from.GetCanSaveCredentials()
	p.PasswordMissing = from.GetPasswordMissing()
	p.FormID = from.GetFormID()
	p.BotID = from.GetBotID()
	p.Title = from.GetTitle()
	p.Description = from.GetDescription()
	if val, ok := from.GetPhoto(); ok {
		p.Photo = val
	}

	p.Invoice = from.GetInvoice()
	p.ProviderID = from.GetProviderID()
	p.URL = from.GetURL()
	if val, ok := from.GetNativeProvider(); ok {
		p.NativeProvider = val
	}

	if val, ok := from.GetNativeParams(); ok {
		p.NativeParams = val
	}

	if val, ok := from.GetAdditionalMethods(); ok {
		p.AdditionalMethods = val
	}

	if val, ok := from.GetSavedInfo(); ok {
		p.SavedInfo = val
	}

	if val, ok := from.GetSavedCredentials(); ok {
		p.SavedCredentials = val
	}

	p.Users = from.GetUsers()
}

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

// TypeName returns name of type in TL schema.
func (*PaymentsPaymentForm) TypeName() string {
	return "payments.paymentForm"
}

// TypeInfo returns info about TL type.
func (p *PaymentsPaymentForm) TypeInfo() tdp.Type {
	typ := tdp.Type{
		Name: "payments.paymentForm",
		ID:   PaymentsPaymentFormTypeID,
	}
	if p == nil {
		typ.Null = true
		return typ
	}
	typ.Fields = []tdp.Field{
		{
			Name:       "CanSaveCredentials",
			SchemaName: "can_save_credentials",
			Null:       !p.Flags.Has(2),
		},
		{
			Name:       "PasswordMissing",
			SchemaName: "password_missing",
			Null:       !p.Flags.Has(3),
		},
		{
			Name:       "FormID",
			SchemaName: "form_id",
		},
		{
			Name:       "BotID",
			SchemaName: "bot_id",
		},
		{
			Name:       "Title",
			SchemaName: "title",
		},
		{
			Name:       "Description",
			SchemaName: "description",
		},
		{
			Name:       "Photo",
			SchemaName: "photo",
			Null:       !p.Flags.Has(5),
		},
		{
			Name:       "Invoice",
			SchemaName: "invoice",
		},
		{
			Name:       "ProviderID",
			SchemaName: "provider_id",
		},
		{
			Name:       "URL",
			SchemaName: "url",
		},
		{
			Name:       "NativeProvider",
			SchemaName: "native_provider",
			Null:       !p.Flags.Has(4),
		},
		{
			Name:       "NativeParams",
			SchemaName: "native_params",
			Null:       !p.Flags.Has(4),
		},
		{
			Name:       "AdditionalMethods",
			SchemaName: "additional_methods",
			Null:       !p.Flags.Has(6),
		},
		{
			Name:       "SavedInfo",
			SchemaName: "saved_info",
			Null:       !p.Flags.Has(0),
		},
		{
			Name:       "SavedCredentials",
			SchemaName: "saved_credentials",
			Null:       !p.Flags.Has(1),
		},
		{
			Name:       "Users",
			SchemaName: "users",
		},
	}
	return typ
}

// SetFlags sets flags for non-zero fields.
func (p *PaymentsPaymentForm) SetFlags() {
	if !(p.CanSaveCredentials == false) {
		p.Flags.Set(2)
	}
	if !(p.PasswordMissing == false) {
		p.Flags.Set(3)
	}
	if !(p.Photo == nil) {
		p.Flags.Set(5)
	}
	if !(p.NativeProvider == "") {
		p.Flags.Set(4)
	}
	if !(p.NativeParams.Zero()) {
		p.Flags.Set(4)
	}
	if !(p.AdditionalMethods == nil) {
		p.Flags.Set(6)
	}
	if !(p.SavedInfo.Zero()) {
		p.Flags.Set(0)
	}
	if !(p.SavedCredentials == nil) {
		p.Flags.Set(1)
	}
}

// Encode implements bin.Encoder.
func (p *PaymentsPaymentForm) Encode(b *bin.Buffer) error {
	if p == nil {
		return fmt.Errorf("can't encode payments.paymentForm#a0058751 as nil")
	}
	b.PutID(PaymentsPaymentFormTypeID)
	return p.EncodeBare(b)
}

// EncodeBare implements bin.BareEncoder.
func (p *PaymentsPaymentForm) EncodeBare(b *bin.Buffer) error {
	if p == nil {
		return fmt.Errorf("can't encode payments.paymentForm#a0058751 as nil")
	}
	p.SetFlags()
	if err := p.Flags.Encode(b); err != nil {
		return fmt.Errorf("unable to encode payments.paymentForm#a0058751: field flags: %w", err)
	}
	b.PutLong(p.FormID)
	b.PutLong(p.BotID)
	b.PutString(p.Title)
	b.PutString(p.Description)
	if p.Flags.Has(5) {
		if p.Photo == nil {
			return fmt.Errorf("unable to encode payments.paymentForm#a0058751: field photo is nil")
		}
		if err := p.Photo.Encode(b); err != nil {
			return fmt.Errorf("unable to encode payments.paymentForm#a0058751: field photo: %w", err)
		}
	}
	if err := p.Invoice.Encode(b); err != nil {
		return fmt.Errorf("unable to encode payments.paymentForm#a0058751: field invoice: %w", err)
	}
	b.PutLong(p.ProviderID)
	b.PutString(p.URL)
	if p.Flags.Has(4) {
		b.PutString(p.NativeProvider)
	}
	if p.Flags.Has(4) {
		if err := p.NativeParams.Encode(b); err != nil {
			return fmt.Errorf("unable to encode payments.paymentForm#a0058751: field native_params: %w", err)
		}
	}
	if p.Flags.Has(6) {
		b.PutVectorHeader(len(p.AdditionalMethods))
		for idx, v := range p.AdditionalMethods {
			if err := v.Encode(b); err != nil {
				return fmt.Errorf("unable to encode payments.paymentForm#a0058751: field additional_methods element with index %d: %w", idx, err)
			}
		}
	}
	if p.Flags.Has(0) {
		if err := p.SavedInfo.Encode(b); err != nil {
			return fmt.Errorf("unable to encode payments.paymentForm#a0058751: field saved_info: %w", err)
		}
	}
	if p.Flags.Has(1) {
		b.PutVectorHeader(len(p.SavedCredentials))
		for idx, v := range p.SavedCredentials {
			if err := v.Encode(b); err != nil {
				return fmt.Errorf("unable to encode payments.paymentForm#a0058751: field saved_credentials element with index %d: %w", idx, err)
			}
		}
	}
	b.PutVectorHeader(len(p.Users))
	for idx, v := range p.Users {
		if v == nil {
			return fmt.Errorf("unable to encode payments.paymentForm#a0058751: field users element with index %d is nil", idx)
		}
		if err := v.Encode(b); err != nil {
			return fmt.Errorf("unable to encode payments.paymentForm#a0058751: field users element with index %d: %w", idx, err)
		}
	}
	return nil
}

// Decode implements bin.Decoder.
func (p *PaymentsPaymentForm) Decode(b *bin.Buffer) error {
	if p == nil {
		return fmt.Errorf("can't decode payments.paymentForm#a0058751 to nil")
	}
	if err := b.ConsumeID(PaymentsPaymentFormTypeID); err != nil {
		return fmt.Errorf("unable to decode payments.paymentForm#a0058751: %w", err)
	}
	return p.DecodeBare(b)
}

// DecodeBare implements bin.BareDecoder.
func (p *PaymentsPaymentForm) DecodeBare(b *bin.Buffer) error {
	if p == nil {
		return fmt.Errorf("can't decode payments.paymentForm#a0058751 to nil")
	}
	{
		if err := p.Flags.Decode(b); err != nil {
			return fmt.Errorf("unable to decode payments.paymentForm#a0058751: field flags: %w", err)
		}
	}
	p.CanSaveCredentials = p.Flags.Has(2)
	p.PasswordMissing = p.Flags.Has(3)
	{
		value, err := b.Long()
		if err != nil {
			return fmt.Errorf("unable to decode payments.paymentForm#a0058751: field form_id: %w", err)
		}
		p.FormID = value
	}
	{
		value, err := b.Long()
		if err != nil {
			return fmt.Errorf("unable to decode payments.paymentForm#a0058751: field bot_id: %w", err)
		}
		p.BotID = value
	}
	{
		value, err := b.String()
		if err != nil {
			return fmt.Errorf("unable to decode payments.paymentForm#a0058751: field title: %w", err)
		}
		p.Title = value
	}
	{
		value, err := b.String()
		if err != nil {
			return fmt.Errorf("unable to decode payments.paymentForm#a0058751: field description: %w", err)
		}
		p.Description = value
	}
	if p.Flags.Has(5) {
		value, err := DecodeWebDocument(b)
		if err != nil {
			return fmt.Errorf("unable to decode payments.paymentForm#a0058751: field photo: %w", err)
		}
		p.Photo = value
	}
	{
		if err := p.Invoice.Decode(b); err != nil {
			return fmt.Errorf("unable to decode payments.paymentForm#a0058751: field invoice: %w", err)
		}
	}
	{
		value, err := b.Long()
		if err != nil {
			return fmt.Errorf("unable to decode payments.paymentForm#a0058751: field provider_id: %w", err)
		}
		p.ProviderID = value
	}
	{
		value, err := b.String()
		if err != nil {
			return fmt.Errorf("unable to decode payments.paymentForm#a0058751: field url: %w", err)
		}
		p.URL = value
	}
	if p.Flags.Has(4) {
		value, err := b.String()
		if err != nil {
			return fmt.Errorf("unable to decode payments.paymentForm#a0058751: field native_provider: %w", err)
		}
		p.NativeProvider = value
	}
	if p.Flags.Has(4) {
		if err := p.NativeParams.Decode(b); err != nil {
			return fmt.Errorf("unable to decode payments.paymentForm#a0058751: field native_params: %w", err)
		}
	}
	if p.Flags.Has(6) {
		headerLen, err := b.VectorHeader()
		if err != nil {
			return fmt.Errorf("unable to decode payments.paymentForm#a0058751: field additional_methods: %w", err)
		}

		if headerLen > 0 {
			p.AdditionalMethods = make([]PaymentFormMethod, 0, headerLen%bin.PreallocateLimit)
		}
		for idx := 0; idx < headerLen; idx++ {
			var value PaymentFormMethod
			if err := value.Decode(b); err != nil {
				return fmt.Errorf("unable to decode payments.paymentForm#a0058751: field additional_methods: %w", err)
			}
			p.AdditionalMethods = append(p.AdditionalMethods, value)
		}
	}
	if p.Flags.Has(0) {
		if err := p.SavedInfo.Decode(b); err != nil {
			return fmt.Errorf("unable to decode payments.paymentForm#a0058751: field saved_info: %w", err)
		}
	}
	if p.Flags.Has(1) {
		headerLen, err := b.VectorHeader()
		if err != nil {
			return fmt.Errorf("unable to decode payments.paymentForm#a0058751: field saved_credentials: %w", err)
		}

		if headerLen > 0 {
			p.SavedCredentials = make([]PaymentSavedCredentialsCard, 0, headerLen%bin.PreallocateLimit)
		}
		for idx := 0; idx < headerLen; idx++ {
			var value PaymentSavedCredentialsCard
			if err := value.Decode(b); err != nil {
				return fmt.Errorf("unable to decode payments.paymentForm#a0058751: field saved_credentials: %w", err)
			}
			p.SavedCredentials = append(p.SavedCredentials, value)
		}
	}
	{
		headerLen, err := b.VectorHeader()
		if err != nil {
			return fmt.Errorf("unable to decode payments.paymentForm#a0058751: field users: %w", err)
		}

		if headerLen > 0 {
			p.Users = make([]UserClass, 0, headerLen%bin.PreallocateLimit)
		}
		for idx := 0; idx < headerLen; idx++ {
			value, err := DecodeUser(b)
			if err != nil {
				return fmt.Errorf("unable to decode payments.paymentForm#a0058751: field users: %w", err)
			}
			p.Users = append(p.Users, value)
		}
	}
	return nil
}

// SetCanSaveCredentials sets value of CanSaveCredentials conditional field.
func (p *PaymentsPaymentForm) SetCanSaveCredentials(value bool) {
	if value {
		p.Flags.Set(2)
		p.CanSaveCredentials = true
	} else {
		p.Flags.Unset(2)
		p.CanSaveCredentials = false
	}
}

// GetCanSaveCredentials returns value of CanSaveCredentials conditional field.
func (p *PaymentsPaymentForm) GetCanSaveCredentials() (value bool) {
	if p == nil {
		return
	}
	return p.Flags.Has(2)
}

// SetPasswordMissing sets value of PasswordMissing conditional field.
func (p *PaymentsPaymentForm) SetPasswordMissing(value bool) {
	if value {
		p.Flags.Set(3)
		p.PasswordMissing = true
	} else {
		p.Flags.Unset(3)
		p.PasswordMissing = false
	}
}

// GetPasswordMissing returns value of PasswordMissing conditional field.
func (p *PaymentsPaymentForm) GetPasswordMissing() (value bool) {
	if p == nil {
		return
	}
	return p.Flags.Has(3)
}

// GetFormID returns value of FormID field.
func (p *PaymentsPaymentForm) GetFormID() (value int64) {
	if p == nil {
		return
	}
	return p.FormID
}

// GetBotID returns value of BotID field.
func (p *PaymentsPaymentForm) GetBotID() (value int64) {
	if p == nil {
		return
	}
	return p.BotID
}

// GetTitle returns value of Title field.
func (p *PaymentsPaymentForm) GetTitle() (value string) {
	if p == nil {
		return
	}
	return p.Title
}

// GetDescription returns value of Description field.
func (p *PaymentsPaymentForm) GetDescription() (value string) {
	if p == nil {
		return
	}
	return p.Description
}

// SetPhoto sets value of Photo conditional field.
func (p *PaymentsPaymentForm) SetPhoto(value WebDocumentClass) {
	p.Flags.Set(5)
	p.Photo = value
}

// GetPhoto returns value of Photo conditional field and
// boolean which is true if field was set.
func (p *PaymentsPaymentForm) GetPhoto() (value WebDocumentClass, ok bool) {
	if p == nil {
		return
	}
	if !p.Flags.Has(5) {
		return value, false
	}
	return p.Photo, true
}

// GetInvoice returns value of Invoice field.
func (p *PaymentsPaymentForm) GetInvoice() (value Invoice) {
	if p == nil {
		return
	}
	return p.Invoice
}

// GetProviderID returns value of ProviderID field.
func (p *PaymentsPaymentForm) GetProviderID() (value int64) {
	if p == nil {
		return
	}
	return p.ProviderID
}

// GetURL returns value of URL field.
func (p *PaymentsPaymentForm) GetURL() (value string) {
	if p == nil {
		return
	}
	return p.URL
}

// SetNativeProvider sets value of NativeProvider conditional field.
func (p *PaymentsPaymentForm) SetNativeProvider(value string) {
	p.Flags.Set(4)
	p.NativeProvider = value
}

// GetNativeProvider returns value of NativeProvider conditional field and
// boolean which is true if field was set.
func (p *PaymentsPaymentForm) GetNativeProvider() (value string, ok bool) {
	if p == nil {
		return
	}
	if !p.Flags.Has(4) {
		return value, false
	}
	return p.NativeProvider, true
}

// SetNativeParams sets value of NativeParams conditional field.
func (p *PaymentsPaymentForm) SetNativeParams(value DataJSON) {
	p.Flags.Set(4)
	p.NativeParams = value
}

// GetNativeParams returns value of NativeParams conditional field and
// boolean which is true if field was set.
func (p *PaymentsPaymentForm) GetNativeParams() (value DataJSON, ok bool) {
	if p == nil {
		return
	}
	if !p.Flags.Has(4) {
		return value, false
	}
	return p.NativeParams, true
}

// SetAdditionalMethods sets value of AdditionalMethods conditional field.
func (p *PaymentsPaymentForm) SetAdditionalMethods(value []PaymentFormMethod) {
	p.Flags.Set(6)
	p.AdditionalMethods = value
}

// GetAdditionalMethods returns value of AdditionalMethods conditional field and
// boolean which is true if field was set.
func (p *PaymentsPaymentForm) GetAdditionalMethods() (value []PaymentFormMethod, ok bool) {
	if p == nil {
		return
	}
	if !p.Flags.Has(6) {
		return value, false
	}
	return p.AdditionalMethods, true
}

// SetSavedInfo sets value of SavedInfo conditional field.
func (p *PaymentsPaymentForm) SetSavedInfo(value PaymentRequestedInfo) {
	p.Flags.Set(0)
	p.SavedInfo = value
}

// GetSavedInfo returns value of SavedInfo conditional field and
// boolean which is true if field was set.
func (p *PaymentsPaymentForm) GetSavedInfo() (value PaymentRequestedInfo, ok bool) {
	if p == nil {
		return
	}
	if !p.Flags.Has(0) {
		return value, false
	}
	return p.SavedInfo, true
}

// SetSavedCredentials sets value of SavedCredentials conditional field.
func (p *PaymentsPaymentForm) SetSavedCredentials(value []PaymentSavedCredentialsCard) {
	p.Flags.Set(1)
	p.SavedCredentials = value
}

// GetSavedCredentials returns value of SavedCredentials conditional field and
// boolean which is true if field was set.
func (p *PaymentsPaymentForm) GetSavedCredentials() (value []PaymentSavedCredentialsCard, ok bool) {
	if p == nil {
		return
	}
	if !p.Flags.Has(1) {
		return value, false
	}
	return p.SavedCredentials, true
}

// GetUsers returns value of Users field.
func (p *PaymentsPaymentForm) GetUsers() (value []UserClass) {
	if p == nil {
		return
	}
	return p.Users
}

// MapUsers returns field Users wrapped in UserClassArray helper.
func (p *PaymentsPaymentForm) MapUsers() (value UserClassArray) {
	return UserClassArray(p.Users)
}

// PaymentsPaymentFormStars represents TL type `payments.paymentFormStars#7bf6b15c`.
// Represents a payment form, for payments to be using Telegram Stars, see here »¹ for
// more info.
//
// Links:
//  1. https://core.telegram.org/api/stars
//
// See https://core.telegram.org/constructor/payments.paymentFormStars for reference.
type PaymentsPaymentFormStars struct {
	// Flags, see TL conditional fields¹
	//
	// Links:
	//  1) https://core.telegram.org/mtproto/TL-combinators#conditional-fields
	Flags bin.Fields
	// Form ID.
	FormID int64
	// Bot ID.
	BotID int64
	// Form title
	Title string
	// Description
	Description string
	// Product photo
	//
	// Use SetPhoto and GetPhoto helpers.
	Photo WebDocumentClass
	// Invoice
	Invoice Invoice
	// Info about users mentioned in the other fields.
	Users []UserClass
}

// PaymentsPaymentFormStarsTypeID is TL type id of PaymentsPaymentFormStars.
const PaymentsPaymentFormStarsTypeID = 0x7bf6b15c

// construct implements constructor of PaymentsPaymentFormClass.
func (p PaymentsPaymentFormStars) construct() PaymentsPaymentFormClass { return &p }

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

	_ PaymentsPaymentFormClass = &PaymentsPaymentFormStars{}
)

func (p *PaymentsPaymentFormStars) Zero() bool {
	if p == nil {
		return true
	}
	if !(p.Flags.Zero()) {
		return false
	}
	if !(p.FormID == 0) {
		return false
	}
	if !(p.BotID == 0) {
		return false
	}
	if !(p.Title == "") {
		return false
	}
	if !(p.Description == "") {
		return false
	}
	if !(p.Photo == nil) {
		return false
	}
	if !(p.Invoice.Zero()) {
		return false
	}
	if !(p.Users == nil) {
		return false
	}

	return true
}

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

// FillFrom fills PaymentsPaymentFormStars from given interface.
func (p *PaymentsPaymentFormStars) FillFrom(from interface {
	GetFormID() (value int64)
	GetBotID() (value int64)
	GetTitle() (value string)
	GetDescription() (value string)
	GetPhoto() (value WebDocumentClass, ok bool)
	GetInvoice() (value Invoice)
	GetUsers() (value []UserClass)
}) {
	p.FormID = from.GetFormID()
	p.BotID = from.GetBotID()
	p.Title = from.GetTitle()
	p.Description = from.GetDescription()
	if val, ok := from.GetPhoto(); ok {
		p.Photo = val
	}

	p.Invoice = from.GetInvoice()
	p.Users = from.GetUsers()
}

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

// TypeName returns name of type in TL schema.
func (*PaymentsPaymentFormStars) TypeName() string {
	return "payments.paymentFormStars"
}

// TypeInfo returns info about TL type.
func (p *PaymentsPaymentFormStars) TypeInfo() tdp.Type {
	typ := tdp.Type{
		Name: "payments.paymentFormStars",
		ID:   PaymentsPaymentFormStarsTypeID,
	}
	if p == nil {
		typ.Null = true
		return typ
	}
	typ.Fields = []tdp.Field{
		{
			Name:       "FormID",
			SchemaName: "form_id",
		},
		{
			Name:       "BotID",
			SchemaName: "bot_id",
		},
		{
			Name:       "Title",
			SchemaName: "title",
		},
		{
			Name:       "Description",
			SchemaName: "description",
		},
		{
			Name:       "Photo",
			SchemaName: "photo",
			Null:       !p.Flags.Has(5),
		},
		{
			Name:       "Invoice",
			SchemaName: "invoice",
		},
		{
			Name:       "Users",
			SchemaName: "users",
		},
	}
	return typ
}

// SetFlags sets flags for non-zero fields.
func (p *PaymentsPaymentFormStars) SetFlags() {
	if !(p.Photo == nil) {
		p.Flags.Set(5)
	}
}

// Encode implements bin.Encoder.
func (p *PaymentsPaymentFormStars) Encode(b *bin.Buffer) error {
	if p == nil {
		return fmt.Errorf("can't encode payments.paymentFormStars#7bf6b15c as nil")
	}
	b.PutID(PaymentsPaymentFormStarsTypeID)
	return p.EncodeBare(b)
}

// EncodeBare implements bin.BareEncoder.
func (p *PaymentsPaymentFormStars) EncodeBare(b *bin.Buffer) error {
	if p == nil {
		return fmt.Errorf("can't encode payments.paymentFormStars#7bf6b15c as nil")
	}
	p.SetFlags()
	if err := p.Flags.Encode(b); err != nil {
		return fmt.Errorf("unable to encode payments.paymentFormStars#7bf6b15c: field flags: %w", err)
	}
	b.PutLong(p.FormID)
	b.PutLong(p.BotID)
	b.PutString(p.Title)
	b.PutString(p.Description)
	if p.Flags.Has(5) {
		if p.Photo == nil {
			return fmt.Errorf("unable to encode payments.paymentFormStars#7bf6b15c: field photo is nil")
		}
		if err := p.Photo.Encode(b); err != nil {
			return fmt.Errorf("unable to encode payments.paymentFormStars#7bf6b15c: field photo: %w", err)
		}
	}
	if err := p.Invoice.Encode(b); err != nil {
		return fmt.Errorf("unable to encode payments.paymentFormStars#7bf6b15c: field invoice: %w", err)
	}
	b.PutVectorHeader(len(p.Users))
	for idx, v := range p.Users {
		if v == nil {
			return fmt.Errorf("unable to encode payments.paymentFormStars#7bf6b15c: field users element with index %d is nil", idx)
		}
		if err := v.Encode(b); err != nil {
			return fmt.Errorf("unable to encode payments.paymentFormStars#7bf6b15c: field users element with index %d: %w", idx, err)
		}
	}
	return nil
}

// Decode implements bin.Decoder.
func (p *PaymentsPaymentFormStars) Decode(b *bin.Buffer) error {
	if p == nil {
		return fmt.Errorf("can't decode payments.paymentFormStars#7bf6b15c to nil")
	}
	if err := b.ConsumeID(PaymentsPaymentFormStarsTypeID); err != nil {
		return fmt.Errorf("unable to decode payments.paymentFormStars#7bf6b15c: %w", err)
	}
	return p.DecodeBare(b)
}

// DecodeBare implements bin.BareDecoder.
func (p *PaymentsPaymentFormStars) DecodeBare(b *bin.Buffer) error {
	if p == nil {
		return fmt.Errorf("can't decode payments.paymentFormStars#7bf6b15c to nil")
	}
	{
		if err := p.Flags.Decode(b); err != nil {
			return fmt.Errorf("unable to decode payments.paymentFormStars#7bf6b15c: field flags: %w", err)
		}
	}
	{
		value, err := b.Long()
		if err != nil {
			return fmt.Errorf("unable to decode payments.paymentFormStars#7bf6b15c: field form_id: %w", err)
		}
		p.FormID = value
	}
	{
		value, err := b.Long()
		if err != nil {
			return fmt.Errorf("unable to decode payments.paymentFormStars#7bf6b15c: field bot_id: %w", err)
		}
		p.BotID = value
	}
	{
		value, err := b.String()
		if err != nil {
			return fmt.Errorf("unable to decode payments.paymentFormStars#7bf6b15c: field title: %w", err)
		}
		p.Title = value
	}
	{
		value, err := b.String()
		if err != nil {
			return fmt.Errorf("unable to decode payments.paymentFormStars#7bf6b15c: field description: %w", err)
		}
		p.Description = value
	}
	if p.Flags.Has(5) {
		value, err := DecodeWebDocument(b)
		if err != nil {
			return fmt.Errorf("unable to decode payments.paymentFormStars#7bf6b15c: field photo: %w", err)
		}
		p.Photo = value
	}
	{
		if err := p.Invoice.Decode(b); err != nil {
			return fmt.Errorf("unable to decode payments.paymentFormStars#7bf6b15c: field invoice: %w", err)
		}
	}
	{
		headerLen, err := b.VectorHeader()
		if err != nil {
			return fmt.Errorf("unable to decode payments.paymentFormStars#7bf6b15c: field users: %w", err)
		}

		if headerLen > 0 {
			p.Users = make([]UserClass, 0, headerLen%bin.PreallocateLimit)
		}
		for idx := 0; idx < headerLen; idx++ {
			value, err := DecodeUser(b)
			if err != nil {
				return fmt.Errorf("unable to decode payments.paymentFormStars#7bf6b15c: field users: %w", err)
			}
			p.Users = append(p.Users, value)
		}
	}
	return nil
}

// GetFormID returns value of FormID field.
func (p *PaymentsPaymentFormStars) GetFormID() (value int64) {
	if p == nil {
		return
	}
	return p.FormID
}

// GetBotID returns value of BotID field.
func (p *PaymentsPaymentFormStars) GetBotID() (value int64) {
	if p == nil {
		return
	}
	return p.BotID
}

// GetTitle returns value of Title field.
func (p *PaymentsPaymentFormStars) GetTitle() (value string) {
	if p == nil {
		return
	}
	return p.Title
}

// GetDescription returns value of Description field.
func (p *PaymentsPaymentFormStars) GetDescription() (value string) {
	if p == nil {
		return
	}
	return p.Description
}

// SetPhoto sets value of Photo conditional field.
func (p *PaymentsPaymentFormStars) SetPhoto(value WebDocumentClass) {
	p.Flags.Set(5)
	p.Photo = value
}

// GetPhoto returns value of Photo conditional field and
// boolean which is true if field was set.
func (p *PaymentsPaymentFormStars) GetPhoto() (value WebDocumentClass, ok bool) {
	if p == nil {
		return
	}
	if !p.Flags.Has(5) {
		return value, false
	}
	return p.Photo, true
}

// GetInvoice returns value of Invoice field.
func (p *PaymentsPaymentFormStars) GetInvoice() (value Invoice) {
	if p == nil {
		return
	}
	return p.Invoice
}

// GetUsers returns value of Users field.
func (p *PaymentsPaymentFormStars) GetUsers() (value []UserClass) {
	if p == nil {
		return
	}
	return p.Users
}

// MapUsers returns field Users wrapped in UserClassArray helper.
func (p *PaymentsPaymentFormStars) MapUsers() (value UserClassArray) {
	return UserClassArray(p.Users)
}

// PaymentsPaymentFormStarGift represents TL type `payments.paymentFormStarGift#b425cfe1`.
// Represents a payment form for a gift, see here »¹ for more info.
//
// Links:
//  1. https://core.telegram.org/api/gifts
//
// See https://core.telegram.org/constructor/payments.paymentFormStarGift for reference.
type PaymentsPaymentFormStarGift struct {
	// Form ID.
	FormID int64
	// Invoice
	Invoice Invoice
}

// PaymentsPaymentFormStarGiftTypeID is TL type id of PaymentsPaymentFormStarGift.
const PaymentsPaymentFormStarGiftTypeID = 0xb425cfe1

// construct implements constructor of PaymentsPaymentFormClass.
func (p PaymentsPaymentFormStarGift) construct() PaymentsPaymentFormClass { return &p }

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

	_ PaymentsPaymentFormClass = &PaymentsPaymentFormStarGift{}
)

func (p *PaymentsPaymentFormStarGift) Zero() bool {
	if p == nil {
		return true
	}
	if !(p.FormID == 0) {
		return false
	}
	if !(p.Invoice.Zero()) {
		return false
	}

	return true
}

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

// FillFrom fills PaymentsPaymentFormStarGift from given interface.
func (p *PaymentsPaymentFormStarGift) FillFrom(from interface {
	GetFormID() (value int64)
	GetInvoice() (value Invoice)
}) {
	p.FormID = from.GetFormID()
	p.Invoice = from.GetInvoice()
}

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

// TypeName returns name of type in TL schema.
func (*PaymentsPaymentFormStarGift) TypeName() string {
	return "payments.paymentFormStarGift"
}

// TypeInfo returns info about TL type.
func (p *PaymentsPaymentFormStarGift) TypeInfo() tdp.Type {
	typ := tdp.Type{
		Name: "payments.paymentFormStarGift",
		ID:   PaymentsPaymentFormStarGiftTypeID,
	}
	if p == nil {
		typ.Null = true
		return typ
	}
	typ.Fields = []tdp.Field{
		{
			Name:       "FormID",
			SchemaName: "form_id",
		},
		{
			Name:       "Invoice",
			SchemaName: "invoice",
		},
	}
	return typ
}

// Encode implements bin.Encoder.
func (p *PaymentsPaymentFormStarGift) Encode(b *bin.Buffer) error {
	if p == nil {
		return fmt.Errorf("can't encode payments.paymentFormStarGift#b425cfe1 as nil")
	}
	b.PutID(PaymentsPaymentFormStarGiftTypeID)
	return p.EncodeBare(b)
}

// EncodeBare implements bin.BareEncoder.
func (p *PaymentsPaymentFormStarGift) EncodeBare(b *bin.Buffer) error {
	if p == nil {
		return fmt.Errorf("can't encode payments.paymentFormStarGift#b425cfe1 as nil")
	}
	b.PutLong(p.FormID)
	if err := p.Invoice.Encode(b); err != nil {
		return fmt.Errorf("unable to encode payments.paymentFormStarGift#b425cfe1: field invoice: %w", err)
	}
	return nil
}

// Decode implements bin.Decoder.
func (p *PaymentsPaymentFormStarGift) Decode(b *bin.Buffer) error {
	if p == nil {
		return fmt.Errorf("can't decode payments.paymentFormStarGift#b425cfe1 to nil")
	}
	if err := b.ConsumeID(PaymentsPaymentFormStarGiftTypeID); err != nil {
		return fmt.Errorf("unable to decode payments.paymentFormStarGift#b425cfe1: %w", err)
	}
	return p.DecodeBare(b)
}

// DecodeBare implements bin.BareDecoder.
func (p *PaymentsPaymentFormStarGift) DecodeBare(b *bin.Buffer) error {
	if p == nil {
		return fmt.Errorf("can't decode payments.paymentFormStarGift#b425cfe1 to nil")
	}
	{
		value, err := b.Long()
		if err != nil {
			return fmt.Errorf("unable to decode payments.paymentFormStarGift#b425cfe1: field form_id: %w", err)
		}
		p.FormID = value
	}
	{
		if err := p.Invoice.Decode(b); err != nil {
			return fmt.Errorf("unable to decode payments.paymentFormStarGift#b425cfe1: field invoice: %w", err)
		}
	}
	return nil
}

// GetFormID returns value of FormID field.
func (p *PaymentsPaymentFormStarGift) GetFormID() (value int64) {
	if p == nil {
		return
	}
	return p.FormID
}

// GetInvoice returns value of Invoice field.
func (p *PaymentsPaymentFormStarGift) GetInvoice() (value Invoice) {
	if p == nil {
		return
	}
	return p.Invoice
}

// PaymentsPaymentFormClassName is schema name of PaymentsPaymentFormClass.
const PaymentsPaymentFormClassName = "payments.PaymentForm"

// PaymentsPaymentFormClass represents payments.PaymentForm generic type.
//
// See https://core.telegram.org/type/payments.PaymentForm for reference.
//
// Example:
//
//	g, err := tg.DecodePaymentsPaymentForm(buf)
//	if err != nil {
//	    panic(err)
//	}
//	switch v := g.(type) {
//	case *tg.PaymentsPaymentForm: // payments.paymentForm#a0058751
//	case *tg.PaymentsPaymentFormStars: // payments.paymentFormStars#7bf6b15c
//	case *tg.PaymentsPaymentFormStarGift: // payments.paymentFormStarGift#b425cfe1
//	default: panic(v)
//	}
type PaymentsPaymentFormClass interface {
	bin.Encoder
	bin.Decoder
	bin.BareEncoder
	bin.BareDecoder
	construct() PaymentsPaymentFormClass

	// 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

	// Form ID
	GetFormID() (value int64)

	// Invoice
	GetInvoice() (value Invoice)
}

// DecodePaymentsPaymentForm implements binary de-serialization for PaymentsPaymentFormClass.
func DecodePaymentsPaymentForm(buf *bin.Buffer) (PaymentsPaymentFormClass, error) {
	id, err := buf.PeekID()
	if err != nil {
		return nil, err
	}
	switch id {
	case PaymentsPaymentFormTypeID:
		// Decoding payments.paymentForm#a0058751.
		v := PaymentsPaymentForm{}
		if err := v.Decode(buf); err != nil {
			return nil, fmt.Errorf("unable to decode PaymentsPaymentFormClass: %w", err)
		}
		return &v, nil
	case PaymentsPaymentFormStarsTypeID:
		// Decoding payments.paymentFormStars#7bf6b15c.
		v := PaymentsPaymentFormStars{}
		if err := v.Decode(buf); err != nil {
			return nil, fmt.Errorf("unable to decode PaymentsPaymentFormClass: %w", err)
		}
		return &v, nil
	case PaymentsPaymentFormStarGiftTypeID:
		// Decoding payments.paymentFormStarGift#b425cfe1.
		v := PaymentsPaymentFormStarGift{}
		if err := v.Decode(buf); err != nil {
			return nil, fmt.Errorf("unable to decode PaymentsPaymentFormClass: %w", err)
		}
		return &v, nil
	default:
		return nil, fmt.Errorf("unable to decode PaymentsPaymentFormClass: %w", bin.NewUnexpectedID(id))
	}
}

// PaymentsPaymentForm boxes the PaymentsPaymentFormClass providing a helper.
type PaymentsPaymentFormBox struct {
	PaymentForm PaymentsPaymentFormClass
}

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

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