-- vim:fileencoding=utf-8:foldmethod=marker:foldmarker={{{,}}}

-- {{{ Libraries

local awful = require("awful")
local wibox = require("wibox")
local watch = require("awful.widget.watch")
local lgi = require("lgi")

-- End libraries }}}


-- {{{ Variables 

local GET_STATUS_CMD = 'playerctl -a status'
local GET_CURRENT_SONG_CMD = 'playerctl -a metadata'
local player_widget = {}
local Playerctl = lgi.Playerctl
local player = Playerctl.Player{}

-- End variables }}}


-- {{{ Misc functions

local function ellipsize(text, length)
	if utf8 == nil then
		return text:sub(0, length)
	end
	return (utf8.len(text) > length and length > 0)
		and text:sub(0, utf8.offset(text, length - 2) -1) .. '...'
		or text
end

local function music_PlayPause()
	player:play_pause()
end

local function music_next()
	player:next()
end

local function music_prev()
	player:previous()
end

local function music_stop()
	player:stop()
end

-- End misc functions }}}


-- {{{ Worker function 

local function worker(user_args)

	-- {{{ Variables
	local args = user_args or {}
	local widget_dir = os.getenv("HOME") .. '/.config/awesome/widgets/playerctl-widget/'

	local play_icon = args.play_icon or widget_dir .. 'player_play.png'
	local pause_icon = args.pause_icon or widget_dir .. 'player_pause.png'
	local font = args.font or 'Play 9'
	local dim_when_paused = args.dim_when_paused == nil and false or args.dim_when_paused
	local dim_opacity = args.dim_opacity or 0.2
	local max_length = args.max_length or 15
	local show_tooltip = args.show_tooltip == nil and true or args.show_tooltip
	local refresh_rate = args.refresh_rate or 1
	local max_text_size = args.max_text_size or 150
	local text_speed = args.max_text_speed or 20

	local cur_artist = ''
	local cur_title = ''
	local cur_album = ''
	-- End variables }}}


	-- {{{ Player functions
	
	function player_widget:PlayPause()
		music_PlayPause()
	end

	-- End player functions }}}


	-- {{{ player_widget settings
	player_widget = wibox.widget {
		{
			id = 'artistw',
			font = font,
			widget = wibox.widget.textbox,
			--text = 'artistw',
		},
		{
			id = "icon",
			widget = wibox.widget.imagebox,
			image = pause_icon,
		},
		{
			layout = wibox.container.scroll.horizontal,
			max_size = max_text_size,
			--step_function = wibox.container.scroll.step_functions.waiting_nonlinear_back_and_forth,
			step_function = wibox.container.scroll.step_functions.increase,
			speed = text_speed,
			{
				id = 'titlew',
				font = font,
				widget = wibox.widget.textbox,
				--text = 'titlew',
			},
		},
		layout = wibox.layout.align.horizontal,
		set_status = function (self, is_playing)
			self.icon.image = (is_playing and play_icon or pause_icon)
			if dim_when_paused then
				self:get_children_by_id('icon')[1]:set_opacity(is_playing and 1 or dim_opacity)
			end
		end,

		set_text = function (self, artist, song)
			local artist_to_display = ellipsize(artist, max_length)
			local title_to_display = ellipsize(song, max_length)
			if self:get_children_by_id('artistw')[1]:get_markup() ~= artist_to_display then
				self:get_children_by_id('artistw')[1]:set_markup(artist_to_display)
			end

			if self:get_children_by_id('titlew')[1]:get_markup() ~= title_to_display then
				self:get_children_by_id('titlew')[1]:set_markup(title_to_display)
			end
		end
	}
	-- End player_widget settings }}}


	-- {{{ update_widget_icon
	local update_widget_icon = function (widget, stdout, _, _, _)
		stdout = string.gsub(stdout, "\n", "")
		widget:set_status(stdout == 'Playing' and true or false)
	end
	-- End update_widget_icon }}}


	-- {{{ update_widget_text
	local update_widget_text = function (widget, stdout, _, _, _)
		if string.len(stdout) == 0 then
			widget:set_text('','')
			widget:set_visible(false)
			return
		end

		local escaped = string.gsub(stdout, "&", '&amp;')
--		local album, _, artist, title =
--			string.match(escaped, 'Album%s*(.*)\nAlbumArtist%s*(.*)\nArtist%s*(.*)\nTitle%s*(.*)\n')
		local title = string.match(escaped, "xesam:title *([^\n]*)")
		local album = string.match(escaped, "xesam:album *([^\n]*)")
		local artist = string.match(escaped, "xesam:artist *([^\n]*)")

		if album ~= nil and title ~= nil and artist ~= nil then
			cur_artist = artist
			cur_title = title
			cur_album = album

			widget:set_text(artist, title)
			widget:set_visible(true)
		else
			cur_album = album ~= nil and album or 'album_place'
			cur_title = title ~= nil and title or 'title_place'
			cur_artist = artist ~= nil and artist or 'artist_place'

			widget:set_text(artist, title)
			widget:set_visible(true)
		end
	end
	-- End update_widget_text }}}

	watch(GET_STATUS_CMD, refresh_rate, update_widget_icon, player_widget)
	watch(GET_CURRENT_SONG_CMD, refresh_rate, update_widget_text, player_widget)

	-- {{{ Add mouse controls to the widget
	
	player_widget:connect_signal("button::press", function (_, _, _, button)
		print(button)
		if (button == 1) then
			music_PlayPause()
		elseif (button == 3) then
			music_stop()
		elseif (button == 4) then
			music_next()
		elseif (button == 5) then
			music_prev()
		end
		awful.spawn.easy_async(GET_CURRENT_SONG_CMD, function (stdout, stderr, exitreason, exitcode)
			update_widget_icon(player_widget, stdout, stderr, exitreason, exitcode)
		end)
	end)

	-- End add mouse controls to the widget }}}


	-- {{{ Show tooltip
	if show_tooltip then
		local player_tooltip = awful.tooltip {
			mode = 'outside',
			preferred_positions = {'bottom'},
		}

		player_tooltip:add_to_object(player_widget)

		player_widget:connect_signal('mouse::enter', function ()
			player_tooltip.markup = '<b>Album</b>: ' .. cur_album
				.. '\n<b>Artist</b>: ' .. cur_artist
				.. '\n<b>Song</b>: ' .. cur_title
		end)
	end
	-- End show tooltip }}}

	function player_widget:music_PlayPause()
		music_PlayPause()
	end
	function player_widget:music_next()
		music_next()
	end
	function player_widget:music_prev()
		music_prev()
	end
	function player_widget:music_stop()
		music_stop()
	end

	return player_widget

end

-- End worker function }}}


return setmetatable(player_widget, {
	__call = function (_, ...)
		return worker(...)
	end
})
