"""
Volumio Platform.

For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/media_player.volumio/
"""
import logging
import asyncio
import aiohttp

import voluptuous as vol

from homeassistant.components.media_player import (
    SUPPORT_NEXT_TRACK, SUPPORT_PAUSE, SUPPORT_PREVIOUS_TRACK, SUPPORT_SEEK,
    SUPPORT_PLAY_MEDIA, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET, SUPPORT_STOP,
    SUPPORT_PLAY, MediaPlayerDevice, PLATFORM_SCHEMA, MEDIA_TYPE_MUSIC)
from homeassistant.const import (
    STATE_PLAYING, STATE_PAUSED, STATE_IDLE, CONF_HOST, CONF_PORT, CONF_NAME)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.aiohttp_client import async_get_clientsession

_CONFIGURING = {}
_LOGGER = logging.getLogger(__name__)

DEFAULT_HOST = 'localhost'
DEFAULT_NAME = 'Volumio'
DEFAULT_PORT = 3000

TIMEOUT = 10

SUPPORT_VOLUMIO = SUPPORT_PAUSE | SUPPORT_VOLUME_SET | SUPPORT_VOLUME_MUTE | \
    SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK | SUPPORT_SEEK | \
    SUPPORT_PLAY_MEDIA | SUPPORT_STOP | SUPPORT_PLAY


PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
    vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string,
    vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
    vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
})


@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
    """Set up the Volumio platform."""
    host = config.get(CONF_HOST)
    port = config.get(CONF_PORT)
    name = config.get(CONF_NAME)

    async_add_devices([Volumio(name, host, port, hass)])


class Volumio(MediaPlayerDevice):
    """Volumio Player Object."""

    def __init__(self, name, host, port, hass):
        """Initialize the media player."""
        self.host = host
        self.port = port
        self.hass = hass
        self._url = '{}:{}'.format(host, str(port))
        self._name = name
        self._state = {}
        self.async_update()
        self._lastvol = self._state.get('volume', 0)

    @asyncio.coroutine
    def send_volumio_msg(self, method, params=None):
        """Send message."""
        url = "http://{}:{}/api/v1/{}/".format(self.host, self.port, method)

        _LOGGER.debug("URL: %s params: %s", url, params)

        try:
            websession = async_get_clientsession(self.hass)
            response = yield from websession.get(url, params=params)
            if response.status == 200:
                data = yield from response.json()
            else:
                _LOGGER.error(
                    "Query failed, response code: %s Full message: %s",
                    response.status, response)
                return False

        except (asyncio.TimeoutError, aiohttp.ClientError) as error:
            _LOGGER.error("Failed communicating with Volumio: %s", type(error))
            return False

        try:
            return data
        except AttributeError:
            _LOGGER.error("Received invalid response: %s", data)
            return False

    @asyncio.coroutine
    def async_update(self):
        """Update state."""
        resp = yield from self.send_volumio_msg('getState')
        if resp is False:
            return
        self._state = resp.copy()

    @property
    def media_content_type(self):
        """Content type of current playing media."""
        return MEDIA_TYPE_MUSIC

    @property
    def state(self):
        """Return the state of the device."""
        status = self._state.get('status', None)
        if status == 'pause':
            return STATE_PAUSED
        elif status == 'play':
            return STATE_PLAYING
        else:
            return STATE_IDLE

    @property
    def media_title(self):
        """Title of current playing media."""
        return self._state.get('title', None)

    @property
    def media_artist(self):
        """Artist of current playing media (Music track only)."""
        return self._state.get('artist', None)

    @property
    def media_album_name(self):
        """Artist of current playing media (Music track only)."""
        return self._state.get('album', None)

    @property
    def media_image_url(self):
        """Image url of current playing media."""
        url = self._state.get('albumart', None)
        if url is None:
            return
        if str(url[0:2]).lower() == 'ht':
            mediaurl = url
        else:
            mediaurl = "http://{}:{}{}".format(self.host, self.port, url)
        return mediaurl

    @property
    def media_seek_position(self):
        """Time in seconds of current seek position."""
        return self._state.get('seek', None)

    @property
    def media_duration(self):
        """Time in seconds of current song duration."""
        return self._state.get('duration', None)

    @property
    def volume_level(self):
        """Volume level of the media player (0..1)."""
        volume = self._state.get('volume', None)
        if volume is not None:
            volume = volume / 100
        return volume

    @property
    def is_volume_muted(self):
        """Boolean if volume is currently muted."""
        return self._state.get('mute', None)

    @property
    def name(self):
        """Return the name of the device."""
        return self._name

    @property
    def supported_features(self):
        """Flag of media commands that are supported."""
        return SUPPORT_VOLUMIO

    def async_media_next_track(self):
        """Send media_next command to media player."""
        return self.send_volumio_msg('commands', params={'cmd': 'next'})

    def async_media_previous_track(self):
        """Send media_previous command to media player."""
        return self.send_volumio_msg('commands', params={'cmd': 'prev'})

    def async_media_play(self):
        """Send media_play command to media player."""
        return self.send_volumio_msg('commands', params={'cmd': 'play'})

    def async_media_pause(self):
        """Send media_pause command to media player."""
        if self._state['trackType'] == 'webradio':
            return self.send_volumio_msg('commands', params={'cmd': 'stop'})
        return self.send_volumio_msg('commands', params={'cmd': 'pause'})

    def async_set_volume_level(self, volume):
        """Send volume_up command to media player."""
        return self.send_volumio_msg(
            'commands', params={'cmd': 'volume', 'volume': int(volume * 100)})

    def async_mute_volume(self, mute):
        """Send mute command to media player."""
        mutecmd = 'mute' if mute else 'unmute'
        if mute:
            # mute is implemenhted as 0 volume, do save last volume level
            self._lastvol = self._state['volume']
            return self.send_volumio_msg(
                'commands', params={'cmd': 'volume', 'volume': mutecmd})
        else:
            return self.send_volumio_msg(
                'commands', params={'cmd': 'volume', 'volume': self._lastvol})
