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

// StarGift represents TL type `starGift#c62aca28`.
// Represents a star gift, see here »¹ for more info.
//
// Links:
//  1. https://core.telegram.org/api/gifts
//
// See https://core.telegram.org/constructor/starGift for reference.
type StarGift struct {
	// Flags, see TL conditional fields¹
	//
	// Links:
	//  1) https://core.telegram.org/mtproto/TL-combinators#conditional-fields
	Flags bin.Fields
	// Whether this is a limited-supply gift.
	Limited bool
	// Whether this gift sold out and cannot be bought anymore.
	SoldOut bool
	// Birthday field of StarGift.
	Birthday bool
	// Identifier of the gift
	ID int64
	// Sticker¹ that represents the gift.
	//
	// Links:
	//  1) https://core.telegram.org/api/stickers
	Sticker DocumentClass
	// Price of the gift in Telegram Stars¹.
	//
	// Links:
	//  1) https://core.telegram.org/api/stars
	Stars int64
	// For limited-supply gifts: the remaining number of gifts that may be bought.
	//
	// Use SetAvailabilityRemains and GetAvailabilityRemains helpers.
	AvailabilityRemains int
	// For limited-supply gifts: the total number of gifts that was available in the initial
	// supply.
	//
	// Use SetAvailabilityTotal and GetAvailabilityTotal helpers.
	AvailabilityTotal int
	// AvailabilityResale field of StarGift.
	//
	// Use SetAvailabilityResale and GetAvailabilityResale helpers.
	AvailabilityResale int64
	// The receiver of this gift may convert it to this many Telegram Stars, instead of
	// displaying it on their profile page.convert_stars will be equal to stars only if the
	// gift was bought using recently bought Telegram Stars, otherwise it will be less than
	// stars.
	ConvertStars int64
	// For sold out gifts only: when was the gift first bought.
	//
	// Use SetFirstSaleDate and GetFirstSaleDate helpers.
	FirstSaleDate int
	// For sold out gifts only: when was the gift last bought.
	//
	// Use SetLastSaleDate and GetLastSaleDate helpers.
	LastSaleDate int
	// UpgradeStars field of StarGift.
	//
	// Use SetUpgradeStars and GetUpgradeStars helpers.
	UpgradeStars int64
	// ResellMinStars field of StarGift.
	//
	// Use SetResellMinStars and GetResellMinStars helpers.
	ResellMinStars int64
	// Title field of StarGift.
	//
	// Use SetTitle and GetTitle helpers.
	Title string
}

// StarGiftTypeID is TL type id of StarGift.
const StarGiftTypeID = 0xc62aca28

// construct implements constructor of StarGiftClass.
func (s StarGift) construct() StarGiftClass { return &s }

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

	_ StarGiftClass = &StarGift{}
)

func (s *StarGift) Zero() bool {
	if s == nil {
		return true
	}
	if !(s.Flags.Zero()) {
		return false
	}
	if !(s.Limited == false) {
		return false
	}
	if !(s.SoldOut == false) {
		return false
	}
	if !(s.Birthday == false) {
		return false
	}
	if !(s.ID == 0) {
		return false
	}
	if !(s.Sticker == nil) {
		return false
	}
	if !(s.Stars == 0) {
		return false
	}
	if !(s.AvailabilityRemains == 0) {
		return false
	}
	if !(s.AvailabilityTotal == 0) {
		return false
	}
	if !(s.AvailabilityResale == 0) {
		return false
	}
	if !(s.ConvertStars == 0) {
		return false
	}
	if !(s.FirstSaleDate == 0) {
		return false
	}
	if !(s.LastSaleDate == 0) {
		return false
	}
	if !(s.UpgradeStars == 0) {
		return false
	}
	if !(s.ResellMinStars == 0) {
		return false
	}
	if !(s.Title == "") {
		return false
	}

	return true
}

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

// FillFrom fills StarGift from given interface.
func (s *StarGift) FillFrom(from interface {
	GetLimited() (value bool)
	GetSoldOut() (value bool)
	GetBirthday() (value bool)
	GetID() (value int64)
	GetSticker() (value DocumentClass)
	GetStars() (value int64)
	GetAvailabilityRemains() (value int, ok bool)
	GetAvailabilityTotal() (value int, ok bool)
	GetAvailabilityResale() (value int64, ok bool)
	GetConvertStars() (value int64)
	GetFirstSaleDate() (value int, ok bool)
	GetLastSaleDate() (value int, ok bool)
	GetUpgradeStars() (value int64, ok bool)
	GetResellMinStars() (value int64, ok bool)
	GetTitle() (value string, ok bool)
}) {
	s.Limited = from.GetLimited()
	s.SoldOut = from.GetSoldOut()
	s.Birthday = from.GetBirthday()
	s.ID = from.GetID()
	s.Sticker = from.GetSticker()
	s.Stars = from.GetStars()
	if val, ok := from.GetAvailabilityRemains(); ok {
		s.AvailabilityRemains = val
	}

	if val, ok := from.GetAvailabilityTotal(); ok {
		s.AvailabilityTotal = val
	}

	if val, ok := from.GetAvailabilityResale(); ok {
		s.AvailabilityResale = val
	}

	s.ConvertStars = from.GetConvertStars()
	if val, ok := from.GetFirstSaleDate(); ok {
		s.FirstSaleDate = val
	}

	if val, ok := from.GetLastSaleDate(); ok {
		s.LastSaleDate = val
	}

	if val, ok := from.GetUpgradeStars(); ok {
		s.UpgradeStars = val
	}

	if val, ok := from.GetResellMinStars(); ok {
		s.ResellMinStars = val
	}

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

}

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

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

// TypeInfo returns info about TL type.
func (s *StarGift) TypeInfo() tdp.Type {
	typ := tdp.Type{
		Name: "starGift",
		ID:   StarGiftTypeID,
	}
	if s == nil {
		typ.Null = true
		return typ
	}
	typ.Fields = []tdp.Field{
		{
			Name:       "Limited",
			SchemaName: "limited",
			Null:       !s.Flags.Has(0),
		},
		{
			Name:       "SoldOut",
			SchemaName: "sold_out",
			Null:       !s.Flags.Has(1),
		},
		{
			Name:       "Birthday",
			SchemaName: "birthday",
			Null:       !s.Flags.Has(2),
		},
		{
			Name:       "ID",
			SchemaName: "id",
		},
		{
			Name:       "Sticker",
			SchemaName: "sticker",
		},
		{
			Name:       "Stars",
			SchemaName: "stars",
		},
		{
			Name:       "AvailabilityRemains",
			SchemaName: "availability_remains",
			Null:       !s.Flags.Has(0),
		},
		{
			Name:       "AvailabilityTotal",
			SchemaName: "availability_total",
			Null:       !s.Flags.Has(0),
		},
		{
			Name:       "AvailabilityResale",
			SchemaName: "availability_resale",
			Null:       !s.Flags.Has(4),
		},
		{
			Name:       "ConvertStars",
			SchemaName: "convert_stars",
		},
		{
			Name:       "FirstSaleDate",
			SchemaName: "first_sale_date",
			Null:       !s.Flags.Has(1),
		},
		{
			Name:       "LastSaleDate",
			SchemaName: "last_sale_date",
			Null:       !s.Flags.Has(1),
		},
		{
			Name:       "UpgradeStars",
			SchemaName: "upgrade_stars",
			Null:       !s.Flags.Has(3),
		},
		{
			Name:       "ResellMinStars",
			SchemaName: "resell_min_stars",
			Null:       !s.Flags.Has(4),
		},
		{
			Name:       "Title",
			SchemaName: "title",
			Null:       !s.Flags.Has(5),
		},
	}
	return typ
}

// SetFlags sets flags for non-zero fields.
func (s *StarGift) SetFlags() {
	if !(s.Limited == false) {
		s.Flags.Set(0)
	}
	if !(s.SoldOut == false) {
		s.Flags.Set(1)
	}
	if !(s.Birthday == false) {
		s.Flags.Set(2)
	}
	if !(s.AvailabilityRemains == 0) {
		s.Flags.Set(0)
	}
	if !(s.AvailabilityTotal == 0) {
		s.Flags.Set(0)
	}
	if !(s.AvailabilityResale == 0) {
		s.Flags.Set(4)
	}
	if !(s.FirstSaleDate == 0) {
		s.Flags.Set(1)
	}
	if !(s.LastSaleDate == 0) {
		s.Flags.Set(1)
	}
	if !(s.UpgradeStars == 0) {
		s.Flags.Set(3)
	}
	if !(s.ResellMinStars == 0) {
		s.Flags.Set(4)
	}
	if !(s.Title == "") {
		s.Flags.Set(5)
	}
}

// Encode implements bin.Encoder.
func (s *StarGift) Encode(b *bin.Buffer) error {
	if s == nil {
		return fmt.Errorf("can't encode starGift#c62aca28 as nil")
	}
	b.PutID(StarGiftTypeID)
	return s.EncodeBare(b)
}

// EncodeBare implements bin.BareEncoder.
func (s *StarGift) EncodeBare(b *bin.Buffer) error {
	if s == nil {
		return fmt.Errorf("can't encode starGift#c62aca28 as nil")
	}
	s.SetFlags()
	if err := s.Flags.Encode(b); err != nil {
		return fmt.Errorf("unable to encode starGift#c62aca28: field flags: %w", err)
	}
	b.PutLong(s.ID)
	if s.Sticker == nil {
		return fmt.Errorf("unable to encode starGift#c62aca28: field sticker is nil")
	}
	if err := s.Sticker.Encode(b); err != nil {
		return fmt.Errorf("unable to encode starGift#c62aca28: field sticker: %w", err)
	}
	b.PutLong(s.Stars)
	if s.Flags.Has(0) {
		b.PutInt(s.AvailabilityRemains)
	}
	if s.Flags.Has(0) {
		b.PutInt(s.AvailabilityTotal)
	}
	if s.Flags.Has(4) {
		b.PutLong(s.AvailabilityResale)
	}
	b.PutLong(s.ConvertStars)
	if s.Flags.Has(1) {
		b.PutInt(s.FirstSaleDate)
	}
	if s.Flags.Has(1) {
		b.PutInt(s.LastSaleDate)
	}
	if s.Flags.Has(3) {
		b.PutLong(s.UpgradeStars)
	}
	if s.Flags.Has(4) {
		b.PutLong(s.ResellMinStars)
	}
	if s.Flags.Has(5) {
		b.PutString(s.Title)
	}
	return nil
}

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

// DecodeBare implements bin.BareDecoder.
func (s *StarGift) DecodeBare(b *bin.Buffer) error {
	if s == nil {
		return fmt.Errorf("can't decode starGift#c62aca28 to nil")
	}
	{
		if err := s.Flags.Decode(b); err != nil {
			return fmt.Errorf("unable to decode starGift#c62aca28: field flags: %w", err)
		}
	}
	s.Limited = s.Flags.Has(0)
	s.SoldOut = s.Flags.Has(1)
	s.Birthday = s.Flags.Has(2)
	{
		value, err := b.Long()
		if err != nil {
			return fmt.Errorf("unable to decode starGift#c62aca28: field id: %w", err)
		}
		s.ID = value
	}
	{
		value, err := DecodeDocument(b)
		if err != nil {
			return fmt.Errorf("unable to decode starGift#c62aca28: field sticker: %w", err)
		}
		s.Sticker = value
	}
	{
		value, err := b.Long()
		if err != nil {
			return fmt.Errorf("unable to decode starGift#c62aca28: field stars: %w", err)
		}
		s.Stars = value
	}
	if s.Flags.Has(0) {
		value, err := b.Int()
		if err != nil {
			return fmt.Errorf("unable to decode starGift#c62aca28: field availability_remains: %w", err)
		}
		s.AvailabilityRemains = value
	}
	if s.Flags.Has(0) {
		value, err := b.Int()
		if err != nil {
			return fmt.Errorf("unable to decode starGift#c62aca28: field availability_total: %w", err)
		}
		s.AvailabilityTotal = value
	}
	if s.Flags.Has(4) {
		value, err := b.Long()
		if err != nil {
			return fmt.Errorf("unable to decode starGift#c62aca28: field availability_resale: %w", err)
		}
		s.AvailabilityResale = value
	}
	{
		value, err := b.Long()
		if err != nil {
			return fmt.Errorf("unable to decode starGift#c62aca28: field convert_stars: %w", err)
		}
		s.ConvertStars = value
	}
	if s.Flags.Has(1) {
		value, err := b.Int()
		if err != nil {
			return fmt.Errorf("unable to decode starGift#c62aca28: field first_sale_date: %w", err)
		}
		s.FirstSaleDate = value
	}
	if s.Flags.Has(1) {
		value, err := b.Int()
		if err != nil {
			return fmt.Errorf("unable to decode starGift#c62aca28: field last_sale_date: %w", err)
		}
		s.LastSaleDate = value
	}
	if s.Flags.Has(3) {
		value, err := b.Long()
		if err != nil {
			return fmt.Errorf("unable to decode starGift#c62aca28: field upgrade_stars: %w", err)
		}
		s.UpgradeStars = value
	}
	if s.Flags.Has(4) {
		value, err := b.Long()
		if err != nil {
			return fmt.Errorf("unable to decode starGift#c62aca28: field resell_min_stars: %w", err)
		}
		s.ResellMinStars = value
	}
	if s.Flags.Has(5) {
		value, err := b.String()
		if err != nil {
			return fmt.Errorf("unable to decode starGift#c62aca28: field title: %w", err)
		}
		s.Title = value
	}
	return nil
}

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

// GetLimited returns value of Limited conditional field.
func (s *StarGift) GetLimited() (value bool) {
	if s == nil {
		return
	}
	return s.Flags.Has(0)
}

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

// GetSoldOut returns value of SoldOut conditional field.
func (s *StarGift) GetSoldOut() (value bool) {
	if s == nil {
		return
	}
	return s.Flags.Has(1)
}

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

// GetBirthday returns value of Birthday conditional field.
func (s *StarGift) GetBirthday() (value bool) {
	if s == nil {
		return
	}
	return s.Flags.Has(2)
}

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

// GetSticker returns value of Sticker field.
func (s *StarGift) GetSticker() (value DocumentClass) {
	if s == nil {
		return
	}
	return s.Sticker
}

// GetStars returns value of Stars field.
func (s *StarGift) GetStars() (value int64) {
	if s == nil {
		return
	}
	return s.Stars
}

// SetAvailabilityRemains sets value of AvailabilityRemains conditional field.
func (s *StarGift) SetAvailabilityRemains(value int) {
	s.Flags.Set(0)
	s.AvailabilityRemains = value
}

// GetAvailabilityRemains returns value of AvailabilityRemains conditional field and
// boolean which is true if field was set.
func (s *StarGift) GetAvailabilityRemains() (value int, ok bool) {
	if s == nil {
		return
	}
	if !s.Flags.Has(0) {
		return value, false
	}
	return s.AvailabilityRemains, true
}

// SetAvailabilityTotal sets value of AvailabilityTotal conditional field.
func (s *StarGift) SetAvailabilityTotal(value int) {
	s.Flags.Set(0)
	s.AvailabilityTotal = value
}

// GetAvailabilityTotal returns value of AvailabilityTotal conditional field and
// boolean which is true if field was set.
func (s *StarGift) GetAvailabilityTotal() (value int, ok bool) {
	if s == nil {
		return
	}
	if !s.Flags.Has(0) {
		return value, false
	}
	return s.AvailabilityTotal, true
}

// SetAvailabilityResale sets value of AvailabilityResale conditional field.
func (s *StarGift) SetAvailabilityResale(value int64) {
	s.Flags.Set(4)
	s.AvailabilityResale = value
}

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

// GetConvertStars returns value of ConvertStars field.
func (s *StarGift) GetConvertStars() (value int64) {
	if s == nil {
		return
	}
	return s.ConvertStars
}

// SetFirstSaleDate sets value of FirstSaleDate conditional field.
func (s *StarGift) SetFirstSaleDate(value int) {
	s.Flags.Set(1)
	s.FirstSaleDate = value
}

// GetFirstSaleDate returns value of FirstSaleDate conditional field and
// boolean which is true if field was set.
func (s *StarGift) GetFirstSaleDate() (value int, ok bool) {
	if s == nil {
		return
	}
	if !s.Flags.Has(1) {
		return value, false
	}
	return s.FirstSaleDate, true
}

// SetLastSaleDate sets value of LastSaleDate conditional field.
func (s *StarGift) SetLastSaleDate(value int) {
	s.Flags.Set(1)
	s.LastSaleDate = value
}

// GetLastSaleDate returns value of LastSaleDate conditional field and
// boolean which is true if field was set.
func (s *StarGift) GetLastSaleDate() (value int, ok bool) {
	if s == nil {
		return
	}
	if !s.Flags.Has(1) {
		return value, false
	}
	return s.LastSaleDate, true
}

// SetUpgradeStars sets value of UpgradeStars conditional field.
func (s *StarGift) SetUpgradeStars(value int64) {
	s.Flags.Set(3)
	s.UpgradeStars = value
}

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

// SetResellMinStars sets value of ResellMinStars conditional field.
func (s *StarGift) SetResellMinStars(value int64) {
	s.Flags.Set(4)
	s.ResellMinStars = value
}

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

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

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

// StarGiftUnique represents TL type `starGiftUnique#6411db89`.
//
// See https://core.telegram.org/constructor/starGiftUnique for reference.
type StarGiftUnique struct {
	// Flags field of StarGiftUnique.
	Flags bin.Fields
	// ID field of StarGiftUnique.
	ID int64
	// Title field of StarGiftUnique.
	Title string
	// Slug field of StarGiftUnique.
	Slug string
	// Num field of StarGiftUnique.
	Num int
	// OwnerID field of StarGiftUnique.
	//
	// Use SetOwnerID and GetOwnerID helpers.
	OwnerID PeerClass
	// OwnerName field of StarGiftUnique.
	//
	// Use SetOwnerName and GetOwnerName helpers.
	OwnerName string
	// OwnerAddress field of StarGiftUnique.
	//
	// Use SetOwnerAddress and GetOwnerAddress helpers.
	OwnerAddress string
	// Attributes field of StarGiftUnique.
	Attributes []StarGiftAttributeClass
	// AvailabilityIssued field of StarGiftUnique.
	AvailabilityIssued int
	// AvailabilityTotal field of StarGiftUnique.
	AvailabilityTotal int
	// GiftAddress field of StarGiftUnique.
	//
	// Use SetGiftAddress and GetGiftAddress helpers.
	GiftAddress string
	// ResellStars field of StarGiftUnique.
	//
	// Use SetResellStars and GetResellStars helpers.
	ResellStars int64
}

// StarGiftUniqueTypeID is TL type id of StarGiftUnique.
const StarGiftUniqueTypeID = 0x6411db89

// construct implements constructor of StarGiftClass.
func (s StarGiftUnique) construct() StarGiftClass { return &s }

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

	_ StarGiftClass = &StarGiftUnique{}
)

func (s *StarGiftUnique) Zero() bool {
	if s == nil {
		return true
	}
	if !(s.Flags.Zero()) {
		return false
	}
	if !(s.ID == 0) {
		return false
	}
	if !(s.Title == "") {
		return false
	}
	if !(s.Slug == "") {
		return false
	}
	if !(s.Num == 0) {
		return false
	}
	if !(s.OwnerID == nil) {
		return false
	}
	if !(s.OwnerName == "") {
		return false
	}
	if !(s.OwnerAddress == "") {
		return false
	}
	if !(s.Attributes == nil) {
		return false
	}
	if !(s.AvailabilityIssued == 0) {
		return false
	}
	if !(s.AvailabilityTotal == 0) {
		return false
	}
	if !(s.GiftAddress == "") {
		return false
	}
	if !(s.ResellStars == 0) {
		return false
	}

	return true
}

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

// FillFrom fills StarGiftUnique from given interface.
func (s *StarGiftUnique) FillFrom(from interface {
	GetID() (value int64)
	GetTitle() (value string)
	GetSlug() (value string)
	GetNum() (value int)
	GetOwnerID() (value PeerClass, ok bool)
	GetOwnerName() (value string, ok bool)
	GetOwnerAddress() (value string, ok bool)
	GetAttributes() (value []StarGiftAttributeClass)
	GetAvailabilityIssued() (value int)
	GetAvailabilityTotal() (value int)
	GetGiftAddress() (value string, ok bool)
	GetResellStars() (value int64, ok bool)
}) {
	s.ID = from.GetID()
	s.Title = from.GetTitle()
	s.Slug = from.GetSlug()
	s.Num = from.GetNum()
	if val, ok := from.GetOwnerID(); ok {
		s.OwnerID = val
	}

	if val, ok := from.GetOwnerName(); ok {
		s.OwnerName = val
	}

	if val, ok := from.GetOwnerAddress(); ok {
		s.OwnerAddress = val
	}

	s.Attributes = from.GetAttributes()
	s.AvailabilityIssued = from.GetAvailabilityIssued()
	s.AvailabilityTotal = from.GetAvailabilityTotal()
	if val, ok := from.GetGiftAddress(); ok {
		s.GiftAddress = val
	}

	if val, ok := from.GetResellStars(); ok {
		s.ResellStars = val
	}

}

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

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

// TypeInfo returns info about TL type.
func (s *StarGiftUnique) TypeInfo() tdp.Type {
	typ := tdp.Type{
		Name: "starGiftUnique",
		ID:   StarGiftUniqueTypeID,
	}
	if s == nil {
		typ.Null = true
		return typ
	}
	typ.Fields = []tdp.Field{
		{
			Name:       "ID",
			SchemaName: "id",
		},
		{
			Name:       "Title",
			SchemaName: "title",
		},
		{
			Name:       "Slug",
			SchemaName: "slug",
		},
		{
			Name:       "Num",
			SchemaName: "num",
		},
		{
			Name:       "OwnerID",
			SchemaName: "owner_id",
			Null:       !s.Flags.Has(0),
		},
		{
			Name:       "OwnerName",
			SchemaName: "owner_name",
			Null:       !s.Flags.Has(1),
		},
		{
			Name:       "OwnerAddress",
			SchemaName: "owner_address",
			Null:       !s.Flags.Has(2),
		},
		{
			Name:       "Attributes",
			SchemaName: "attributes",
		},
		{
			Name:       "AvailabilityIssued",
			SchemaName: "availability_issued",
		},
		{
			Name:       "AvailabilityTotal",
			SchemaName: "availability_total",
		},
		{
			Name:       "GiftAddress",
			SchemaName: "gift_address",
			Null:       !s.Flags.Has(3),
		},
		{
			Name:       "ResellStars",
			SchemaName: "resell_stars",
			Null:       !s.Flags.Has(4),
		},
	}
	return typ
}

// SetFlags sets flags for non-zero fields.
func (s *StarGiftUnique) SetFlags() {
	if !(s.OwnerID == nil) {
		s.Flags.Set(0)
	}
	if !(s.OwnerName == "") {
		s.Flags.Set(1)
	}
	if !(s.OwnerAddress == "") {
		s.Flags.Set(2)
	}
	if !(s.GiftAddress == "") {
		s.Flags.Set(3)
	}
	if !(s.ResellStars == 0) {
		s.Flags.Set(4)
	}
}

// Encode implements bin.Encoder.
func (s *StarGiftUnique) Encode(b *bin.Buffer) error {
	if s == nil {
		return fmt.Errorf("can't encode starGiftUnique#6411db89 as nil")
	}
	b.PutID(StarGiftUniqueTypeID)
	return s.EncodeBare(b)
}

// EncodeBare implements bin.BareEncoder.
func (s *StarGiftUnique) EncodeBare(b *bin.Buffer) error {
	if s == nil {
		return fmt.Errorf("can't encode starGiftUnique#6411db89 as nil")
	}
	s.SetFlags()
	if err := s.Flags.Encode(b); err != nil {
		return fmt.Errorf("unable to encode starGiftUnique#6411db89: field flags: %w", err)
	}
	b.PutLong(s.ID)
	b.PutString(s.Title)
	b.PutString(s.Slug)
	b.PutInt(s.Num)
	if s.Flags.Has(0) {
		if s.OwnerID == nil {
			return fmt.Errorf("unable to encode starGiftUnique#6411db89: field owner_id is nil")
		}
		if err := s.OwnerID.Encode(b); err != nil {
			return fmt.Errorf("unable to encode starGiftUnique#6411db89: field owner_id: %w", err)
		}
	}
	if s.Flags.Has(1) {
		b.PutString(s.OwnerName)
	}
	if s.Flags.Has(2) {
		b.PutString(s.OwnerAddress)
	}
	b.PutVectorHeader(len(s.Attributes))
	for idx, v := range s.Attributes {
		if v == nil {
			return fmt.Errorf("unable to encode starGiftUnique#6411db89: field attributes element with index %d is nil", idx)
		}
		if err := v.Encode(b); err != nil {
			return fmt.Errorf("unable to encode starGiftUnique#6411db89: field attributes element with index %d: %w", idx, err)
		}
	}
	b.PutInt(s.AvailabilityIssued)
	b.PutInt(s.AvailabilityTotal)
	if s.Flags.Has(3) {
		b.PutString(s.GiftAddress)
	}
	if s.Flags.Has(4) {
		b.PutLong(s.ResellStars)
	}
	return nil
}

// Decode implements bin.Decoder.
func (s *StarGiftUnique) Decode(b *bin.Buffer) error {
	if s == nil {
		return fmt.Errorf("can't decode starGiftUnique#6411db89 to nil")
	}
	if err := b.ConsumeID(StarGiftUniqueTypeID); err != nil {
		return fmt.Errorf("unable to decode starGiftUnique#6411db89: %w", err)
	}
	return s.DecodeBare(b)
}

// DecodeBare implements bin.BareDecoder.
func (s *StarGiftUnique) DecodeBare(b *bin.Buffer) error {
	if s == nil {
		return fmt.Errorf("can't decode starGiftUnique#6411db89 to nil")
	}
	{
		if err := s.Flags.Decode(b); err != nil {
			return fmt.Errorf("unable to decode starGiftUnique#6411db89: field flags: %w", err)
		}
	}
	{
		value, err := b.Long()
		if err != nil {
			return fmt.Errorf("unable to decode starGiftUnique#6411db89: field id: %w", err)
		}
		s.ID = value
	}
	{
		value, err := b.String()
		if err != nil {
			return fmt.Errorf("unable to decode starGiftUnique#6411db89: field title: %w", err)
		}
		s.Title = value
	}
	{
		value, err := b.String()
		if err != nil {
			return fmt.Errorf("unable to decode starGiftUnique#6411db89: field slug: %w", err)
		}
		s.Slug = value
	}
	{
		value, err := b.Int()
		if err != nil {
			return fmt.Errorf("unable to decode starGiftUnique#6411db89: field num: %w", err)
		}
		s.Num = value
	}
	if s.Flags.Has(0) {
		value, err := DecodePeer(b)
		if err != nil {
			return fmt.Errorf("unable to decode starGiftUnique#6411db89: field owner_id: %w", err)
		}
		s.OwnerID = value
	}
	if s.Flags.Has(1) {
		value, err := b.String()
		if err != nil {
			return fmt.Errorf("unable to decode starGiftUnique#6411db89: field owner_name: %w", err)
		}
		s.OwnerName = value
	}
	if s.Flags.Has(2) {
		value, err := b.String()
		if err != nil {
			return fmt.Errorf("unable to decode starGiftUnique#6411db89: field owner_address: %w", err)
		}
		s.OwnerAddress = value
	}
	{
		headerLen, err := b.VectorHeader()
		if err != nil {
			return fmt.Errorf("unable to decode starGiftUnique#6411db89: field attributes: %w", err)
		}

		if headerLen > 0 {
			s.Attributes = make([]StarGiftAttributeClass, 0, headerLen%bin.PreallocateLimit)
		}
		for idx := 0; idx < headerLen; idx++ {
			value, err := DecodeStarGiftAttribute(b)
			if err != nil {
				return fmt.Errorf("unable to decode starGiftUnique#6411db89: field attributes: %w", err)
			}
			s.Attributes = append(s.Attributes, value)
		}
	}
	{
		value, err := b.Int()
		if err != nil {
			return fmt.Errorf("unable to decode starGiftUnique#6411db89: field availability_issued: %w", err)
		}
		s.AvailabilityIssued = value
	}
	{
		value, err := b.Int()
		if err != nil {
			return fmt.Errorf("unable to decode starGiftUnique#6411db89: field availability_total: %w", err)
		}
		s.AvailabilityTotal = value
	}
	if s.Flags.Has(3) {
		value, err := b.String()
		if err != nil {
			return fmt.Errorf("unable to decode starGiftUnique#6411db89: field gift_address: %w", err)
		}
		s.GiftAddress = value
	}
	if s.Flags.Has(4) {
		value, err := b.Long()
		if err != nil {
			return fmt.Errorf("unable to decode starGiftUnique#6411db89: field resell_stars: %w", err)
		}
		s.ResellStars = value
	}
	return nil
}

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

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

// GetSlug returns value of Slug field.
func (s *StarGiftUnique) GetSlug() (value string) {
	if s == nil {
		return
	}
	return s.Slug
}

// GetNum returns value of Num field.
func (s *StarGiftUnique) GetNum() (value int) {
	if s == nil {
		return
	}
	return s.Num
}

// SetOwnerID sets value of OwnerID conditional field.
func (s *StarGiftUnique) SetOwnerID(value PeerClass) {
	s.Flags.Set(0)
	s.OwnerID = value
}

// GetOwnerID returns value of OwnerID conditional field and
// boolean which is true if field was set.
func (s *StarGiftUnique) GetOwnerID() (value PeerClass, ok bool) {
	if s == nil {
		return
	}
	if !s.Flags.Has(0) {
		return value, false
	}
	return s.OwnerID, true
}

// SetOwnerName sets value of OwnerName conditional field.
func (s *StarGiftUnique) SetOwnerName(value string) {
	s.Flags.Set(1)
	s.OwnerName = value
}

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

// SetOwnerAddress sets value of OwnerAddress conditional field.
func (s *StarGiftUnique) SetOwnerAddress(value string) {
	s.Flags.Set(2)
	s.OwnerAddress = value
}

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

// GetAttributes returns value of Attributes field.
func (s *StarGiftUnique) GetAttributes() (value []StarGiftAttributeClass) {
	if s == nil {
		return
	}
	return s.Attributes
}

// GetAvailabilityIssued returns value of AvailabilityIssued field.
func (s *StarGiftUnique) GetAvailabilityIssued() (value int) {
	if s == nil {
		return
	}
	return s.AvailabilityIssued
}

// GetAvailabilityTotal returns value of AvailabilityTotal field.
func (s *StarGiftUnique) GetAvailabilityTotal() (value int) {
	if s == nil {
		return
	}
	return s.AvailabilityTotal
}

// SetGiftAddress sets value of GiftAddress conditional field.
func (s *StarGiftUnique) SetGiftAddress(value string) {
	s.Flags.Set(3)
	s.GiftAddress = value
}

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

// SetResellStars sets value of ResellStars conditional field.
func (s *StarGiftUnique) SetResellStars(value int64) {
	s.Flags.Set(4)
	s.ResellStars = value
}

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

// MapAttributes returns field Attributes wrapped in StarGiftAttributeClassArray helper.
func (s *StarGiftUnique) MapAttributes() (value StarGiftAttributeClassArray) {
	return StarGiftAttributeClassArray(s.Attributes)
}

// StarGiftClassName is schema name of StarGiftClass.
const StarGiftClassName = "StarGift"

// StarGiftClass represents StarGift generic type.
//
// See https://core.telegram.org/type/StarGift for reference.
//
// Example:
//
//	g, err := tg.DecodeStarGift(buf)
//	if err != nil {
//	    panic(err)
//	}
//	switch v := g.(type) {
//	case *tg.StarGift: // starGift#c62aca28
//	case *tg.StarGiftUnique: // starGiftUnique#6411db89
//	default: panic(v)
//	}
type StarGiftClass interface {
	bin.Encoder
	bin.Decoder
	bin.BareEncoder
	bin.BareDecoder
	construct() StarGiftClass

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

	// Identifier of the gift
	GetID() (value int64)
}

// DecodeStarGift implements binary de-serialization for StarGiftClass.
func DecodeStarGift(buf *bin.Buffer) (StarGiftClass, error) {
	id, err := buf.PeekID()
	if err != nil {
		return nil, err
	}
	switch id {
	case StarGiftTypeID:
		// Decoding starGift#c62aca28.
		v := StarGift{}
		if err := v.Decode(buf); err != nil {
			return nil, fmt.Errorf("unable to decode StarGiftClass: %w", err)
		}
		return &v, nil
	case StarGiftUniqueTypeID:
		// Decoding starGiftUnique#6411db89.
		v := StarGiftUnique{}
		if err := v.Decode(buf); err != nil {
			return nil, fmt.Errorf("unable to decode StarGiftClass: %w", err)
		}
		return &v, nil
	default:
		return nil, fmt.Errorf("unable to decode StarGiftClass: %w", bin.NewUnexpectedID(id))
	}
}

// StarGift boxes the StarGiftClass providing a helper.
type StarGiftBox struct {
	StarGift StarGiftClass
}

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

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