# -*- coding: utf-8 -*-
# Moovida - Home multimedia server
# Copyright (C) 2006-2009 Fluendo Embedded S.L. (www.fluendo.com).
# All rights reserved.
#
# This file is available under one of two license agreements.
#
# This file is licensed under the GPL version 3.
# See "LICENSE.GPL" in the root of this distribution including a special
# exception to use Moovida with Fluendo's plugins.
#
# The GPL part of Moovida is also available under a commercial licensing
# agreement from Fluendo.
# See "LICENSE.Moovida" in the root directory of this distribution package
# for details on that license.
#
# Authors:
#   Benjamin Kampmann <benjamin@fluendo.com>

from elisa.core.components.model import Model

from elisa.plugins.base.models.audio import TrackModel, ArtistModel, AlbumModel

class DaapModel(Model):
    """
    A DaapModel is generic Model that is used for the parsing process. The three
    class variables mappings, container and container_items are used internally.
    This model itself is a *metaclass*. Never use it directly!
    """
    mappings = {}
    container = None
    container_items = None

    def __init__(self):
        """
        The DaapModel reads all the values in self.mappings and sets the values
        to None. If container is set, it also creates the initial list at the
        attribute with the name specified in the container. This is the first
        step for the parsing process.
        """
        super(DaapModel, self).__init__()
        for value in self.mappings.values():
            setattr(self, value, None)

        # set the container to an empty list
        if self.container:
            setattr(self, self.container, [])


class DaapServerInfoModel(DaapModel):
    """
    Holds the informations about the DaapServer. Most of them are used
    internally. The only one that are interesting for the outside are:
    
    @ivar server_name:      The name of the server
    @type server_name:     C{str}
    @ivar database_count:   the number of databases in this server
    @type database_count:  C{int}
    @ivar login_required:   is a login required
    @type login_required:  C{bool}
    """
    mappings = {"mstt": "status",
               "apro": "protocol",
               "msix": "indexing_support",
               'msdc': "database_count",
               "msex": "extensions_support",
               "msup": "update_support",
               "msal": "auto_logout",
               "mstm": "timeout",
               "mslr": "login_required",
               "msqy": "query_support",
               "minm": "server_name",
               "msrs": "resolve_support",
               "msbr": "browsing_support",
               "mspi": "persistent_ids",
               "mpro": "protocol_version"}

class DaapDatabaseModel(DaapModel):
    """
    A DaapDatabase is a brief representation of one Database in the
    L{DaapDatabaseList}.databases field.

    @ivar name:             the name of this database
    @type name:            C{str}
    @ivar database_id:      the internal ID of this database. Needed to do a
                            full request for the database-songlist
    @type database_id:     C{int}
    @ivar song_count:       number of songs in this database
    @type song_count:      C{int}
    @ivar playlist_count:   number of playlists (more generic containers) in
                            this database
    @type playlist_count:  C{int}
    """
    mappings = { 'miid': 'database_id',
                 'mper': 'persistent_id',
                 'minm': 'name',
                 'mimc': 'song_count',
                 'mctc': 'playlist_count'
                }

class DaapDatabaseListModel(DaapModel):
    """
    Holds a list of alle the databases this server has. For each databases it
    holds one L{DaapDatabase}-Model in C{self.databases}.

    @ivar databases_count:  the number of databases found
    @type database_count:  C{int}
    @ivar databases:        each Database has one Model in here
    @type databases:       C{list} of L{DaapDatabase}s
    """
    mappings = { "mstt": "status",
	             "muty": "update_type", # always 0...
	             "mtco": "matched_items", 
	             "mrco": "databases_count",
                }
    container = 'databases'
    container_items = DaapDatabaseModel

class DaapSongModel(DaapModel, TrackModel):
    """
    This is a representation for one Song in a Database or a Playlist.

    @ivar song_id:  the id of this song in this database (only way to identify
                    it directly)
    @type song_id: C{int}
    @ivar kind:     the kind of data it is (2 for music)
    @type kind:    C{int}
    @ivar genre:    the genre of this song
    @type genre:   C{str}
    @ivar size:     the size of the song (in bytes)
    @type size:    C{int}
    """
    mappings = {'mikd': 'kind', # (2 for music)
                'miid': 'song_id', # the important song ID
                'minm': 'title',
                'asar': 'artist',
                'asal': 'album',
                'astm': 'duration',
                'assz': 'size',
                'asgn': 'genre',
                'astn': 'track_number',
                }

    def _title_set(self, title):
        self._title = title
        self.name = title

    def _title_get(self):
        return self._title

    title = property(fget=_title_get, fset=_title_set)

class DaapPlaylistEntryModel(DaapModel):
    """
    This is a representation of one Playlist in the PlaylistList of one
    Database.

    @ivar name:         the name of the playlist
    @type name:        C{str}
    @ivar playlist_id:  the id to identify the playlist in this database
    @type playlist_id: C{int}
    @ivar items_count:  the number of items in this playlist
    @type items_count: C{int}
    @ivar dynamic:      is it a dynamic list (0=no, 1=yes)
    @type dynamic:     C{int}
    """
    mappings = {'miid': 'playlist_id',
                'mper': 'persistent_id',
                'minm': 'name',
                'mimc': 'items_count',
                'aeSP': 'dynamic' # optional
                }


# A generic listing class, because all of their mappings are the same
class DaapListing(DaapModel):
    """
    Generic Listing class. Don't use it directly as it is meant to be a
    metaclass.

    @ivar items_count:  the number of items in this listing 
    @type items_count: C{int}
    """
    mappings = { 'mstt': 'status',
                 'muty': 'update_type',
                 'mtco': 'matched_items',
                 'mrco': 'items_count',
                }

class DaapSongListModel(DaapListing):
    """
    A list of L{DaapSongs} for one database. You received it by asking for
    'database/<id>/items'.
    
    @ivar songs:    one entry per song
    @type songs:   C{list} of L{DaapSongs}
    """
    container = 'songs'
    container_items = DaapSongModel

class DaapPlaylistListModel(DaapListing):
    """
    This is a representation of the list of playlists one database on one server
    has. It is created and filled when you access databases/<id>/containers.

    @ivar playlists:    one entry per playlist
    @type playlists:    C{list} of L{DaapPlaylistEntry}

    """
    container = 'playlists'
    container_items = DaapPlaylistEntryModel

class DaapPlaylistModel(DaapListing):
    """
    This is a representation of one playlist of a database. It holds a smaller
    list of the DaapSongs. *Attention*: on a usual request the DaapSongs that
    are created only have the L{DaapSong.song_id} set. No other values are set.
    This is more a filtering meachanism for the whole database then a Playlist
    you want to show up like this directly.

    @ivar entries:  with only the song_id set
    @type entries:  C{list} of L{DaapSong}s
    """
    container = 'entries'
    container_items = DaapSongModel


class DaapArtistListModel(Model):
    """
    Representation of a list of L{DaapArtistModel}
    """

    def __init__(self):
        super(DaapArtistListModel, self).__init__()
        self.artists = []

class DaapArtistModel(ArtistModel):
    """
    L{ArtistModel} that keeps track of the list of L{AlbumModel} and
    has a single image
    """

    def __init__(self):
        super(DaapArtistModel, self).__init__()
        self.albums = []

class DaapAlbumModel(AlbumModel):
    """
    L{AlbumModel} that has a single cover_uri
    """
