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

package battery

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 BatteryProviderManager1Interface = "org.bluez.BatteryProviderManager1"

// NewBatteryProviderManager1 create a new instance of BatteryProviderManager1
//
// Args:
// - objectPath: /org/bluez/{hci0,hci1,...}
func NewBatteryProviderManager1(objectPath dbus.ObjectPath) (*BatteryProviderManager1, error) {
	a := new(BatteryProviderManager1)
	a.client = bluez.NewClient(
		&bluez.Config{
			Name:  "org.bluez",
			Iface: BatteryProviderManager1Interface,
			Path:  dbus.ObjectPath(objectPath),
			Bus:   bluez.SystemBus,
		},
	)
	a.Properties = new(BatteryProviderManager1Properties)

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

/*
BatteryProviderManager1 Battery Provider Manager hierarchy
A battery provider starts by registering itself as a battery provider with the
RegisterBatteryProvider method passing an object path as the provider ID. Then,
it can start exposing org.bluez.BatteryProvider1 objects having the path
starting with the given provider ID. It can also remove objects at any time.
The objects and their properties exposed by battery providers will be reflected
on org.bluez.Battery1 interface.

BlueZ will stop monitoring these exposed and removed objects after
UnregisterBatteryProvider is called for that provider ID.

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

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

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

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

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

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

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

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

// GetObjectManagerSignal return a channel for receiving updates from the ObjectManager
func (a *BatteryProviderManager1) 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 BatteryProviderManager1Properties to map
func (a *BatteryProviderManager1Properties) ToMap() (map[string]interface{}, error) {
	return props.ToMap(a), nil
}

// FromMap convert a map to an BatteryProviderManager1Properties
func (a *BatteryProviderManager1Properties) FromMap(props map[string]interface{}) (*BatteryProviderManager1Properties, 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 BatteryProviderManager1Properties
func (a *BatteryProviderManager1Properties) FromDBusMap(props map[string]dbus.Variant) (*BatteryProviderManager1Properties, error) {
	s := new(BatteryProviderManager1Properties)
	err := util.MapToStruct(s, props)
	return s, err
}

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

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

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

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

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

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

// GetPropertiesSignal return a channel for receiving udpdates on property changes
func (a *BatteryProviderManager1) 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 *BatteryProviderManager1) unregisterPropertiesSignal() {
	if a.propertiesSignal != nil {
		a.propertiesSignal <- nil
		a.propertiesSignal = nil
	}
}

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

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

/*
RegisterBatteryProvider 			This registers a battery provider. A registered
			battery provider can then expose objects with
			org.bluez.BatteryProvider1 interface described below.

*/
func (a *BatteryProviderManager1) RegisterBatteryProvider(provider dbus.ObjectPath) error {
	return a.client.Call("RegisterBatteryProvider", 0, provider).Store()
}

/*
UnregisterBatteryProvider 			This unregisters a battery provider. After
			unregistration, the BatteryProvider1 objects provided
			by this client are ignored by BlueZ.

*/
func (a *BatteryProviderManager1) UnregisterBatteryProvider(provider dbus.ObjectPath) error {
	return a.client.Call("UnregisterBatteryProvider", 0, provider).Store()
}
