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

// PremiumBoostsStatus represents TL type `premium.boostsStatus#4959427a`.
// Contains info about the current boost status¹ of a peer.
//
// Links:
//  1. https://core.telegram.org/api/boost
//
// See https://core.telegram.org/constructor/premium.boostsStatus for reference.
type PremiumBoostsStatus struct {
	// Flags, see TL conditional fields¹
	//
	// Links:
	//  1) https://core.telegram.org/mtproto/TL-combinators#conditional-fields
	Flags bin.Fields
	// Whether we're currently boosting this channel/supergroup, my_boost_slots will also be
	// set.
	MyBoost bool
	// The current boost level of the channel/supergroup.
	Level int
	// The number of boosts acquired so far in the current level.
	CurrentLevelBoosts int
	// Total number of boosts acquired so far.
	Boosts int
	// The number of boosts acquired from created Telegram Premium gift codes¹ and
	// giveaways²; only returned to channel/supergroup admins.
	//
	// Links:
	//  1) https://core.telegram.org/api/giveaways
	//  2) https://core.telegram.org/api/giveaways
	//
	// Use SetGiftBoosts and GetGiftBoosts helpers.
	GiftBoosts int
	// Total number of boosts needed to reach the next level; if absent, the next level isn't
	// available.
	//
	// Use SetNextLevelBoosts and GetNextLevelBoosts helpers.
	NextLevelBoosts int
	// Only returned to channel/supergroup admins: contains the approximated number of
	// Premium users subscribed to the channel/supergroup, related to the total number of
	// subscribers.
	//
	// Use SetPremiumAudience and GetPremiumAudience helpers.
	PremiumAudience StatsPercentValue
	// Boost deep link »¹ that can be used to boost the chat.
	//
	// Links:
	//  1) https://core.telegram.org/api/links#boost-links
	BoostURL string
	// A list of prepaid giveaways¹ available for the chat; only returned to
	// channel/supergroup admins.
	//
	// Links:
	//  1) https://core.telegram.org/api/giveaways
	//
	// Use SetPrepaidGiveaways and GetPrepaidGiveaways helpers.
	PrepaidGiveaways []PrepaidGiveawayClass
	// Indicates which of our boost slots¹ we've assigned to this peer (populated if
	// my_boost is set).
	//
	// Links:
	//  1) https://core.telegram.org/api/boost
	//
	// Use SetMyBoostSlots and GetMyBoostSlots helpers.
	MyBoostSlots []int
}

// PremiumBoostsStatusTypeID is TL type id of PremiumBoostsStatus.
const PremiumBoostsStatusTypeID = 0x4959427a

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

func (b *PremiumBoostsStatus) Zero() bool {
	if b == nil {
		return true
	}
	if !(b.Flags.Zero()) {
		return false
	}
	if !(b.MyBoost == false) {
		return false
	}
	if !(b.Level == 0) {
		return false
	}
	if !(b.CurrentLevelBoosts == 0) {
		return false
	}
	if !(b.Boosts == 0) {
		return false
	}
	if !(b.GiftBoosts == 0) {
		return false
	}
	if !(b.NextLevelBoosts == 0) {
		return false
	}
	if !(b.PremiumAudience.Zero()) {
		return false
	}
	if !(b.BoostURL == "") {
		return false
	}
	if !(b.PrepaidGiveaways == nil) {
		return false
	}
	if !(b.MyBoostSlots == nil) {
		return false
	}

	return true
}

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

// FillFrom fills PremiumBoostsStatus from given interface.
func (b *PremiumBoostsStatus) FillFrom(from interface {
	GetMyBoost() (value bool)
	GetLevel() (value int)
	GetCurrentLevelBoosts() (value int)
	GetBoosts() (value int)
	GetGiftBoosts() (value int, ok bool)
	GetNextLevelBoosts() (value int, ok bool)
	GetPremiumAudience() (value StatsPercentValue, ok bool)
	GetBoostURL() (value string)
	GetPrepaidGiveaways() (value []PrepaidGiveawayClass, ok bool)
	GetMyBoostSlots() (value []int, ok bool)
}) {
	b.MyBoost = from.GetMyBoost()
	b.Level = from.GetLevel()
	b.CurrentLevelBoosts = from.GetCurrentLevelBoosts()
	b.Boosts = from.GetBoosts()
	if val, ok := from.GetGiftBoosts(); ok {
		b.GiftBoosts = val
	}

	if val, ok := from.GetNextLevelBoosts(); ok {
		b.NextLevelBoosts = val
	}

	if val, ok := from.GetPremiumAudience(); ok {
		b.PremiumAudience = val
	}

	b.BoostURL = from.GetBoostURL()
	if val, ok := from.GetPrepaidGiveaways(); ok {
		b.PrepaidGiveaways = val
	}

	if val, ok := from.GetMyBoostSlots(); ok {
		b.MyBoostSlots = val
	}

}

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

// TypeName returns name of type in TL schema.
func (*PremiumBoostsStatus) TypeName() string {
	return "premium.boostsStatus"
}

// TypeInfo returns info about TL type.
func (b *PremiumBoostsStatus) TypeInfo() tdp.Type {
	typ := tdp.Type{
		Name: "premium.boostsStatus",
		ID:   PremiumBoostsStatusTypeID,
	}
	if b == nil {
		typ.Null = true
		return typ
	}
	typ.Fields = []tdp.Field{
		{
			Name:       "MyBoost",
			SchemaName: "my_boost",
			Null:       !b.Flags.Has(2),
		},
		{
			Name:       "Level",
			SchemaName: "level",
		},
		{
			Name:       "CurrentLevelBoosts",
			SchemaName: "current_level_boosts",
		},
		{
			Name:       "Boosts",
			SchemaName: "boosts",
		},
		{
			Name:       "GiftBoosts",
			SchemaName: "gift_boosts",
			Null:       !b.Flags.Has(4),
		},
		{
			Name:       "NextLevelBoosts",
			SchemaName: "next_level_boosts",
			Null:       !b.Flags.Has(0),
		},
		{
			Name:       "PremiumAudience",
			SchemaName: "premium_audience",
			Null:       !b.Flags.Has(1),
		},
		{
			Name:       "BoostURL",
			SchemaName: "boost_url",
		},
		{
			Name:       "PrepaidGiveaways",
			SchemaName: "prepaid_giveaways",
			Null:       !b.Flags.Has(3),
		},
		{
			Name:       "MyBoostSlots",
			SchemaName: "my_boost_slots",
			Null:       !b.Flags.Has(2),
		},
	}
	return typ
}

// SetFlags sets flags for non-zero fields.
func (b *PremiumBoostsStatus) SetFlags() {
	if !(b.MyBoost == false) {
		b.Flags.Set(2)
	}
	if !(b.GiftBoosts == 0) {
		b.Flags.Set(4)
	}
	if !(b.NextLevelBoosts == 0) {
		b.Flags.Set(0)
	}
	if !(b.PremiumAudience.Zero()) {
		b.Flags.Set(1)
	}
	if !(b.PrepaidGiveaways == nil) {
		b.Flags.Set(3)
	}
	if !(b.MyBoostSlots == nil) {
		b.Flags.Set(2)
	}
}

// Encode implements bin.Encoder.
func (b *PremiumBoostsStatus) Encode(buf *bin.Buffer) error {
	if b == nil {
		return fmt.Errorf("can't encode premium.boostsStatus#4959427a as nil")
	}
	buf.PutID(PremiumBoostsStatusTypeID)
	return b.EncodeBare(buf)
}

// EncodeBare implements bin.BareEncoder.
func (b *PremiumBoostsStatus) EncodeBare(buf *bin.Buffer) error {
	if b == nil {
		return fmt.Errorf("can't encode premium.boostsStatus#4959427a as nil")
	}
	b.SetFlags()
	if err := b.Flags.Encode(buf); err != nil {
		return fmt.Errorf("unable to encode premium.boostsStatus#4959427a: field flags: %w", err)
	}
	buf.PutInt(b.Level)
	buf.PutInt(b.CurrentLevelBoosts)
	buf.PutInt(b.Boosts)
	if b.Flags.Has(4) {
		buf.PutInt(b.GiftBoosts)
	}
	if b.Flags.Has(0) {
		buf.PutInt(b.NextLevelBoosts)
	}
	if b.Flags.Has(1) {
		if err := b.PremiumAudience.Encode(buf); err != nil {
			return fmt.Errorf("unable to encode premium.boostsStatus#4959427a: field premium_audience: %w", err)
		}
	}
	buf.PutString(b.BoostURL)
	if b.Flags.Has(3) {
		buf.PutVectorHeader(len(b.PrepaidGiveaways))
		for idx, v := range b.PrepaidGiveaways {
			if v == nil {
				return fmt.Errorf("unable to encode premium.boostsStatus#4959427a: field prepaid_giveaways element with index %d is nil", idx)
			}
			if err := v.Encode(buf); err != nil {
				return fmt.Errorf("unable to encode premium.boostsStatus#4959427a: field prepaid_giveaways element with index %d: %w", idx, err)
			}
		}
	}
	if b.Flags.Has(2) {
		buf.PutVectorHeader(len(b.MyBoostSlots))
		for _, v := range b.MyBoostSlots {
			buf.PutInt(v)
		}
	}
	return nil
}

// Decode implements bin.Decoder.
func (b *PremiumBoostsStatus) Decode(buf *bin.Buffer) error {
	if b == nil {
		return fmt.Errorf("can't decode premium.boostsStatus#4959427a to nil")
	}
	if err := buf.ConsumeID(PremiumBoostsStatusTypeID); err != nil {
		return fmt.Errorf("unable to decode premium.boostsStatus#4959427a: %w", err)
	}
	return b.DecodeBare(buf)
}

// DecodeBare implements bin.BareDecoder.
func (b *PremiumBoostsStatus) DecodeBare(buf *bin.Buffer) error {
	if b == nil {
		return fmt.Errorf("can't decode premium.boostsStatus#4959427a to nil")
	}
	{
		if err := b.Flags.Decode(buf); err != nil {
			return fmt.Errorf("unable to decode premium.boostsStatus#4959427a: field flags: %w", err)
		}
	}
	b.MyBoost = b.Flags.Has(2)
	{
		value, err := buf.Int()
		if err != nil {
			return fmt.Errorf("unable to decode premium.boostsStatus#4959427a: field level: %w", err)
		}
		b.Level = value
	}
	{
		value, err := buf.Int()
		if err != nil {
			return fmt.Errorf("unable to decode premium.boostsStatus#4959427a: field current_level_boosts: %w", err)
		}
		b.CurrentLevelBoosts = value
	}
	{
		value, err := buf.Int()
		if err != nil {
			return fmt.Errorf("unable to decode premium.boostsStatus#4959427a: field boosts: %w", err)
		}
		b.Boosts = value
	}
	if b.Flags.Has(4) {
		value, err := buf.Int()
		if err != nil {
			return fmt.Errorf("unable to decode premium.boostsStatus#4959427a: field gift_boosts: %w", err)
		}
		b.GiftBoosts = value
	}
	if b.Flags.Has(0) {
		value, err := buf.Int()
		if err != nil {
			return fmt.Errorf("unable to decode premium.boostsStatus#4959427a: field next_level_boosts: %w", err)
		}
		b.NextLevelBoosts = value
	}
	if b.Flags.Has(1) {
		if err := b.PremiumAudience.Decode(buf); err != nil {
			return fmt.Errorf("unable to decode premium.boostsStatus#4959427a: field premium_audience: %w", err)
		}
	}
	{
		value, err := buf.String()
		if err != nil {
			return fmt.Errorf("unable to decode premium.boostsStatus#4959427a: field boost_url: %w", err)
		}
		b.BoostURL = value
	}
	if b.Flags.Has(3) {
		headerLen, err := buf.VectorHeader()
		if err != nil {
			return fmt.Errorf("unable to decode premium.boostsStatus#4959427a: field prepaid_giveaways: %w", err)
		}

		if headerLen > 0 {
			b.PrepaidGiveaways = make([]PrepaidGiveawayClass, 0, headerLen%bin.PreallocateLimit)
		}
		for idx := 0; idx < headerLen; idx++ {
			value, err := DecodePrepaidGiveaway(buf)
			if err != nil {
				return fmt.Errorf("unable to decode premium.boostsStatus#4959427a: field prepaid_giveaways: %w", err)
			}
			b.PrepaidGiveaways = append(b.PrepaidGiveaways, value)
		}
	}
	if b.Flags.Has(2) {
		headerLen, err := buf.VectorHeader()
		if err != nil {
			return fmt.Errorf("unable to decode premium.boostsStatus#4959427a: field my_boost_slots: %w", err)
		}

		if headerLen > 0 {
			b.MyBoostSlots = make([]int, 0, headerLen%bin.PreallocateLimit)
		}
		for idx := 0; idx < headerLen; idx++ {
			value, err := buf.Int()
			if err != nil {
				return fmt.Errorf("unable to decode premium.boostsStatus#4959427a: field my_boost_slots: %w", err)
			}
			b.MyBoostSlots = append(b.MyBoostSlots, value)
		}
	}
	return nil
}

// SetMyBoost sets value of MyBoost conditional field.
func (b *PremiumBoostsStatus) SetMyBoost(value bool) {
	if value {
		b.Flags.Set(2)
		b.MyBoost = true
	} else {
		b.Flags.Unset(2)
		b.MyBoost = false
	}
}

// GetMyBoost returns value of MyBoost conditional field.
func (b *PremiumBoostsStatus) GetMyBoost() (value bool) {
	if b == nil {
		return
	}
	return b.Flags.Has(2)
}

// GetLevel returns value of Level field.
func (b *PremiumBoostsStatus) GetLevel() (value int) {
	if b == nil {
		return
	}
	return b.Level
}

// GetCurrentLevelBoosts returns value of CurrentLevelBoosts field.
func (b *PremiumBoostsStatus) GetCurrentLevelBoosts() (value int) {
	if b == nil {
		return
	}
	return b.CurrentLevelBoosts
}

// GetBoosts returns value of Boosts field.
func (b *PremiumBoostsStatus) GetBoosts() (value int) {
	if b == nil {
		return
	}
	return b.Boosts
}

// SetGiftBoosts sets value of GiftBoosts conditional field.
func (b *PremiumBoostsStatus) SetGiftBoosts(value int) {
	b.Flags.Set(4)
	b.GiftBoosts = value
}

// GetGiftBoosts returns value of GiftBoosts conditional field and
// boolean which is true if field was set.
func (b *PremiumBoostsStatus) GetGiftBoosts() (value int, ok bool) {
	if b == nil {
		return
	}
	if !b.Flags.Has(4) {
		return value, false
	}
	return b.GiftBoosts, true
}

// SetNextLevelBoosts sets value of NextLevelBoosts conditional field.
func (b *PremiumBoostsStatus) SetNextLevelBoosts(value int) {
	b.Flags.Set(0)
	b.NextLevelBoosts = value
}

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

// SetPremiumAudience sets value of PremiumAudience conditional field.
func (b *PremiumBoostsStatus) SetPremiumAudience(value StatsPercentValue) {
	b.Flags.Set(1)
	b.PremiumAudience = value
}

// GetPremiumAudience returns value of PremiumAudience conditional field and
// boolean which is true if field was set.
func (b *PremiumBoostsStatus) GetPremiumAudience() (value StatsPercentValue, ok bool) {
	if b == nil {
		return
	}
	if !b.Flags.Has(1) {
		return value, false
	}
	return b.PremiumAudience, true
}

// GetBoostURL returns value of BoostURL field.
func (b *PremiumBoostsStatus) GetBoostURL() (value string) {
	if b == nil {
		return
	}
	return b.BoostURL
}

// SetPrepaidGiveaways sets value of PrepaidGiveaways conditional field.
func (b *PremiumBoostsStatus) SetPrepaidGiveaways(value []PrepaidGiveawayClass) {
	b.Flags.Set(3)
	b.PrepaidGiveaways = value
}

// GetPrepaidGiveaways returns value of PrepaidGiveaways conditional field and
// boolean which is true if field was set.
func (b *PremiumBoostsStatus) GetPrepaidGiveaways() (value []PrepaidGiveawayClass, ok bool) {
	if b == nil {
		return
	}
	if !b.Flags.Has(3) {
		return value, false
	}
	return b.PrepaidGiveaways, true
}

// SetMyBoostSlots sets value of MyBoostSlots conditional field.
func (b *PremiumBoostsStatus) SetMyBoostSlots(value []int) {
	b.Flags.Set(2)
	b.MyBoostSlots = value
}

// GetMyBoostSlots returns value of MyBoostSlots conditional field and
// boolean which is true if field was set.
func (b *PremiumBoostsStatus) GetMyBoostSlots() (value []int, ok bool) {
	if b == nil {
		return
	}
	if !b.Flags.Has(2) {
		return value, false
	}
	return b.MyBoostSlots, true
}

// MapPrepaidGiveaways returns field PrepaidGiveaways wrapped in PrepaidGiveawayClassArray helper.
func (b *PremiumBoostsStatus) MapPrepaidGiveaways() (value PrepaidGiveawayClassArray, ok bool) {
	if !b.Flags.Has(3) {
		return value, false
	}
	return PrepaidGiveawayClassArray(b.PrepaidGiveaways), true
}
