from mutagen.flac import FLAC, Picture
from mutagen.id3 import ID3, ID3NoHeaderError, \
    TXXX, TIT2, TPE1, TALB, TPE2, TRCK, TPOS, TCON, TYER, TDAT, TLEN, TBPM, \
    TPUB, TSRC, USLT, SYLT, APIC, IPLS, TCOM, TCOP, TCMP, Encoding, PictureType, POPM

# Adds tags to a MP3 file
def tagID3(path, track, save):
    # Delete exsisting tags
    try:
        tag = ID3(path)
        tag.delete()
    except ID3NoHeaderError:
        tag = ID3()

    if save['title']:
        tag.add(TIT2(text=track.title))

    if save['artist'] and len(track.artists):
        if save['multiArtistSeparator'] == "default":
            tag.add(TPE1(text=track.artists))
        else:
            if save['multiArtistSeparator'] == "nothing":
                tag.add(TPE1(text=track.mainArtist.name))
            else:
                tag.add(TPE1(text=track.artistsString))
            # Tag ARTISTS is added to keep the multiartist support when using a non standard tagging method
            # https://picard-docs.musicbrainz.org/en/appendices/tag_mapping.html#artists
            if save['artists']:
                tag.add(TXXX(desc="ARTISTS", text=track.artists))

    if save['album']:
        tag.add(TALB(text=track.album.title))

    if save['albumArtist'] and len(track.album.artists):
        if save['singleAlbumArtist'] and track.album.mainArtist.save:
            tag.add(TPE2(text=track.album.mainArtist.name))
        else:
            tag.add(TPE2(text=track.album.artists))

    if save['trackNumber']:
        trackNumber = str(track.trackNumber)
        if save['trackTotal']:
            trackNumber += "/" + str(track.album.trackTotal)
        tag.add(TRCK(text=trackNumber))
    if save['discNumber']:
        discNumber = str(track.discNumber)
        if save['discTotal']:
            discNumber += "/" + str(track.album.discTotal)
        tag.add(TPOS(text=discNumber))

    if save['genre']:
        tag.add(TCON(text=track.album.genre))
    if save['year']:
        tag.add(TYER(text=str(track.date.year)))
    if save['date']:
        # Referencing ID3 standard
        # https://id3.org/id3v2.3.0#TDAT
        # The 'Date' frame is a numeric string in the DDMM format.
        tag.add(TDAT(text=str(track.date.day) + str(track.date.month)))
    if save['length']:
        tag.add(TLEN(text=str(int(track.duration)*1000)))
    if save['bpm'] and track.bpm:
        tag.add(TBPM(text=str(track.bpm)))
    if save['label']:
        tag.add(TPUB(text=track.album.label))
    if save['isrc']:
        tag.add(TSRC(text=track.ISRC))
    if save['barcode']:
        tag.add(TXXX(desc="BARCODE", text=track.album.barcode))
    if save['explicit']:
        tag.add(TXXX(desc="ITUNESADVISORY", text= "1" if track.explicit else "0" ))
    if save['replayGain']:
        tag.add(TXXX(desc="REPLAYGAIN_TRACK_GAIN", text=track.replayGain))
    if track.lyrics.unsync and save['lyrics']:
        tag.add(USLT(text=track.lyrics.unsync))
    if track.lyrics.syncID3 and save['syncedLyrics']:
        # Referencing ID3 standard
        # https://id3.org/id3v2.3.0#sec4.10
        # Type:   1  => is lyrics
        # Format: 2  => Absolute time, 32 bit sized, using milliseconds as unit
        tag.add(SYLT(Encoding.UTF8, type=1, format=2, text=track.lyrics.syncID3))

    involved_people = []
    for role in track.contributors:
        if role in ['author', 'engineer', 'mixer', 'producer', 'writer']:
            for person in track.contributors[role]:
                involved_people.append([role, person])
        elif role == 'composer' and save['composer']:
            tag.add(TCOM(text=track.contributors['composer']))
    if len(involved_people) > 0 and save['involvedPeople']:
        tag.add(IPLS(people=involved_people))

    if save['copyright'] and track.copyright:
        tag.add(TCOP(text=track.copyright))
    if save['savePlaylistAsCompilation'] and track.playlist or track.album.recordType == "compile":
        tag.add(TCMP(text="1"))

    if save['source']:
        tag.add(TXXX(desc="SOURCE", text='Deezer'))
        tag.add(TXXX(desc="SOURCEID", text=str(track.id)))

    if save['rating']:
        rank = round((int(track.rank) / 10000) * 2.55)
        if rank > 255 :
            rank = 255
        else:
            rank = round(rank, 0)

        tag.add(POPM(rating=rank))

    if save['cover'] and track.album.embeddedCoverPath:

        descEncoding = Encoding.LATIN1
        if save['coverDescriptionUTF8']:
            descEncoding = Encoding.UTF8

        mimeType = 'image/jpeg'
        if str(track.album.embeddedCoverPath).endswith('png'):
            mimeType = 'image/png'

        with open(track.album.embeddedCoverPath, 'rb') as f:
            tag.add(APIC(descEncoding, mimeType, PictureType.COVER_FRONT, desc='cover', data=f.read()))

    tag.save( path,
              v1=2 if save['saveID3v1'] else 0,
              v2_version=3,
              v23_sep=None if save['useNullSeparator'] else '/' )

# Adds tags to a FLAC file
def tagFLAC(path, track, save):
    # Delete exsisting tags
    tag = FLAC(path)
    tag.delete()
    tag.clear_pictures()

    if save['title']:
        tag["TITLE"] = track.title

    if save['artist'] and len(track.artists):
        if save['multiArtistSeparator'] == "default":
            tag["ARTIST"] = track.artists
        else:
            if save['multiArtistSeparator'] == "nothing":
                tag["ARTIST"] = track.mainArtist.name
            else:
                tag["ARTIST"] = track.artistsString
            # Tag ARTISTS is added to keep the multiartist support when using a non standard tagging method
            # https://picard-docs.musicbrainz.org/en/technical/tag_mapping.html#artists
            if save['artists']:
                tag["ARTISTS"] = track.artists

    if save['album']:
        tag["ALBUM"] = track.album.title

    if save['albumArtist'] and len(track.album.artists):
        if save['singleAlbumArtist'] and track.album.mainArtist.save:
            tag["ALBUMARTIST"] = track.album.mainArtist.name
        else:
            tag["ALBUMARTIST"] = track.album.artists

    if save['trackNumber']:
        tag["TRACKNUMBER"] = str(track.trackNumber)
    if save['trackTotal']:
        tag["TRACKTOTAL"] = str(track.album.trackTotal)
    if save['discNumber']:
        tag["DISCNUMBER"] = str(track.discNumber)
    if save['discTotal']:
        tag["DISCTOTAL"] = str(track.album.discTotal)
    if save['genre']:
        tag["GENRE"] = track.album.genre

    # YEAR tag is not suggested as a standard tag
    # Being YEAR already contained in DATE will only use DATE instead
    # Reference: https://www.xiph.org/vorbis/doc/v-comment.html#fieldnames
    if save['date']:
        tag["DATE"] = track.dateString
    elif save['year']:
        tag["DATE"] = str(track.date.year)

    if save['length']:
        tag["LENGTH"] = str(int(track.duration)*1000)
    if save['bpm'] and track.bpm:
        tag["BPM"] = str(track.bpm)
    if save['label']:
        tag["PUBLISHER"] = track.album.label
    if save['isrc']:
        tag["ISRC"] = track.ISRC
    if save['barcode']:
        tag["BARCODE"] = track.album.barcode
    if save['explicit']:
        tag["ITUNESADVISORY"] = "1" if track.explicit else "0"
    if save['replayGain']:
        tag["REPLAYGAIN_TRACK_GAIN"] = track.replayGain
    if track.lyrics.unsync and save['lyrics']:
        tag["LYRICS"] = track.lyrics.unsync

    for role in track.contributors:
        if role in ['author', 'engineer', 'mixer', 'producer', 'writer', 'composer']:
            if save['involvedPeople'] and role != 'composer' or save['composer'] and role == 'composer':
                tag[role] = track.contributors[role]
        elif role == 'musicpublisher' and save['involvedPeople']:
            tag["ORGANIZATION"] = track.contributors['musicpublisher']

    if save['copyright'] and track.copyright:
        tag["COPYRIGHT"] = track.copyright
    if save['savePlaylistAsCompilation'] and track.playlist or track.album.recordType == "compile":
        tag["COMPILATION"] = "1"

    if save['source']:
        tag["SOURCE"] = 'Deezer'
        tag["SOURCEID"] = str(track.id)

    if save['rating']:
        rank = round((int(track.rank) / 10000))
        tag['RATING'] = str(rank)

    if save['cover'] and track.album.embeddedCoverPath:
        image = Picture()
        image.type = PictureType.COVER_FRONT
        image.mime = 'image/jpeg'
        if str(track.album.embeddedCoverPath).endswith('png'):
            image.mime = 'image/png'
        with open(track.album.embeddedCoverPath, 'rb') as f:
            image.data = f.read()
        tag.add_picture(image)

    tag.save(deleteid3=True)