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

package media

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 MediaPlayer1Interface = "org.bluez.MediaPlayer1"

// NewMediaPlayer1 create a new instance of MediaPlayer1
//
// Args:
// - objectPath: [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/playerX
func NewMediaPlayer1(objectPath dbus.ObjectPath) (*MediaPlayer1, error) {
	a := new(MediaPlayer1)
	a.client = bluez.NewClient(
		&bluez.Config{
			Name:  "org.bluez",
			Iface: MediaPlayer1Interface,
			Path:  dbus.ObjectPath(objectPath),
			Bus:   bluez.SystemBus,
		},
	)
	a.Properties = new(MediaPlayer1Properties)

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

/*
MediaPlayer1 MediaPlayer1 hierarchy

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

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

	/*
		Album Track album name
	*/
	Album string

	/*
		Artist Track artist name
	*/
	Artist string

	/*
		Browsable If present indicates the player can be browsed using
				MediaFolder interface.

				Possible values:

					True: Supported and active
					False: Supported but inactive

				Note: If supported but inactive clients can enable it
				by using MediaFolder interface but it might interfere
				in the playback of other players.
	*/
	Browsable bool

	/*
		Device Device object path.
	*/
	Device dbus.ObjectPath

	/*
		Duration Track duration in milliseconds
	*/
	Duration uint32

	/*
		Equalizer Possible values: "off" or "on"
	*/
	Equalizer string

	/*
		Genre Track genre name
	*/
	Genre string

	/*
		Name Player name
	*/
	Name string

	/*
		NumberOfTracks Number of tracks in total
	*/
	NumberOfTracks uint32

	/*
		Playlist Playlist object path.
	*/
	Playlist dbus.ObjectPath

	/*
		Position Playback position in milliseconds. Changing the
				position may generate additional events that will be
				sent to the remote device. When position is 0 it means
				the track is starting and when it's greater than or
				equal to track's duration the track has ended. Note
				that even if duration is not available in metadata it's
				possible to signal its end by setting position to the
				maximum uint32 value.
	*/
	Position uint32

	/*
		Repeat Possible values: "off", "singletrack", "alltracks" or
						"group"
	*/
	Repeat string

	/*
		Scan Possible values: "off", "alltracks" or "group"
	*/
	Scan string

	/*
		Searchable If present indicates the player can be searched using
				MediaFolder interface.

				Possible values:

					True: Supported and active
					False: Supported but inactive

				Note: If supported but inactive clients can enable it
				by using MediaFolder interface but it might interfere
				in the playback of other players.
	*/
	Searchable bool

	/*
		Shuffle Possible values: "off", "alltracks" or "group"
	*/
	Shuffle string

	/*
		Status Possible status: "playing", "stopped", "paused",
						"forward-seek", "reverse-seek"
						or "error"
	*/
	Status string

	/*
		Subtype Player subtype

				Possible values:

					"Audio Book"
					"Podcast"
	*/
	Subtype string

	/*
		Title Track title name
	*/
	Title string

	/*
		Track Track metadata.

				Possible values:
	*/
	Track Track

	/*
		TrackNumber Track number
	*/
	TrackNumber uint32

	/*
		Type Player type

				Possible values:

					"Audio"
					"Video"
					"Audio Broadcasting"
					"Video Broadcasting"
	*/
	Type string
}

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

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

// SetAlbum set Album value
func (a *MediaPlayer1) SetAlbum(v string) error {
	return a.SetProperty("Album", v)
}

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

// SetArtist set Artist value
func (a *MediaPlayer1) SetArtist(v string) error {
	return a.SetProperty("Artist", v)
}

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

// SetBrowsable set Browsable value
func (a *MediaPlayer1) SetBrowsable(v bool) error {
	return a.SetProperty("Browsable", v)
}

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

// SetDevice set Device value
func (a *MediaPlayer1) SetDevice(v dbus.ObjectPath) error {
	return a.SetProperty("Device", v)
}

// GetDevice get Device value
func (a *MediaPlayer1) GetDevice() (dbus.ObjectPath, error) {
	v, err := a.GetProperty("Device")
	if err != nil {
		return dbus.ObjectPath(""), err
	}
	return v.Value().(dbus.ObjectPath), nil
}

// SetDuration set Duration value
func (a *MediaPlayer1) SetDuration(v uint32) error {
	return a.SetProperty("Duration", v)
}

// GetDuration get Duration value
func (a *MediaPlayer1) GetDuration() (uint32, error) {
	v, err := a.GetProperty("Duration")
	if err != nil {
		return uint32(0), err
	}
	return v.Value().(uint32), nil
}

// SetEqualizer set Equalizer value
func (a *MediaPlayer1) SetEqualizer(v string) error {
	return a.SetProperty("Equalizer", v)
}

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

// SetGenre set Genre value
func (a *MediaPlayer1) SetGenre(v string) error {
	return a.SetProperty("Genre", v)
}

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

// SetName set Name value
func (a *MediaPlayer1) SetName(v string) error {
	return a.SetProperty("Name", v)
}

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

// SetNumberOfTracks set NumberOfTracks value
func (a *MediaPlayer1) SetNumberOfTracks(v uint32) error {
	return a.SetProperty("NumberOfTracks", v)
}

// GetNumberOfTracks get NumberOfTracks value
func (a *MediaPlayer1) GetNumberOfTracks() (uint32, error) {
	v, err := a.GetProperty("NumberOfTracks")
	if err != nil {
		return uint32(0), err
	}
	return v.Value().(uint32), nil
}

// SetPlaylist set Playlist value
func (a *MediaPlayer1) SetPlaylist(v dbus.ObjectPath) error {
	return a.SetProperty("Playlist", v)
}

// GetPlaylist get Playlist value
func (a *MediaPlayer1) GetPlaylist() (dbus.ObjectPath, error) {
	v, err := a.GetProperty("Playlist")
	if err != nil {
		return dbus.ObjectPath(""), err
	}
	return v.Value().(dbus.ObjectPath), nil
}

// SetPosition set Position value
func (a *MediaPlayer1) SetPosition(v uint32) error {
	return a.SetProperty("Position", v)
}

// GetPosition get Position value
func (a *MediaPlayer1) GetPosition() (uint32, error) {
	v, err := a.GetProperty("Position")
	if err != nil {
		return uint32(0), err
	}
	return v.Value().(uint32), nil
}

// SetRepeat set Repeat value
func (a *MediaPlayer1) SetRepeat(v string) error {
	return a.SetProperty("Repeat", v)
}

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

// SetScan set Scan value
func (a *MediaPlayer1) SetScan(v string) error {
	return a.SetProperty("Scan", v)
}

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

// SetSearchable set Searchable value
func (a *MediaPlayer1) SetSearchable(v bool) error {
	return a.SetProperty("Searchable", v)
}

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

// SetShuffle set Shuffle value
func (a *MediaPlayer1) SetShuffle(v string) error {
	return a.SetProperty("Shuffle", v)
}

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

// SetStatus set Status value
func (a *MediaPlayer1) SetStatus(v string) error {
	return a.SetProperty("Status", v)
}

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

// SetSubtype set Subtype value
func (a *MediaPlayer1) SetSubtype(v string) error {
	return a.SetProperty("Subtype", v)
}

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

// SetTitle set Title value
func (a *MediaPlayer1) SetTitle(v string) error {
	return a.SetProperty("Title", v)
}

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

// SetTrack set Track value
func (a *MediaPlayer1) SetTrack(v map[string]interface{}) error {
	return a.SetProperty("Track", v)
}

// GetTrack get Track value
func (a *MediaPlayer1) GetTrack() (map[string]interface{}, error) {
	v, err := a.GetProperty("Track")
	if err != nil {
		return map[string]interface{}{}, err
	}
	return v.Value().(map[string]interface{}), nil
}

// SetTrackNumber set TrackNumber value
func (a *MediaPlayer1) SetTrackNumber(v uint32) error {
	return a.SetProperty("TrackNumber", v)
}

// GetTrackNumber get TrackNumber value
func (a *MediaPlayer1) GetTrackNumber() (uint32, error) {
	v, err := a.GetProperty("TrackNumber")
	if err != nil {
		return uint32(0), err
	}
	return v.Value().(uint32), nil
}

// SetType set Type value
func (a *MediaPlayer1) SetType(v string) error {
	return a.SetProperty("Type", v)
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

/*
Play 			Resume playback.
			Possible Errors: org.bluez.Error.NotSupported
					 org.bluez.Error.Failed

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

/*
Pause 			Pause playback.
			Possible Errors: org.bluez.Error.NotSupported
					 org.bluez.Error.Failed

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

/*
Stop 			Stop playback.
			Possible Errors: org.bluez.Error.NotSupported
					 org.bluez.Error.Failed

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

/*
Next 			Next item.
			Possible Errors: org.bluez.Error.NotSupported
					 org.bluez.Error.Failed

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

/*
Previous 			Previous item.
			Possible Errors: org.bluez.Error.NotSupported
					 org.bluez.Error.Failed

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

/*
FastForward 			Fast forward playback, this action is only stopped
			when another method in this interface is called.
			Possible Errors: org.bluez.Error.NotSupported
					 org.bluez.Error.Failed

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

/*
Rewind 			Rewind playback, this action is only stopped
			when another method in this interface is called.
			Possible Errors: org.bluez.Error.NotSupported
					 org.bluez.Error.Failed

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

/*
Press 			Press a specific key to send as passthrough command.
			The key will be released automatically. Use Hold()
			instead if the intention is to hold down the key.
			Possible Errors: org.bluez.Error.InvalidArguments
					 org.bluez.Error.NotSupported
					 org.bluez.Error.Failed

*/
func (a *MediaPlayer1) Press(avc_key byte) error {
	return a.client.Call("Press", 0, avc_key).Store()
}

/*
Hold 			Press and hold a specific key to send as passthrough
			command. It is your responsibility to make sure that
			Release() is called after calling this method. The held
			key will also be released when any other method in this
			interface is called.
			Possible Errors: org.bluez.Error.InvalidArguments
					 org.bluez.Error.NotSupported
					 org.bluez.Error.Failed

*/
func (a *MediaPlayer1) Hold(avc_key byte) error {
	return a.client.Call("Hold", 0, avc_key).Store()
}

/*
Release 			Release the previously held key invoked using Hold().
			Possible Errors: org.bluez.Error.NotSupported
					 org.bluez.Error.Failed

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