# This file is part of beets.
# Copyright 2013, Adrian Sampson.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.

"""Tests for autotagging functionality.
"""
import os
import shutil
import re
import copy

import _common
from _common import unittest
from beets import autotag
from beets.autotag import match
from beets.library import Item
from beets.util import plurality
from beets.autotag import AlbumInfo, TrackInfo
from beets import config

class PluralityTest(unittest.TestCase):
    def test_plurality_consensus(self):
        objs = [1, 1, 1, 1]
        obj, freq = plurality(objs)
        self.assertEqual(obj, 1)
        self.assertEqual(freq, 4)

    def test_plurality_near_consensus(self):
        objs = [1, 1, 2, 1]
        obj, freq = plurality(objs)
        self.assertEqual(obj, 1)
        self.assertEqual(freq, 3)

    def test_plurality_conflict(self):
        objs = [1, 1, 2, 2, 3]
        obj, freq = plurality(objs)
        self.assert_(obj in (1, 2))
        self.assertEqual(freq, 2)

    def test_plurality_empty_sequence_raises_error(self):
        with self.assertRaises(ValueError):
            plurality([])

    def test_current_metadata_finds_pluralities(self):
        items = [Item({'artist': 'The Beetles', 'album': 'The White Album'}),
                 Item({'artist': 'The Beatles', 'album': 'The White Album'}),
                 Item({'artist': 'The Beatles', 'album': 'Teh White Album'})]
        l_artist, l_album, artist_consensus = match.current_metadata(items)
        self.assertEqual(l_artist, 'The Beatles')
        self.assertEqual(l_album, 'The White Album')
        self.assertFalse(artist_consensus)

    def test_current_metadata_artist_consensus(self):
        items = [Item({'artist': 'The Beatles', 'album': 'The White Album'}),
                 Item({'artist': 'The Beatles', 'album': 'The White Album'}),
                 Item({'artist': 'The Beatles', 'album': 'Teh White Album'})]
        l_artist, l_album, artist_consensus = match.current_metadata(items)
        self.assertEqual(l_artist, 'The Beatles')
        self.assertEqual(l_album, 'The White Album')
        self.assertTrue(artist_consensus)

    def test_albumartist_consensus(self):
        items = [Item({'artist': 'tartist1', 'album': 'album',
                       'albumartist': 'aartist'}),
                 Item({'artist': 'tartist2', 'album': 'album',
                       'albumartist': 'aartist'}),
                 Item({'artist': 'tartist3', 'album': 'album',
                       'albumartist': 'aartist'})]
        l_artist, l_album, artist_consensus = match.current_metadata(items)
        self.assertEqual(l_artist, 'aartist')
        self.assertFalse(artist_consensus)

def _make_item(title, track, artist=u'some artist'):
    return Item({
        'title': title, 'track': track,
        'artist': artist, 'album': u'some album',
        'length': 1,
        'mb_trackid': '', 'mb_albumid': '', 'mb_artistid': '',
    })

def _make_trackinfo():
    return [
        TrackInfo(u'one', None, u'some artist', length=1, index=1),
        TrackInfo(u'two', None, u'some artist', length=1, index=2),
        TrackInfo(u'three', None, u'some artist', length=1, index=3),
    ]

class TrackDistanceTest(unittest.TestCase):
    def test_identical_tracks(self):
        item = _make_item(u'one', 1)
        info = _make_trackinfo()[0]
        dist = match.track_distance(item, info, incl_artist=True)
        self.assertEqual(dist, 0.0)

    def test_different_title(self):
        item = _make_item(u'foo', 1)
        info = _make_trackinfo()[0]
        dist = match.track_distance(item, info, incl_artist=True)
        self.assertNotEqual(dist, 0.0)

    def test_different_artist(self):
        item = _make_item(u'one', 1)
        item.artist = u'foo'
        info = _make_trackinfo()[0]
        dist = match.track_distance(item, info, incl_artist=True)
        self.assertNotEqual(dist, 0.0)

    def test_various_artists_tolerated(self):
        item = _make_item(u'one', 1)
        item.artist = u'Various Artists'
        info = _make_trackinfo()[0]
        dist = match.track_distance(item, info, incl_artist=True)
        self.assertEqual(dist, 0.0)

class AlbumDistanceTest(unittest.TestCase):
    def _mapping(self, items, info):
        out = {}
        for i, t in zip(items, info.tracks):
            out[i] = t
        return out

    def _dist(self, items, info):
        return match.distance(items, info, self._mapping(items, info))

    def test_identical_albums(self):
        items = []
        items.append(_make_item(u'one', 1))
        items.append(_make_item(u'two', 2))
        items.append(_make_item(u'three', 3))
        info = AlbumInfo(
            artist = u'some artist',
            album = u'some album',
            tracks = _make_trackinfo(),
            va = False,
            album_id = None, artist_id = None,