// Code generated by gotdgen, DO NOT EDIT.

package tg

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

	"go.uber.org/multierr"

	"github.com/gotd/td/bin"
	"github.com/gotd/td/tdjson"
	"github.com/gotd/td/tdp"
	"github.com/gotd/td/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{}
)

// PeerSettings represents TL type `peerSettings#a518110d`.
// List of actions that are possible when interacting with this user, to be shown as
// suggested actions in the chat bar
//
// See https://core.telegram.org/constructor/peerSettings for reference.
type PeerSettings struct {
	// Flags, see TL conditional fields¹
	//
	// Links:
	//  1) https://core.telegram.org/mtproto/TL-combinators#conditional-fields
	Flags bin.Fields
	// Whether we can still report the user for spam
	ReportSpam bool
	// Whether we can add the user as contact
	AddContact bool
	// Whether we can block the user
	BlockContact bool
	// Whether we can share the user's contact
	ShareContact bool
	// Whether a special exception for contacts is needed
	NeedContactsException bool
	// Whether we can report a geogroup as irrelevant for this location
	ReportGeo bool
	// Whether this peer was automatically archived according to privacy settings¹ and can
	// be unarchived
	//
	// Links:
	//  1) https://core.telegram.org/constructor/globalPrivacySettings
	Autoarchived bool
	// If set, this is a recently created group chat to which new members can be invited
	InviteMembers bool
	// This flag is set if request_chat_title and request_chat_date fields are set and the
	// join request »¹ is related to a channel (otherwise if only the request fields are
	// set, the join request »² is related to a chat).
	//
	// Links:
	//  1) https://core.telegram.org/api/invites#join-requests
	//  2) https://core.telegram.org/api/invites#join-requests
	RequestChatBroadcast bool
	// Distance in meters between us and this peer
	//
	// Use SetGeoDistance and GetGeoDistance helpers.
	GeoDistance int
	// If set, this is a private chat with an administrator of a chat or channel to which the
	// user sent a join request, and this field contains the chat/channel's title.
	//
	// Use SetRequestChatTitle and GetRequestChatTitle helpers.
	RequestChatTitle string
	// If set, this is a private chat with an administrator of a chat or channel to which the
	// user sent a join request, and this field contains the timestamp when the join request
	// »¹ was sent.
	//
	// Links:
	//  1) https://core.telegram.org/api/invites#join-requests
	//
	// Use SetRequestChatDate and GetRequestChatDate helpers.
	RequestChatDate int
}

// PeerSettingsTypeID is TL type id of PeerSettings.
const PeerSettingsTypeID = 0xa518110d

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

func (p *PeerSettings) Zero() bool {
	if p == nil {
		return true
	}
	if !(p.Flags.Zero()) {
		return false
	}
	if !(p.ReportSpam == false) {
		return false
	}
	if !(p.AddContact == false) {
		return false
	}
	if !(p.BlockContact == false) {
		return false
	}
	if !(p.ShareContact == false) {
		return false
	}
	if !(p.NeedContactsException == false) {
		return false
	}
	if !(p.ReportGeo == false) {
		return false
	}
	if !(p.Autoarchived == false) {
		return false
	}
	if !(p.InviteMembers == false) {
		return false
	}
	if !(p.RequestChatBroadcast == false) {
		return false
	}
	if !(p.GeoDistance == 0) {
		return false
	}
	if !(p.RequestChatTitle == "") {
		return false
	}
	if !(p.RequestChatDate == 0) {
		return false
	}

	return true
}

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

// FillFrom fills PeerSettings from given interface.
func (p *PeerSettings) FillFrom(from interface {
	GetReportSpam() (value bool)
	GetAddContact() (value bool)
	GetBlockContact() (value bool)
	GetShareContact() (value bool)
	GetNeedContactsException() (value bool)
	GetReportGeo() (value bool)
	GetAutoarchived() (value bool)
	GetInviteMembers() (value bool)
	GetRequestChatBroadcast() (value bool)
	GetGeoDistance() (value int, ok bool)
	GetRequestChatTitle() (value string, ok bool)
	GetRequestChatDate() (value int, ok bool)
}) {
	p.ReportSpam = from.GetReportSpam()
	p.AddContact = from.GetAddContact()
	p.BlockContact = from.GetBlockContact()
	p.ShareContact = from.GetShareContact()
	p.NeedContactsException = from.GetNeedContactsException()
	p.ReportGeo = from.GetReportGeo()
	p.Autoarchived = from.GetAutoarchived()
	p.InviteMembers = from.GetInviteMembers()
	p.RequestChatBroadcast = from.GetRequestChatBroadcast()
	if val, ok := from.GetGeoDistance(); ok {
		p.GeoDistance = val
	}

	if val, ok := from.GetRequestChatTitle(); ok {
		p.RequestChatTitle = val
	}

	if val, ok := from.GetRequestChatDate(); ok {
		p.RequestChatDate = val
	}

}

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

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

// TypeInfo returns info about TL type.
func (p *PeerSettings) TypeInfo() tdp.Type {
	typ := tdp.Type{
		Name: "peerSettings",
		ID:   PeerSettingsTypeID,
	}
	if p == nil {
		typ.Null = true
		return typ
	}
	typ.Fields = []tdp.Field{
		{
			Name:       "ReportSpam",
			SchemaName: "report_spam",
			Null:       !p.Flags.Has(0),
		},
		{
			Name:       "AddContact",
			SchemaName: "add_contact",
			Null:       !p.Flags.Has(1),
		},
		{
			Name:       "BlockContact",
			SchemaName: "block_contact",
			Null:       !p.Flags.Has(2),
		},
		{
			Name:       "ShareContact",
			SchemaName: "share_contact",
			Null:       !p.Flags.Has(3),
		},
		{
			Name:       "NeedContactsException",
			SchemaName: "need_contacts_exception",
			Null:       !p.Flags.Has(4),
		},
		{
			Name:       "ReportGeo",
			SchemaName: "report_geo",
			Null:       !p.Flags.Has(5),
		},
		{
			Name:       "Autoarchived",
			SchemaName: "autoarchived",
			Null:       !p.Flags.Has(7),
		},
		{
			Name:       "InviteMembers",
			SchemaName: "invite_members",
			Null:       !p.Flags.Has(8),
		},
		{
			Name:       "RequestChatBroadcast",
			SchemaName: "request_chat_broadcast",
			Null:       !p.Flags.Has(10),
		},
		{
			Name:       "GeoDistance",
			SchemaName: "geo_distance",
			Null:       !p.Flags.Has(6),
		},
		{
			Name:       "RequestChatTitle",
			SchemaName: "request_chat_title",
			Null:       !p.Flags.Has(9),
		},
		{
			Name:       "RequestChatDate",
			SchemaName: "request_chat_date",
			Null:       !p.Flags.Has(9),
		},
	}
	return typ
}

// SetFlags sets flags for non-zero fields.
func (p *PeerSettings) SetFlags() {
	if !(p.ReportSpam == false) {
		p.Flags.Set(0)
	}
	if !(p.AddContact == false) {
		p.Flags.Set(1)
	}
	if !(p.BlockContact == false) {
		p.Flags.Set(2)
	}
	if !(p.ShareContact == false) {
		p.Flags.Set(3)
	}
	if !(p.NeedContactsException == false) {
		p.Flags.Set(4)
	}
	if !(p.ReportGeo == false) {
		p.Flags.Set(5)
	}
	if !(p.Autoarchived == false) {
		p.Flags.Set(7)
	}
	if !(p.InviteMembers == false) {
		p.Flags.Set(8)
	}
	if !(p.RequestChatBroadcast == false) {
		p.Flags.Set(10)
	}
	if !(p.GeoDistance == 0) {
		p.Flags.Set(6)
	}
	if !(p.RequestChatTitle == "") {
		p.Flags.Set(9)
	}
	if !(p.RequestChatDate == 0) {
		p.Flags.Set(9)
	}
}

// Encode implements bin.Encoder.
func (p *PeerSettings) Encode(b *bin.Buffer) error {
	if p == nil {
		return fmt.Errorf("can't encode peerSettings#a518110d as nil")
	}
	b.PutID(PeerSettingsTypeID)
	return p.EncodeBare(b)
}

// EncodeBare implements bin.BareEncoder.
func (p *PeerSettings) EncodeBare(b *bin.Buffer) error {
	if p == nil {
		return fmt.Errorf("can't encode peerSettings#a518110d as nil")
	}
	p.SetFlags()
	if err := p.Flags.Encode(b); err != nil {
		return fmt.Errorf("unable to encode peerSettings#a518110d: field flags: %w", err)
	}
	if p.Flags.Has(6) {
		b.PutInt(p.GeoDistance)
	}
	if p.Flags.Has(9) {
		b.PutString(p.RequestChatTitle)
	}
	if p.Flags.Has(9) {
		b.PutInt(p.RequestChatDate)
	}
	return nil
}

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

// DecodeBare implements bin.BareDecoder.
func (p *PeerSettings) DecodeBare(b *bin.Buffer) error {
	if p == nil {
		return fmt.Errorf("can't decode peerSettings#a518110d to nil")
	}
	{
		if err := p.Flags.Decode(b); err != nil {
			return fmt.Errorf("unable to decode peerSettings#a518110d: field flags: %w", err)
		}
	}
	p.ReportSpam = p.Flags.Has(0)
	p.AddContact = p.Flags.Has(1)
	p.BlockContact = p.Flags.Has(2)
	p.ShareContact = p.Flags.Has(3)
	p.NeedContactsException = p.Flags.Has(4)
	p.ReportGeo = p.Flags.Has(5)
	p.Autoarchived = p.Flags.Has(7)
	p.InviteMembers = p.Flags.Has(8)
	p.RequestChatBroadcast = p.Flags.Has(10)
	if p.Flags.Has(6) {
		value, err := b.Int()
		if err != nil {
			return fmt.Errorf("unable to decode peerSettings#a518110d: field geo_distance: %w", err)
		}
		p.GeoDistance = value
	}
	if p.Flags.Has(9) {
		value, err := b.String()
		if err != nil {
			return fmt.Errorf("unable to decode peerSettings#a518110d: field request_chat_title: %w", err)
		}
		p.RequestChatTitle = value
	}
	if p.Flags.Has(9) {
		value, err := b.Int()
		if err != nil {
			return fmt.Errorf("unable to decode peerSettings#a518110d: field request_chat_date: %w", err)
		}
		p.RequestChatDate = value
	}
	return nil
}

// SetReportSpam sets value of ReportSpam conditional field.
func (p *PeerSettings) SetReportSpam(value bool) {
	if value {
		p.Flags.Set(0)
		p.ReportSpam = true
	} else {
		p.Flags.Unset(0)
		p.ReportSpam = false
	}
}

// GetReportSpam returns value of ReportSpam conditional field.
func (p *PeerSettings) GetReportSpam() (value bool) {
	if p == nil {
		return
	}
	return p.Flags.Has(0)
}

// SetAddContact sets value of AddContact conditional field.
func (p *PeerSettings) SetAddContact(value bool) {
	if value {
		p.Flags.Set(1)
		p.AddContact = true
	} else {
		p.Flags.Unset(1)
		p.AddContact = false
	}
}

// GetAddContact returns value of AddContact conditional field.
func (p *PeerSettings) GetAddContact() (value bool) {
	if p == nil {
		return
	}
	return p.Flags.Has(1)
}

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

// GetBlockContact returns value of BlockContact conditional field.
func (p *PeerSettings) GetBlockContact() (value bool) {
	if p == nil {
		return
	}
	return p.Flags.Has(2)
}

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

// GetShareContact returns value of ShareContact conditional field.
func (p *PeerSettings) GetShareContact() (value bool) {
	if p == nil {
		return
	}
	return p.Flags.Has(3)
}

// SetNeedContactsException sets value of NeedContactsException conditional field.
func (p *PeerSettings) SetNeedContactsException(value bool) {
	if value {
		p.Flags.Set(4)
		p.NeedContactsException = true
	} else {
		p.Flags.Unset(4)
		p.NeedContactsException = false
	}
}

// GetNeedContactsException returns value of NeedContactsException conditional field.
func (p *PeerSettings) GetNeedContactsException() (value bool) {
	if p == nil {
		return
	}
	return p.Flags.Has(4)
}

// SetReportGeo sets value of ReportGeo conditional field.
func (p *PeerSettings) SetReportGeo(value bool) {
	if value {
		p.Flags.Set(5)
		p.ReportGeo = true
	} else {
		p.Flags.Unset(5)
		p.ReportGeo = false
	}
}

// GetReportGeo returns value of ReportGeo conditional field.
func (p *PeerSettings) GetReportGeo() (value bool) {
	if p == nil {
		return
	}
	return p.Flags.Has(5)
}

// SetAutoarchived sets value of Autoarchived conditional field.
func (p *PeerSettings) SetAutoarchived(value bool) {
	if value {
		p.Flags.Set(7)
		p.Autoarchived = true
	} else {
		p.Flags.Unset(7)
		p.Autoarchived = false
	}
}

// GetAutoarchived returns value of Autoarchived conditional field.
func (p *PeerSettings) GetAutoarchived() (value bool) {
	if p == nil {
		return
	}
	return p.Flags.Has(7)
}

// SetInviteMembers sets value of InviteMembers conditional field.
func (p *PeerSettings) SetInviteMembers(value bool) {
	if value {
		p.Flags.Set(8)
		p.InviteMembers = true
	} else {
		p.Flags.Unset(8)
		p.InviteMembers = false
	}
}

// GetInviteMembers returns value of InviteMembers conditional field.
func (p *PeerSettings) GetInviteMembers() (value bool) {
	if p == nil {
		return
	}
	return p.Flags.Has(8)
}

// SetRequestChatBroadcast sets value of RequestChatBroadcast conditional field.
func (p *PeerSettings) SetRequestChatBroadcast(value bool) {
	if value {
		p.Flags.Set(10)
		p.RequestChatBroadcast = true
	} else {
		p.Flags.Unset(10)
		p.RequestChatBroadcast = false
	}
}

// GetRequestChatBroadcast returns value of RequestChatBroadcast conditional field.
func (p *PeerSettings) GetRequestChatBroadcast() (value bool) {
	if p == nil {
		return
	}
	return p.Flags.Has(10)
}

// SetGeoDistance sets value of GeoDistance conditional field.
func (p *PeerSettings) SetGeoDistance(value int) {
	p.Flags.Set(6)
	p.GeoDistance = value
}

// GetGeoDistance returns value of GeoDistance conditional field and
// boolean which is true if field was set.
func (p *PeerSettings) GetGeoDistance() (value int, ok bool) {
	if p == nil {
		return
	}
	if !p.Flags.Has(6) {
		return value, false
	}
	return p.GeoDistance, true
}

// SetRequestChatTitle sets value of RequestChatTitle conditional field.
func (p *PeerSettings) SetRequestChatTitle(value string) {
	p.Flags.Set(9)
	p.RequestChatTitle = value
}

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

// SetRequestChatDate sets value of RequestChatDate conditional field.
func (p *PeerSettings) SetRequestChatDate(value int) {
	p.Flags.Set(9)
	p.RequestChatDate = value
}

// GetRequestChatDate returns value of RequestChatDate conditional field and
// boolean which is true if field was set.
func (p *PeerSettings) GetRequestChatDate() (value int, ok bool) {
	if p == nil {
		return
	}
	if !p.Flags.Has(9) {
		return value, false
	}
	return p.RequestChatDate, true
}
