"""The data models for the Music submodule of the URY website.

These data models are implemented using SQLAlchemy and contain no
website-specific code, and are theoretically transplantable into any Python
project.

Most notably missing from these models is any semblance of a "get URL" function
as this is defined at the template level.  This is not ideal, but is
deliberately done to separate data models from the website concepts.

---

Copyright (c) 2013, University Madio York.
All rights reserved.

Redistribution and use in sourceand binary forms, with or without modification,
are permitted provided that the following conditions are met:

* Redistributins of source code must retain the above copyright notice,
  this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
  notice, this list of Musonditions and the following disclaimer in the
  documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THECOPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. INNO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""

import itertools
import operator
import sqlalchemy

import lass.model_base
import lass.common
import lass.people.models


# These exist to speed up rec_Xlookup and similar definitions:
def lookup_id(name, direct_name=False):
    return sqlalchemy.Column(
        name if direct_name else '_'.join((name, 'code')),
        sqlalchemy.CHAR(1),
        primary_key=True,
        nullable=False
    )


def lookup_descr(name, direct_name=False):
    return sqlalchemy.Column(
        name if direct_name else '_'.join((name, 'descr')),
        sqlalchemy.Text,
        nullable=False
    )


#
# REC
#

class Genre(lass.model_base.PublicModel):
    """A genre in the track database."""
    __tablename__ = 'rec_genrelookup'
    id = lookup_id('genre')
    description = lookup_descr('genre')


class Medium(lass.model_base.PublicModel):
    """A type of record medium in the track database.

    Medium in this case means, for example, 'vinyl', 'CD' etc.
    """
    __tablename__ = 'rec_medialookup'
    id = lookup_id('media')
    description = lookup_descr('media')


class RecordFormat(lass.model_base.PublicModel):
    """A type of record format in the track database.

    Format in this case means, for example, 'album' or 'single'.
    """
    __tablename__ = 'rec_formatlookup'
    id = lookup_id('format')
    description = lookup_descr('format')


class RecordStatus(lass.model_base.PublicModel):
    """A type of cleanliness status in the track database."""
    __tablename__ = 'rec_statuslookup'
    id = lookup_id('status')
    description = lookup_descr('status')


class CleanStatus(lass.model_base.PublicModel):
    """A type of cleanliness status in the track database."""
    __tablename__ = 'rec_cleanlookup'
    id = lookup_id('clean')
    description = lookup_descr('clean')


class Record(lass.model_base.PublicModel):
    """A record in the track database."""
    __tablename__ = 'rec_record'

    id = sqlalchemy.Column(
        'recordid',
        sqlalchemy.Integer,
        primary_key=True,
        nullable=False
    )

    status_id = sqlalchemy.Column(
        'status',
        sqlalchemy.ForeignKey(RecordStatus.id),
        nullable=False,
        server_default='o'
    )
    status = sqlalchemy.orm.relationship(RecordStatus)

    medium_id = sqlalchemy.Column(
        'media',
        sqlalchemy.ForeignKey(Medium.id),
        nullable=False
    )
    medium = sqlalchemy.orm.relationship(Medium)

    format_id = sqlalchemy.Column(
        'format',
        sqlalchemy.ForeignKey(RecordFormat.id),
        nullable=False
    )
    format = sqlalchemy.orm.relationship(RecordFormat)

    memberid_add = sqlalchemy.Column(
        sqlalchemy.ForeignKey(lass.people.models.Person.id),
        nullable=False
    )
    adder = sqlalchemy.orm.relationship(
        lass.people.models.Person,
        foreign_keys=[memberid_add]
    )

    memberid_lastedit = sqlalchemy.Column(
        sqlalchemy.ForeignKey(lass.people.models.Person.id)
    )
    last_editor = sqlalchemy.orm.relationship(
        lass.people.models.Person,
        foreign_keys=[memberid_lastedit]
    )

    title = sqlalchemy.Column(sqlalchemy.Text, nullable=False)
    artist = sqlalchemy.Column(sqlalchemy.Text, nullable=False)
    recordlabel = sqlalchemy.Column(sqlalchemy.Text, nullable=False)
    dateadded = sqlalchemy.Column(
        sqlalchemy.DateTime(timezone=True),
        nullable=False
    )
    datereleased = sqlalchemy.Column(sqlalchemy.Date)
    shelfnumber = sqlalchemy.Column(sqlalchemy.SmallInteger, nullable=False)
    shelfletter = sqlalchemy.Column(sqlalchemy.CHAR(1), nullable=False)
    datetime_lastedit = sqlalchemy.Column(sqlalchemy.DateTime(timezone=True))
    cdid = sqlalchemy.Column(sqlalchemy.String(8))
    location = sqlalchemy.Column(sqlalchemy.Text)
    promoterid = sqlalchemy.Column(sqlalchemy.Integer)