// Code generated by go-bluetooth generator DO NOT EDIT.

package obex

import (
	"sync"

	"github.com/godbus/dbus/v5"
	"github.com/muka/go-bluetooth/bluez"
	"github.com/muka/go-bluetooth/props"
	"github.com/muka/go-bluetooth/util"
)

var PhonebookAccess1Interface = "org.bluez.obex.PhonebookAccess1"

// NewPhonebookAccess1 create a new instance of PhonebookAccess1
//
// Args:
// - objectPath: [Session object path]
func NewPhonebookAccess1(objectPath dbus.ObjectPath) (*PhonebookAccess1, error) {
	a := new(PhonebookAccess1)
	a.client = bluez.NewClient(
		&bluez.Config{
			Name:  "org.bluez.obex",
			Iface: PhonebookAccess1Interface,
			Path:  dbus.ObjectPath(objectPath),
			Bus:   bluez.SystemBus,
		},
	)
	a.Properties = new(PhonebookAccess1Properties)

	_, err := a.GetProperties()
	if err != nil {
		return nil, err
	}
	return a, nil
}

/*
PhonebookAccess1 Phonebook Access hierarchy

*/
type PhonebookAccess1 struct {
	client                 *bluez.Client
	propertiesSignal       chan *dbus.Signal
	objectManagerSignal    chan *dbus.Signal
	objectManager          *bluez.ObjectManager
	Properties             *PhonebookAccess1Properties
	watchPropertiesChannel chan *dbus.Signal
}

// PhonebookAccess1Properties contains the exposed properties of an interface
type PhonebookAccess1Properties struct {
	lock sync.RWMutex `dbus:"ignore"`

	/*
		DatabaseIdentifier 128 bits persistent database identifier.

				Possible values: 32-character hexadecimal such
				as A1A2A3A4B1B2C1C2D1D2E1E2E3E4E5E6
	*/
	DatabaseIdentifier string

	/*
		FixedImageSize Indicate support for fixed image size.

				Possible values: True if image is JPEG 300x300 pixels
				otherwise False.
	*/
	FixedImageSize bool

	/*
		Folder Current folder.
	*/
	Folder string

	/*
		PrimaryCounter 128 bits primary version counter.

				Possible values: 32-character hexadecimal such
				as A1A2A3A4B1B2C1C2D1D2E1E2E3E4E5E6
	*/
	PrimaryCounter string

	/*
		SecondaryCounter 128 bits secondary version counter.

				Possible values: 32-character hexadecimal such
				as A1A2A3A4B1B2C1C2D1D2E1E2E3E4E5E6
	*/
	SecondaryCounter string
}

//Lock access to properties
func (p *PhonebookAccess1Properties) Lock() {
	p.lock.Lock()
}

//Unlock access to properties
func (p *PhonebookAccess1Properties) Unlock() {
	p.lock.Unlock()
}

// SetDatabaseIdentifier set DatabaseIdentifier value
func (a *PhonebookAccess1) SetDatabaseIdentifier(v string) error {
	return a.SetProperty("DatabaseIdentifier", v)
}

// GetDatabaseIdentifier get DatabaseIdentifier value
func (a *PhonebookAccess1) GetDatabaseIdentifier() (string, error) {
	v, err := a.GetProperty("DatabaseIdentifier")
	if err != nil {
		return "", err
	}
	return v.Value().(string), nil
}

// SetFixedImageSize set FixedImageSize value
func (a *PhonebookAccess1) SetFixedImageSize(v bool) error {
	return a.SetProperty("FixedImageSize", v)
}

// GetFixedImageSize get FixedImageSize value
func (a *PhonebookAccess1) GetFixedImageSize() (bool, error) {
	v, err := a.GetProperty("FixedImageSize")
	if err != nil {
		return false, err
	}
	return v.Value().(bool), nil
}

// SetFolder set Folder value
func (a *PhonebookAccess1) SetFolder(v string) error {
	return a.SetProperty("Folder", v)
}

// GetFolder get Folder value
func (a *PhonebookAccess1) GetFolder() (string, error) {
	v, err := a.GetProperty("Folder")
	if err != nil {
		return "", err
	}
	return v.Value().(string), nil
}

// SetPrimaryCounter set PrimaryCounter value
func (a *PhonebookAccess1) SetPrimaryCounter(v string) error {
	return a.SetProperty("PrimaryCounter", v)
}

// GetPrimaryCounter get PrimaryCounter value
func (a *PhonebookAccess1) GetPrimaryCounter() (string, error) {
	v, err := a.GetProperty("PrimaryCounter")
	if err != nil {
		return "", err
	}
	return v.Value().(string), nil
}

// SetSecondaryCounter set SecondaryCounter value
func (a *PhonebookAccess1) SetSecondaryCounter(v string) error {
	return a.SetProperty("SecondaryCounter", v)
}

// GetSecondaryCounter get SecondaryCounter value
func (a *PhonebookAccess1) GetSecondaryCounter() (string, error) {
	v, err := a.GetProperty("SecondaryCounter")
	if err != nil {
		return "", err
	}
	return v.Value().(string), nil
}

// Close the connection
func (a *PhonebookAccess1) Close() {
	a.unregisterPropertiesSignal()
	a.client.Disconnect()
}

// Path return PhonebookAccess1 object path
func (a *PhonebookAccess1) Path() dbus.ObjectPath {
	return a.client.Config.Path
}

// Client return PhonebookAccess1 dbus client
func (a *PhonebookAccess1) Client() *bluez.Client {
	return a.client
}

// Interface return PhonebookAccess1 interface
func (a *PhonebookAccess1) Interface() string {
	return a.client.Config.Iface
}

// GetObjectManagerSignal return a channel for receiving updates from the ObjectManager
func (a *PhonebookAccess1) GetObjectManagerSignal() (chan *dbus.Signal, func(), error) {

	if a.objectManagerSignal == nil {
		if a.objectManager == nil {
			om, err := bluez.GetObjectManager()
			if err != nil {
				return nil, nil, err
			}
			a.objectManager = om
		}

		s, err := a.objectManager.Register()
		if err != nil {
			return nil, nil, err
		}
		a.objectManagerSignal = s
	}

	cancel := func() {
		if a.objectManagerSignal == nil {
			return
		}
		a.objectManagerSignal <- nil
		a.objectManager.Unregister(a.objectManagerSignal)
		a.objectManagerSignal = nil
	}

	return a.objectManagerSignal, cancel, nil
}

// ToMap convert a PhonebookAccess1Properties to map
func (a *PhonebookAccess1Properties) ToMap() (map[string]interface{}, error) {
	return props.ToMap(a), nil
}

// FromMap convert a map to an PhonebookAccess1Properties
func (a *PhonebookAccess1Properties) FromMap(props map[string]interface{}) (*PhonebookAccess1Properties, error) {
	props1 := map[string]dbus.Variant{}
	for k, val := range props {
		props1[k] = dbus.MakeVariant(val)
	}
	return a.FromDBusMap(props1)
}

// FromDBusMap convert a map to an PhonebookAccess1Properties
func (a *PhonebookAccess1Properties) FromDBusMap(props map[string]dbus.Variant) (*PhonebookAccess1Properties, error) {
	s := new(PhonebookAccess1Properties)
	err := util.MapToStruct(s, props)
	return s, err
}

// ToProps return the properties interface
func (a *PhonebookAccess1) ToProps() bluez.Properties {
	return a.Properties
}

// GetWatchPropertiesChannel return the dbus channel to receive properties interface
func (a *PhonebookAccess1) GetWatchPropertiesChannel() chan *dbus.Signal {
	return a.watchPropertiesChannel
}

// SetWatchPropertiesChannel set the dbus channel to receive properties interface
func (a *PhonebookAccess1) SetWatchPropertiesChannel(c chan *dbus.Signal) {
	a.watchPropertiesChannel = c
}

// GetProperties load all available properties
func (a *PhonebookAccess1) GetProperties() (*PhonebookAccess1Properties, error) {
	a.Properties.Lock()
	err := a.client.GetProperties(a.Properties)
	a.Properties.Unlock()
	return a.Properties, err
}

// SetProperty set a property
func (a *PhonebookAccess1) SetProperty(name string, value interface{}) error {
	return a.client.SetProperty(name, value)
}

// GetProperty get a property
func (a *PhonebookAccess1) GetProperty(name string) (dbus.Variant, error) {
	return a.client.GetProperty(name)
}

// GetPropertiesSignal return a channel for receiving udpdates on property changes
func (a *PhonebookAccess1) GetPropertiesSignal() (chan *dbus.Signal, error) {

	if a.propertiesSignal == nil {
		s, err := a.client.Register(a.client.Config.Path, bluez.PropertiesInterface)
		if err != nil {
			return nil, err
		}
		a.propertiesSignal = s
	}

	return a.propertiesSignal, nil
}

// Unregister for changes signalling
func (a *PhonebookAccess1) unregisterPropertiesSignal() {
	if a.propertiesSignal != nil {
		a.propertiesSignal <- nil
		a.propertiesSignal = nil
	}
}

// WatchProperties updates on property changes
func (a *PhonebookAccess1) WatchProperties() (chan *bluez.PropertyChanged, error) {
	return bluez.WatchProperties(a)
}

func (a *PhonebookAccess1) UnwatchProperties(ch chan *bluez.PropertyChanged) error {
	return bluez.UnwatchProperties(a, ch)
}

/*
Select 			Select the phonebook object for other operations. Should
			be call before all the other operations.
			location : Where the phonebook is stored, possible
			inputs :
				"int" ( "internal" which is default )
				"sim" ( "sim1" )
				"sim2"
				...
			phonebook : Possible inputs :
				"pb" :	phonebook for the saved contacts
				"ich":	incoming call history
				"och":	outgoing call history
				"mch":	missing call history
				"cch":	combination of ich och mch
				"spd":	speed dials entry ( only for "internal" )
				"fav":	favorites entry ( only for "internal" )
			Possible errors: org.bluez.obex.Error.InvalidArguments
					 org.bluez.obex.Error.Failed

*/
func (a *PhonebookAccess1) Select(location string, phonebook string) error {
	return a.client.Call("Select", 0, location, phonebook).Store()
}

/*
PullAll 			Return the entire phonebook object from the PSE server
			in plain string with vcard format, and store it in
			a local file.
			If an empty target file is given, a name will be
			automatically calculated for the temporary file.
			The returned path represents the newly created transfer,
			which should be used to find out if the content has been
			successfully transferred or if the operation fails.
			The properties of this transfer are also returned along
			with the object path, to avoid a call to GetProperties.
			Possible filters: Format, Order, Offset, MaxCount and
			Fields
			Possible errors: org.bluez.obex.Error.InvalidArguments
					org.bluez.obex.Forbidden

*/
func (a *PhonebookAccess1) PullAll(targetfile string, filters map[string]interface{}) (dbus.ObjectPath, map[string]interface{}, error) {
	var val0 dbus.ObjectPath
	var val1 map[string]interface{}
	err := a.client.Call("PullAll", 0, targetfile, filters).Store(&val0, &val1)
	return val0, val1, err
}

/*
List 			Return an array of vcard-listing data where every entry
			consists of a pair of strings containing the vcard
			handle and the contact name. For example:
				"1.vcf" : "John"
			Possible filters: Order, Offset and MaxCount
			Possible errors: org.bluez.obex.Error.InvalidArguments
					 org.bluez.obex.Forbidden

*/
func (a *PhonebookAccess1) List(filters map[string]interface{}) ([]VCardItem, error) {
	val0 := []VCardItem{}
	err := a.client.Call("List", 0, filters).Store(&val0)
	return val0, err
}

/*
Pull 			Given a vcard handle, retrieve the vcard in the current
			phonebook object and store it in a local file.
			If an empty target file is given, a name will be
			automatically calculated for the temporary file.
			The returned path represents the newly created transfer,
			which should be used to find out if the content has been
			successfully transferred or if the operation fails.
			The properties of this transfer are also returned along
			with the object path, to avoid a call to GetProperties.
			Possbile filters: Format and Fields
			Possible errors: org.bluez.obex.Error.InvalidArguments
					 org.bluez.obex.Error.Forbidden
					 org.bluez.obex.Error.Failed

*/
func (a *PhonebookAccess1) Pull(vcard string, targetfile string, filters map[string]interface{}) (dbus.ObjectPath, map[string]interface{}, error) {
	var val0 dbus.ObjectPath
	var val1 map[string]interface{}
	err := a.client.Call("Pull", 0, vcard, targetfile, filters).Store(&val0, &val1)
	return val0, val1, err
}

/*
Search 			Search for entries matching the given condition and
			return an array of vcard-listing data where every entry
			consists of a pair of strings containing the vcard
			handle and the contact name.
			vcard : name paired string match the search condition.
			field : the field in the vcard to search with
				{ "name" (default) | "number" | "sound" }
			value : the string value to search for
			Possible filters: Order, Offset and MaxCount
			Possible errors: org.bluez.obex.Error.InvalidArguments
					 org.bluez.obex.Error.Forbidden
					 org.bluez.obex.Error.Failed

*/
func (a *PhonebookAccess1) Search(field string, value string, filters map[string]interface{}) ([]VCardItem, error) {
	val0 := []VCardItem{}
	err := a.client.Call("Search", 0, field, value, filters).Store(&val0)
	return val0, err
}

/*
GetSize 			Return the number of entries in the selected phonebook
			object that are actually used (i.e. indexes that
			correspond to non-NULL entries).
			Possible errors: org.bluez.obex.Error.Forbidden
					 org.bluez.obex.Error.Failed

*/
func (a *PhonebookAccess1) GetSize() (uint16, error) {
	var val0 uint16
	err := a.client.Call("GetSize", 0).Store(&val0)
	return val0, err
}

/*
UpdateVersion 			Attempt to update PrimaryCounter and SecondaryCounter.
			Possible errors: org.bluez.obex.Error.NotSupported
					 org.bluez.obex.Error.Forbidden
					 org.bluez.obex.Error.Failed

*/
func (a *PhonebookAccess1) UpdateVersion() error {
	return a.client.Call("UpdateVersion", 0).Store()
}

/*
ListFilterFields 			Return All Available fields that can be used in Fields
			filter.
			Possible errors: None

*/
func (a *PhonebookAccess1) ListFilterFields() ([]string, error) {
	val0 := []string{}
	err := a.client.Call("ListFilterFields", 0).Store(&val0)
	return val0, err
}
