# -*- coding: utf-8 -*-

import unittest
import picard
from picard import config
from picard.metadata import Metadata
from picard.mbxml import (
    track_to_metadata,
    release_to_metadata,
    artist_credit_from_node,
    _translate_artist_node
)


settings = {
    "standardize_tracks": False,
    "standardize_artists": False,
    "standardize_releases": False,
    "translate_artist_names": False
}


class XmlNode(object):

    def __init__(self, text=u'', children={}, attribs={}):
        self.text = text
        self.children = children
        self.attribs = attribs

    def __repr__(self):
        return repr(self.__dict__)

    def __getattr__(self, name):
        try:
            return self.children[name]
        except KeyError:
            try:
                return self.attribs[name]
            except KeyError:
                raise
                #raise AttributeError, name


class TrackTest(unittest.TestCase):

    def test_1(self):
        config.setting = settings

        class Track:
            pass

        node = XmlNode(attribs={'id': u'321'}, children={
            'title': [XmlNode(text=u'Foo')],
            'length': [XmlNode(text=u'180000')],
            'position': [XmlNode(text=u'1')],
            'recording': [XmlNode(attribs={'id': u'123'}, children={
                'relation_list': [XmlNode(attribs={'target_type': u'work'}, children={
                    'relation': [XmlNode(attribs={'type': u'performance'}, children={
                        'work': [XmlNode(attribs={'id': u'workid123'}, children={
                            'title': [XmlNode(text=u'Bar')],
                            'language': [XmlNode(text=u'eng')]
                        })]
                    })]
                })]
            })],
            'artist_credit': [XmlNode(children={
                'name_credit': [XmlNode(attribs={'joinphrase': u' & '}, children={
                    'artist': [XmlNode(attribs={'id': u'456'}, children={
                        'name': [XmlNode(text=u'Foo Bar')],
                        'sort_name': [XmlNode(text=u'Bar, Foo')]
                    })]
                }), XmlNode(children={
                    'artist': [XmlNode(attribs={'id': u'789'}, children={
                        'name': [XmlNode(text=u'Baz')],
                        'sort_name': [XmlNode(text=u'Baz')]
                    })]
                })]
            })]
        })
        track = Track()
        m = track.metadata = Metadata()
        track_to_metadata(node, track)
        self.assertEqual(u'123', m['musicbrainz_recordingid'])
        self.assertEqual(u'321', m['musicbrainz_trackid'])
        self.assertEqual(u'456; 789', m['musicbrainz_artistid'])
        self.assertEqual(u'Foo', m['title'])
        self.assertEqual(u'Foo Bar & Baz', m['artist'])
        self.assertEqual(u'Bar, Foo & Baz', m['artistsort'])
        self.assertEqual(u'workid123', m['musicbrainz_workid'])
        self.assertEqual(u'Bar', m['work'])
        self.assertEqual(u'eng', m['language'])


class ReleaseTest(unittest.TestCase):

    def test_1(self):
        config.setting = settings
        release = XmlNode(attribs={'id': u'123'}, children={
            'title': [XmlNode(text=u'Foo')],
            'status': [XmlNode(text=u'Official')],
            'text_representation': [XmlNode(children={
                'language': [XmlNode(text=u'eng')],
                'script': [XmlNode(text=u'Latn')]
            })],
            'artist_credit': [XmlNode(children={
                'name_credit': [XmlNode(attribs={'joinphrase': u' & '}, children={
                    'artist': [XmlNode(attribs={'id': u'456'}, children={
                        'name': [XmlNode(text=u'Foo Bar')],
                        'sort_name': [XmlNode(text=u'Bar, Foo')]
                    })]
                }), XmlNode(children={
                    'artist': [XmlNode(attribs={'id': u'789'}, children={
                        'name': [XmlNode(text=u'Baz')],
                        'sort_name': [XmlNode(text=u'Baz')]
                    })]
                })]
            })],
            'date': [XmlNode(text=u'2009-08-07')],
            'country': [XmlNode(text=u'GB')],
            'barcode': [XmlNode(text=u'012345678929')],
            'asin': [XmlNode(text=u'B123456789')],
            'label_info_list': [XmlNode(attribs={'count': u'1'}, children={
                'label_info': [XmlNode(children={
                    'catalog_number': [XmlNode(text=u'ABC 123')],
                    'label': [XmlNode(children={
                        'name': [XmlNode(text=u'ABC')]
                    })]
                })]
            })]
        })
        m = Metadata()
        release_to_metadata(release, m)
        self.assertEqual(u'123', m['musicbrainz_albumid'])
        self.assertEqual(u'456; 789', m['musicbrainz_albumartistid'])
        self.assertEqual(u'Foo', m['album'])
        self.assertEqual(u'official', m['releasestatus'])
        self.assertEqual(u'eng', m['~releaselanguage'])
        self.assertEqual(u'Latn', m['script'])
        self.assertEqual(u'Foo Bar & Baz', m['albumartist'])
        self.assertEqual(u'Bar, Foo & Baz', m['albumartistsort'])
        self.assertEqual(u'2009-08-07', m['date'])
        self.assertEqual(u'GB', m['releasecountry'])
        self.assertEqual(u'012345678929', m['barcode'])
        self.assertEqual(u'B123456789', m['asin'])
        self.assertEqual(u'ABC', m['label'])
        self.assertEqual(u'ABC 123', m['catalognumber'])


class ArtistTest(unittest.TestCase):

    def test_1(self):
        config.setting = settings
        node = XmlNode(children={
            'name_credit': [XmlNode(attribs={'joinphrase': u' & '}, children={
                'artist': [XmlNode(attribs={'id': u'456'}, children={
                    'name': [XmlNode(text=u'Foo Bar')],
                    'sort_name': [XmlNode(text=u'Bar, Foo')]
                })]
            }), XmlNode(children={
                'artist': [XmlNode(attribs={'id': u'789'}, children={
                    'name': [XmlNode(text=u'Baz')],
                    'sort_name': [XmlNode(text=u'Baz')]
                })]
            })]
        })
        artist, artist_sort, artists, artists_sort = artist_credit_from_node(node)
        self.assertEqual(u'Foo Bar & Baz', artist)
        self.assertEqual([u'Foo Bar', u'Baz'], artists)
        self.assertEqual(u'Bar, Foo & Baz', artist_sort)
        self.assertEqual([u'Bar, Foo', u'Baz'], artists_sort)

    def test_trans1(self):
        config.setting = settings

        node = XmlNode(
            attribs={u'id': u'666'},
            children={
                u'name': [XmlNode(text=u'Pink Floyd')],
                u'alias_list': [
                    XmlNode(
                        attribs={u'count': u'5'},
                        children={u'alias': [
                            XmlNode(
                                text=u'Pink Floid',
                                attribs={
                                    u'type': u'Search hint',
                                    u'sort_name': u'Pink Floid Sort'
                                }
                            ),
                            XmlNode(
                                text=u'Pink Floyd Artist',
                                attribs={
                                    u'locale': u'en',
                                    u'type': u'Artist name',
                                    u'primary': u'primary',
                                    u'sort_name': u'Pink Floyd Artist Sort'
                                }
                            ),
                            XmlNode(
                                text=u'The Pink Floyd',
                                attribs={
                                    u'locale': u'en',
                                    u'type': u'Artist name',
                                    u'sort_name': u'The Pink Floyd Sort'
                                }
                            ),
                            XmlNode(
                                text=u'ピンク・フロイド',
                                attribs={
                                    u'locale': u'ja',
                                    u'type': u'Artist name',
                                    u'primary': u'primary',
                                    u'sort_name': u'ピンク・フロイド Sort'
                                }
                            ),
                            XmlNode(
                                text=u'핑크 플로이드',
                                attribs={
                                    u'locale': u'ko',
                                    u'type': u'Artist name',
                                    u'primary': u'primary',
                                    u'sort_name': u'핑크 플로이드 Sort'
                                }
                            )
                        ]}
                    )
                ],
                u'sort_name': [XmlNode(text=u'Pink Floyd Sort')]
            }
        )

        config.setting["translate_artist_names"] = False
        config.setting["artist_locale"] = "en"
        transl, translsort = _translate_artist_node(node)
        self.assertEqual(u"Pink Floyd", transl)
        self.assertEqual(u"Pink Floyd Sort", translsort)

        config.setting["translate_artist_names"] = True
        config.setting["artist_locale"] = "ja"
        transl, translsort = _translate_artist_node(node)
        self.assertEqual(u'ピンク・フロイド', transl)
        self.assertEqual(u'ピンク・フロイド Sort', translsort)

        config.setting["artist_locale"] = "ko"
        transl, translsort = _translate_artist_node(node)
        self.assertEqual(u'핑크 플로이드', transl)
        self.assertEqual(u'핑크 플로이드 Sort', translsort)

        config.setting["artist_locale"] = "en"
        transl, translsort = _translate_artist_node(node)
        self.assertEqual(u"Pink Floyd Artist", transl)
        self.assertEqual(u"Pink Floyd Artist Sort", translsort)

    def test_trans3(self):
        "Legal name vs Artist name, same locales"
        config.setting = settings

        node = XmlNode(
            attribs={u'id': u'666'},
            children={
                u'name': [XmlNode(text=u'Pink Floyd')],
                u'alias_list': [
                    XmlNode(
                        attribs={u'count': u'3'},
                        children={u'alias': [
                            XmlNode(
                                text=u'Pink Floyd Legal en',
                                attribs={
                                    u'locale': u'en',
                                    u'primary': u'primary',
                                    u'type': u'Legal Name',
                                    u'sort_name': u'Pink Floyd Legal en Sort'
                                }
                            ),
                            XmlNode(
                                text=u'Pink Floyd Artist en',
                                attribs={
                                    u'locale': u'en',
                                    u'primary': u'primary',
                                    u'type': u'Artist name',
                                    u'sort_name': u'Pink Floyd Artist en Sort'
                                }
                            ),
                            XmlNode(
                                text=u'Pink Floyd Legal en_US',
                                attribs={
                                    u'locale': u'en_US',
                                    u'primary': u'primary',
                                    u'type': u'Legal Name',
                                    u'sort_name': u'Pink Floyd Legal en_US Sort'
                                }
                            ),
                        ]}
                    )
                ],
                u'sort_name': [XmlNode(text=u'Pink Floyd Sort')]
            }
        )

        config.setting["translate_artist_names"] = True

        config.setting["artist_locale"] = "en"
        transl, translsort = _translate_artist_node(node)
        self.assertEqual(u"Pink Floyd Artist en", transl)
        self.assertEqual(u"Pink Floyd Artist en Sort", translsort)

        # should pickup Artist name/en over Legal name/en_US ?
        config.setting["artist_locale"] = "en_US"
        transl, translsort = _translate_artist_node(node)
        self.assertEqual(u"Pink Floyd Artist en", transl)
        self.assertEqual(u"Pink Floyd Artist en Sort", translsort)

    def test_trans4(self):
        "exact locale match, new type/primary set"
        config.setting = settings

        node = XmlNode(
            attribs={u'id': u'666'},
            children={
                u'name': [XmlNode(text=u'Pink Floyd')],
                u'alias_list': [
                    XmlNode(
                        attribs={u'count': u'2'},
                        children={u'alias': [
                            XmlNode(
                                text=u'Pink Floyd en',
                                attribs={
                                    u'locale': u'en_US',
                                    u'primary': u'primary',
                                    u'type': u'New type',
                                    u'sort_name': u'Pink Floyd en Sort'
                                }
                            ),
                        ]}
                    )
                ],
                u'sort_name': [XmlNode(text=u'Pink Floyd Sort')]
            }
        )

        config.setting["translate_artist_names"] = True

        config.setting["artist_locale"] = "en_US"
        transl, translsort = _translate_artist_node(node)
        self.assertEqual(u"Pink Floyd en", transl)
        self.assertEqual(u"Pink Floyd en Sort", translsort)

    def test_trans5(self):
        "Lang vs locale, all artist name/primary"
        config.setting = settings

        node = XmlNode(
            attribs={u'id': u'666'},
            children={
                u'name': [XmlNode(text=u'Pink Floyd')],
                u'alias_list': [
                    XmlNode(
                        attribs={u'count': u'2'},
                        children={u'alias': [
                            XmlNode(
                                text=u'Pink Floyd en_US',
                                attribs={
                                    u'locale': u'en_US',
                                    u'primary': u'primary',
                                    u'type': u'Artist name',
                                    u'sort_name': u'Pink Floyd en_US Sort'
                                }
                            ),
                            XmlNode(
                                text=u'Pink Floyd en_UK',
                                attribs={
                                    u'locale': u'en_UK',
                                    u'primary': u'primary',
                                    u'type': u'Artist name',
                                    u'sort_name': u'Pink Floyd en_UK Sort'
                                }
                            ),
                            XmlNode(
                                text=u'Pink Floyd en',
                                attribs={
                                    u'locale': u'en',
                                    u'primary': u'primary',
                                    u'type': u'Artist name',
                                    u'sort_name': u'Pink Floyd en Sort'
                                }
                            ),
                            XmlNode(
                                text=u'Pink Floyd en_AU',
                                attribs={
                                    u'locale': u'en_AU',
                                    u'primary': u'primary',
                                    u'type': u'Artist name',
                                    u'sort_name': u'Pink Floyd en_AU Sort'
                                }
                            ),
                        ]}
                    )
                ],
                u'sort_name': [XmlNode(text=u'Pink Floyd Sort')]
            }
        )

        config.setting["translate_artist_names"] = True

        config.setting["artist_locale"] = "en"
        transl, translsort = _translate_artist_node(node)
        self.assertEqual(u"Pink Floyd en", transl)
        self.assertEqual(u"Pink Floyd en Sort", translsort)

    def test_trans6(self):
        "No alias, name without latin chars, it will use translate_from_sortname()"
        config.setting = settings

        node = XmlNode(
            attribs={u'id': u'666'},
            children={
                u'name': [XmlNode(text=u'ピンク・フロイド')],
                u'sort_name': [XmlNode(text=u'Pink Floyd')]
            }
        )

        config.setting["translate_artist_names"] = True

        # hacky en translation is chosen over native artist's name, because
        # artist's name has no locale definition, this case is a bit weird
        config.setting["artist_locale"] = "ja"
        transl, translsort = _translate_artist_node(node)
        self.assertEqual(u"Pink Floyd", transl)
        self.assertEqual(u"Pink Floyd", translsort)
