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

// StarsSubscription represents TL type `starsSubscription#2e6eab1a`.
// Represents a Telegram Star subscription »¹.
//
// Links:
//  1. https://core.telegram.org/api/invites#paid-invite-links
//
// See https://core.telegram.org/constructor/starsSubscription for reference.
type StarsSubscription struct {
	// Flags, see TL conditional fields¹
	//
	// Links:
	//  1) https://core.telegram.org/mtproto/TL-combinators#conditional-fields
	Flags bin.Fields
	// Whether this subscription was cancelled.
	Canceled bool
	// Whether we left the associated private channel, but we can still rejoin it using
	// payments.fulfillStarsSubscription¹ because the current subscription period hasn't
	// expired yet.
	//
	// Links:
	//  1) https://core.telegram.org/method/payments.fulfillStarsSubscription
	CanRefulfill bool
	// Whether this subscription has expired because there are not enough stars on the user's
	// balance to extend it.
	MissingBalance bool
	// Set if this bot subscription¹ was cancelled by the bot
	//
	// Links:
	//  1) https://core.telegram.org/api/subscriptions#bot-subscriptions
	BotCanceled bool
	// Subscription ID.
	ID string
	// Identifier of the associated private chat.
	Peer PeerClass
	// Expiration date of the current subscription period.
	UntilDate int
	// Pricing of the subscription in Telegram Stars.
	Pricing StarsSubscriptionPricing
	// Invitation link, used to renew the subscription after cancellation or expiration.
	//
	// Use SetChatInviteHash and GetChatInviteHash helpers.
	ChatInviteHash string
	// For bot subscriptions, the title of the subscription invoice
	//
	// Use SetTitle and GetTitle helpers.
	Title string
	// For bot subscriptions, the photo from the subscription invoice
	//
	// Use SetPhoto and GetPhoto helpers.
	Photo WebDocumentClass
	// For bot subscriptions, the identifier¹ of the subscription invoice
	//
	// Links:
	//  1) https://core.telegram.org/api/links#invoice-links
	//
	// Use SetInvoiceSlug and GetInvoiceSlug helpers.
	InvoiceSlug string
}

// StarsSubscriptionTypeID is TL type id of StarsSubscription.
const StarsSubscriptionTypeID = 0x2e6eab1a

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

func (s *StarsSubscription) Zero() bool {
	if s == nil {
		return true
	}
	if !(s.Flags.Zero()) {
		return false
	}
	if !(s.Canceled == false) {
		return false
	}
	if !(s.CanRefulfill == false) {
		return false
	}
	if !(s.MissingBalance == false) {
		return false
	}
	if !(s.BotCanceled == false) {
		return false
	}
	if !(s.ID == "") {
		return false
	}
	if !(s.Peer == nil) {
		return false
	}
	if !(s.UntilDate == 0) {
		return false
	}
	if !(s.Pricing.Zero()) {
		return false
	}
	if !(s.ChatInviteHash == "") {
		return false
	}
	if !(s.Title == "") {
		return false
	}
	if !(s.Photo == nil) {
		return false
	}
	if !(s.InvoiceSlug == "") {
		return false
	}

	return true
}

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

// FillFrom fills StarsSubscription from given interface.
func (s *StarsSubscription) FillFrom(from interface {
	GetCanceled() (value bool)
	GetCanRefulfill() (value bool)
	GetMissingBalance() (value bool)
	GetBotCanceled() (value bool)
	GetID() (value string)
	GetPeer() (value PeerClass)
	GetUntilDate() (value int)
	GetPricing() (value StarsSubscriptionPricing)
	GetChatInviteHash() (value string, ok bool)
	GetTitle() (value string, ok bool)
	GetPhoto() (value WebDocumentClass, ok bool)
	GetInvoiceSlug() (value string, ok bool)
}) {
	s.Canceled = from.GetCanceled()
	s.CanRefulfill = from.GetCanRefulfill()
	s.MissingBalance = from.GetMissingBalance()
	s.BotCanceled = from.GetBotCanceled()
	s.ID = from.GetID()
	s.Peer = from.GetPeer()
	s.UntilDate = from.GetUntilDate()
	s.Pricing = from.GetPricing()
	if val, ok := from.GetChatInviteHash(); ok {
		s.ChatInviteHash = val
	}

	if val, ok := from.GetTitle(); ok {
		s.Title = val
	}

	if val, ok := from.GetPhoto(); ok {
		s.Photo = val
	}

	if val, ok := from.GetInvoiceSlug(); ok {
		s.InvoiceSlug = val
	}

}

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

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

// TypeInfo returns info about TL type.
func (s *StarsSubscription) TypeInfo() tdp.Type {
	typ := tdp.Type{
		Name: "starsSubscription",
		ID:   StarsSubscriptionTypeID,
	}
	if s == nil {
		typ.Null = true
		return typ
	}
	typ.Fields = []tdp.Field{
		{
			Name:       "Canceled",
			SchemaName: "canceled",
			Null:       !s.Flags.Has(0),
		},
		{
			Name:       "CanRefulfill",
			SchemaName: "can_refulfill",
			Null:       !s.Flags.Has(1),
		},
		{
			Name:       "MissingBalance",
			SchemaName: "missing_balance",
			Null:       !s.Flags.Has(2),
		},
		{
			Name:       "BotCanceled",
			SchemaName: "bot_canceled",
			Null:       !s.Flags.Has(7),
		},
		{
			Name:       "ID",
			SchemaName: "id",
		},
		{
			Name:       "Peer",
			SchemaName: "peer",
		},
		{
			Name:       "UntilDate",
			SchemaName: "until_date",
		},
		{
			Name:       "Pricing",
			SchemaName: "pricing",
		},
		{
			Name:       "ChatInviteHash",
			SchemaName: "chat_invite_hash",
			Null:       !s.Flags.Has(3),
		},
		{
			Name:       "Title",
			SchemaName: "title",
			Null:       !s.Flags.Has(4),
		},
		{
			Name:       "Photo",
			SchemaName: "photo",
			Null:       !s.Flags.Has(5),
		},
		{
			Name:       "InvoiceSlug",
			SchemaName: "invoice_slug",
			Null:       !s.Flags.Has(6),
		},
	}
	return typ
}

// SetFlags sets flags for non-zero fields.
func (s *StarsSubscription) SetFlags() {
	if !(s.Canceled == false) {
		s.Flags.Set(0)
	}
	if !(s.CanRefulfill == false) {
		s.Flags.Set(1)
	}
	if !(s.MissingBalance == false) {
		s.Flags.Set(2)
	}
	if !(s.BotCanceled == false) {
		s.Flags.Set(7)
	}
	if !(s.ChatInviteHash == "") {
		s.Flags.Set(3)
	}
	if !(s.Title == "") {
		s.Flags.Set(4)
	}
	if !(s.Photo == nil) {
		s.Flags.Set(5)
	}
	if !(s.InvoiceSlug == "") {
		s.Flags.Set(6)
	}
}

// Encode implements bin.Encoder.
func (s *StarsSubscription) Encode(b *bin.Buffer) error {
	if s == nil {
		return fmt.Errorf("can't encode starsSubscription#2e6eab1a as nil")
	}
	b.PutID(StarsSubscriptionTypeID)
	return s.EncodeBare(b)
}

// EncodeBare implements bin.BareEncoder.
func (s *StarsSubscription) EncodeBare(b *bin.Buffer) error {
	if s == nil {
		return fmt.Errorf("can't encode starsSubscription#2e6eab1a as nil")
	}
	s.SetFlags()
	if err := s.Flags.Encode(b); err != nil {
		return fmt.Errorf("unable to encode starsSubscription#2e6eab1a: field flags: %w", err)
	}
	b.PutString(s.ID)
	if s.Peer == nil {
		return fmt.Errorf("unable to encode starsSubscription#2e6eab1a: field peer is nil")
	}
	if err := s.Peer.Encode(b); err != nil {
		return fmt.Errorf("unable to encode starsSubscription#2e6eab1a: field peer: %w", err)
	}
	b.PutInt(s.UntilDate)
	if err := s.Pricing.Encode(b); err != nil {
		return fmt.Errorf("unable to encode starsSubscription#2e6eab1a: field pricing: %w", err)
	}
	if s.Flags.Has(3) {
		b.PutString(s.ChatInviteHash)
	}
	if s.Flags.Has(4) {
		b.PutString(s.Title)
	}
	if s.Flags.Has(5) {
		if s.Photo == nil {
			return fmt.Errorf("unable to encode starsSubscription#2e6eab1a: field photo is nil")
		}
		if err := s.Photo.Encode(b); err != nil {
			return fmt.Errorf("unable to encode starsSubscription#2e6eab1a: field photo: %w", err)
		}
	}
	if s.Flags.Has(6) {
		b.PutString(s.InvoiceSlug)
	}
	return nil
}

// Decode implements bin.Decoder.
func (s *StarsSubscription) Decode(b *bin.Buffer) error {
	if s == nil {
		return fmt.Errorf("can't decode starsSubscription#2e6eab1a to nil")
	}
	if err := b.ConsumeID(StarsSubscriptionTypeID); err != nil {
		return fmt.Errorf("unable to decode starsSubscription#2e6eab1a: %w", err)
	}
	return s.DecodeBare(b)
}

// DecodeBare implements bin.BareDecoder.
func (s *StarsSubscription) DecodeBare(b *bin.Buffer) error {
	if s == nil {
		return fmt.Errorf("can't decode starsSubscription#2e6eab1a to nil")
	}
	{
		if err := s.Flags.Decode(b); err != nil {
			return fmt.Errorf("unable to decode starsSubscription#2e6eab1a: field flags: %w", err)
		}
	}
	s.Canceled = s.Flags.Has(0)
	s.CanRefulfill = s.Flags.Has(1)
	s.MissingBalance = s.Flags.Has(2)
	s.BotCanceled = s.Flags.Has(7)
	{
		value, err := b.String()
		if err != nil {
			return fmt.Errorf("unable to decode starsSubscription#2e6eab1a: field id: %w", err)
		}
		s.ID = value
	}
	{
		value, err := DecodePeer(b)
		if err != nil {
			return fmt.Errorf("unable to decode starsSubscription#2e6eab1a: field peer: %w", err)
		}
		s.Peer = value
	}
	{
		value, err := b.Int()
		if err != nil {
			return fmt.Errorf("unable to decode starsSubscription#2e6eab1a: field until_date: %w", err)
		}
		s.UntilDate = value
	}
	{
		if err := s.Pricing.Decode(b); err != nil {
			return fmt.Errorf("unable to decode starsSubscription#2e6eab1a: field pricing: %w", err)
		}
	}
	if s.Flags.Has(3) {
		value, err := b.String()
		if err != nil {
			return fmt.Errorf("unable to decode starsSubscription#2e6eab1a: field chat_invite_hash: %w", err)
		}
		s.ChatInviteHash = value
	}
	if s.Flags.Has(4) {
		value, err := b.String()
		if err != nil {
			return fmt.Errorf("unable to decode starsSubscription#2e6eab1a: field title: %w", err)
		}
		s.Title = value
	}
	if s.Flags.Has(5) {
		value, err := DecodeWebDocument(b)
		if err != nil {
			return fmt.Errorf("unable to decode starsSubscription#2e6eab1a: field photo: %w", err)
		}
		s.Photo = value
	}
	if s.Flags.Has(6) {
		value, err := b.String()
		if err != nil {
			return fmt.Errorf("unable to decode starsSubscription#2e6eab1a: field invoice_slug: %w", err)
		}
		s.InvoiceSlug = value
	}
	return nil
}

// SetCanceled sets value of Canceled conditional field.
func (s *StarsSubscription) SetCanceled(value bool) {
	if value {
		s.Flags.Set(0)
		s.Canceled = true
	} else {
		s.Flags.Unset(0)
		s.Canceled = false
	}
}

// GetCanceled returns value of Canceled conditional field.
func (s *StarsSubscription) GetCanceled() (value bool) {
	if s == nil {
		return
	}
	return s.Flags.Has(0)
}

// SetCanRefulfill sets value of CanRefulfill conditional field.
func (s *StarsSubscription) SetCanRefulfill(value bool) {
	if value {
		s.Flags.Set(1)
		s.CanRefulfill = true
	} else {
		s.Flags.Unset(1)
		s.CanRefulfill = false
	}
}

// GetCanRefulfill returns value of CanRefulfill conditional field.
func (s *StarsSubscription) GetCanRefulfill() (value bool) {
	if s == nil {
		return
	}
	return s.Flags.Has(1)
}

// SetMissingBalance sets value of MissingBalance conditional field.
func (s *StarsSubscription) SetMissingBalance(value bool) {
	if value {
		s.Flags.Set(2)
		s.MissingBalance = true
	} else {
		s.Flags.Unset(2)
		s.MissingBalance = false
	}
}

// GetMissingBalance returns value of MissingBalance conditional field.
func (s *StarsSubscription) GetMissingBalance() (value bool) {
	if s == nil {
		return
	}
	return s.Flags.Has(2)
}

// SetBotCanceled sets value of BotCanceled conditional field.
func (s *StarsSubscription) SetBotCanceled(value bool) {
	if value {
		s.Flags.Set(7)
		s.BotCanceled = true
	} else {
		s.Flags.Unset(7)
		s.BotCanceled = false
	}
}

// GetBotCanceled returns value of BotCanceled conditional field.
func (s *StarsSubscription) GetBotCanceled() (value bool) {
	if s == nil {
		return
	}
	return s.Flags.Has(7)
}

// GetID returns value of ID field.
func (s *StarsSubscription) GetID() (value string) {
	if s == nil {
		return
	}
	return s.ID
}

// GetPeer returns value of Peer field.
func (s *StarsSubscription) GetPeer() (value PeerClass) {
	if s == nil {
		return
	}
	return s.Peer
}

// GetUntilDate returns value of UntilDate field.
func (s *StarsSubscription) GetUntilDate() (value int) {
	if s == nil {
		return
	}
	return s.UntilDate
}

// GetPricing returns value of Pricing field.
func (s *StarsSubscription) GetPricing() (value StarsSubscriptionPricing) {
	if s == nil {
		return
	}
	return s.Pricing
}

// SetChatInviteHash sets value of ChatInviteHash conditional field.
func (s *StarsSubscription) SetChatInviteHash(value string) {
	s.Flags.Set(3)
	s.ChatInviteHash = value
}

// GetChatInviteHash returns value of ChatInviteHash conditional field and
// boolean which is true if field was set.
func (s *StarsSubscription) GetChatInviteHash() (value string, ok bool) {
	if s == nil {
		return
	}
	if !s.Flags.Has(3) {
		return value, false
	}
	return s.ChatInviteHash, true
}

// SetTitle sets value of Title conditional field.
func (s *StarsSubscription) SetTitle(value string) {
	s.Flags.Set(4)
	s.Title = value
}

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

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

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

// SetInvoiceSlug sets value of InvoiceSlug conditional field.
func (s *StarsSubscription) SetInvoiceSlug(value string) {
	s.Flags.Set(6)
	s.InvoiceSlug = value
}

// GetInvoiceSlug returns value of InvoiceSlug conditional field and
// boolean which is true if field was set.
func (s *StarsSubscription) GetInvoiceSlug() (value string, ok bool) {
	if s == nil {
		return
	}
	if !s.Flags.Has(6) {
		return value, false
	}
	return s.InvoiceSlug, true
}
