"""Show the amount of records in a user's Discogs collection."""
from datetime import timedelta
import logging
import random

import voluptuous as vol

from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import (
    ATTR_ATTRIBUTION,
    CONF_MONITORED_CONDITIONS,
    CONF_NAME,
    CONF_TOKEN,
)
from homeassistant.helpers.aiohttp_client import SERVER_SOFTWARE
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity

_LOGGER = logging.getLogger(__name__)

ATTR_IDENTITY = "identity"

ATTRIBUTION = "Data provided by Discogs"

DEFAULT_NAME = "Discogs"

ICON_RECORD = "mdi:album"
ICON_PLAYER = "mdi:record-player"
UNIT_RECORDS = "records"

SCAN_INTERVAL = timedelta(minutes=10)

SENSOR_COLLECTION_TYPE = "collection"
SENSOR_WANTLIST_TYPE = "wantlist"
SENSOR_RANDOM_RECORD_TYPE = "random_record"

SENSORS = {
    SENSOR_COLLECTION_TYPE: {
        "name": "Collection",
        "icon": ICON_RECORD,
        "unit_of_measurement": UNIT_RECORDS,
    },
    SENSOR_WANTLIST_TYPE: {
        "name": "Wantlist",
        "icon": ICON_RECORD,
        "unit_of_measurement": UNIT_RECORDS,
    },
    SENSOR_RANDOM_RECORD_TYPE: {
        "name": "Random Record",
        "icon": ICON_PLAYER,
        "unit_of_measurement": None,
    },
}

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
    {
        vol.Required(CONF_TOKEN): cv.string,
        vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
        vol.Optional(CONF_MONITORED_CONDITIONS, default=list(SENSORS)): vol.All(
            cv.ensure_list, [vol.In(SENSORS)]
        ),
    }
)


def setup_platform(hass, config, add_entities, discovery_info=None):
    """Set up the Discogs sensor."""
    import discogs_client

    token = config[CONF_TOKEN]
    name = config[CONF_NAME]

    try:
        discogs_client = discogs_client.Client(SERVER_SOFTWARE, user_token=token)

        discogs_data = {
            "user": discogs_client.identity().name,
            "folders": discogs_client.identity().collection_folders,
            "collection_count": discogs_client.identity().num_collection,
            "wantlist_count": discogs_client.identity().num_wantlist,
        }
    except discogs_client.exceptions.HTTPError:
        _LOGGER.error("API token is not valid")
        return

    sensors = []
    for sensor_type in config.get(CONF_MONITORED_CONDITIONS):
        sensors.append(DiscogsSensor(discogs_data, name, sensor_type))

    add_entities(sensors, True)


class DiscogsSensor(Entity):
    """Create a new Discogs sensor for a specific type."""

    def __init__(self, discogs_data, name, sensor_type):
        """Initialize the Discogs sensor."""
        self._discogs_data = discogs_data
        self._name = name
        self._type = sensor_type
        self._state = None
        self._attrs = {}

    @property
    def name(self):
        """Return the name of the sensor."""
        return "{} {}".format(self._name, SENSORS[self._type]["name"])

    @property
    def state(self):
        """Return the state of the sensor."""
        return self._state

    @property
    def icon(self):
        """Return the icon to use in the frontend, if any."""
        return SENSORS[self._type]["icon"]

    @property
    def unit_of_measurement(self):
        """Return the unit this state is expressed in."""
        return SENSORS[self._type]["unit_of_measurement"]

    @property
    def device_state_attributes(self):
        """Return the state attributes of the sensor."""
        if self._state is None or self._attrs is None:
            return None

        if self._type != SENSOR_RANDOM_RECORD_TYPE:
            return {
                ATTR_ATTRIBUTION: ATTRIBUTION,
                ATTR_IDENTITY: self._discogs_data["user"],
            }

        return {
            "cat_no": self._attrs["labels"][0]["catno"],
            "cover_image": self._attrs["cover_image"],
            "format": "{} ({})".format(
                self._attrs["formats"][0]["name"],
                self._attrs["formats"][0]["descriptions"][0],
            ),
            "label": self._attrs["labels"][0]["name"],
            "released": self._attrs["year"],
            ATTR_ATTRIBUTION: ATTRIBUTION,
            ATTR_IDENTITY: self._discogs_data["user"],
        }

    def get_random_record(self):
        """Get a random record suggestion from the user's collection."""
        # Index 0 in the folders is the 'All' folder
        collection = self._discogs_data["folders"][0]
        random_index = random.randrange(collection.count)
        random_record = collection.releases[random_index].release

        self._attrs = random_record.data
        return "{} - {}".format(
            random_record.data["artists"][0]["name"], random_record.data["title"]
        )

    def update(self):
        """Set state to the amount of records in user's collection."""
        if self._type == SENSOR_COLLECTION_TYPE:
            self._state = self._discogs_data["collection_count"]
        elif self._type == SENSOR_WANTLIST_TYPE:
            self._state = self._discogs_data["wantlist_count"]
        else:
            self._state = self.get_random_record()