#include "musicbrainzService.h"

/*
 * http://musicbrainz.org/ws/2/recording/?query=artist:lana%20del%20rey+recording:ultraviolence
 * http://google.com/complete/search?output=toolbar&q=lana
 * */

musicBrainz::musicBrainz(const DB &song)
{
    this->availableInfo.insert(ONTOLOGY::ALBUM, {INFO::TAGS});
    this->availableInfo.insert(ONTOLOGY::ARTIST, {INFO::TAGS});
    this->availableInfo.insert(ONTOLOGY::TRACK, {INFO::TAGS});

    this->track = song;
}

bool musicBrainz::setUpService(const PULPO::ONTOLOGY &ontology, const PULPO::INFO &info)
{
    this->ontology = ontology;
    this->info = info;

    if(!this->availableInfo[this->ontology].contains(this->info))
        return false;

    auto url = this->API;
    QUrl encodedArtist(this->track[BAE::KEY::ARTIST]);
    encodedArtist.toEncoded(QUrl::FullyEncoded);

    switch(this->ontology)
    {
    case PULPO::ONTOLOGY::ARTIST:
    {
        url.append(QString("artist/?query=artist:\"" + encodedArtist.toString()+ "\"")) ;
        url.append("&fmt=json");
        url.append("&limit=5");
        break;
    }

    case PULPO::ONTOLOGY::ALBUM:
    {
        QUrl encodedAlbum(this->track[BAE::KEY::ALBUM]);
        encodedAlbum.toEncoded(QUrl::FullyEncoded);

        url.append(QString("release/?query=release:\"" + encodedAlbum.toString()+ "\"")) ;
        url.append(QString("+artist:\"" + encodedArtist.toString()+ "\"")) ;
        url.append(QString("+primarytype:\"album\"&fmt=json&limit=5"));
        break;
    }

    case PULPO::ONTOLOGY::TRACK:
    {
        QUrl encodedTrack(this->track[BAE::KEY::TITLE]);
        encodedTrack.toEncoded(QUrl::FullyEncoded);
        url.append(QString("recording/?query=artist:\"" + encodedArtist.toString() + "\""));
        url.append(QString("+recording:\"" + encodedTrack.toString()+ "\""));
        url.append("&fmt=json");
        url.append("&limit=5");

        break;
    }

    default: return false;
    }

    qDebug()<< "[musicbrainz service]: "<< url;

    this->array = this->startConnection(url, this->header);
    if(this->array.isEmpty()) return false;

    return this->parseArray();
}

bool musicBrainz::parseArtist()
{
    QJsonParseError jsonParseError;
    QJsonDocument jsonResponse = QJsonDocument::fromJson(static_cast<QString>(array).toUtf8(), &jsonParseError);

    if (jsonParseError.error != QJsonParseError::NoError)
        return false;

    if (!jsonResponse.isObject()) return false;

    auto data = jsonResponse.object().toVariantMap();

    if(data.isEmpty()) return false;

    QList<QVariant> items = data.value("artists").toList();

    if(items.isEmpty())  return false;

    for(auto item : items)
    {
        auto itemMap = item.toMap();

        if(this->info == INFO::TAGS || this->info == INFO::ALL)
        {
            PULPO::VALUE contexts;

            auto score = itemMap.value("score").toString();
            contexts.insert(CONTEXT::ARTIST_STAT,score);

            QStringList aliases;
            aliases << itemMap.value("sort-name").toString();
            for(auto alias : itemMap.value("aliases").toList())
                aliases << alias.toMap().value("name").toString();

            contexts.insert(CONTEXT::ARTIST_ALIAS,aliases);

            auto gender = itemMap.value("gender").toString();
            contexts.insert(CONTEXT::ARTIST_GENDER,gender);

            QStringList places;

            places << itemMap.value("country").toString();
            places << itemMap.value("area").toMap().value("name").toString();
            places << itemMap.value("begin-area").toMap().value("name").toString();

            contexts.insert(CONTEXT::ARTIST_PLACE,places);

            auto lifeSpan_begin = itemMap.value("life-span").toMap().value("begin").toString();
            auto lifeSpan_end = itemMap.value("life-span").toMap().value("ended").toString();
            contexts.insert(CONTEXT::ARTIST_DATE, QStringList{lifeSpan_begin,lifeSpan_end});



            QStringList tags;
            for(auto tag : itemMap.value("tags").toList())
                tags << tag.toMap().value("name").toString();

            contexts.insert(CONTEXT::TAG,tags);

            emit this->infoReady(this->track, this->packResponse(ONTOLOGY::ARTIST, INFO::TAGS,contexts));
            if(this->info == INFO::TAGS  && !contexts.isEmpty()) return true;
        }

    }

    return false;
}

bool musicBrainz::parseAlbum()
{
    QJsonParseError jsonParseError;
    QJsonDocument jsonResponse = QJsonDocument::fromJson(static_cast<QString>(array).toUtf8(), &jsonParseError);

    if (jsonParseError.error != QJsonParseError::NoError)
        return false;

    if (!jsonResponse.isObject()) return false;

    auto data = jsonResponse.object().toVariantMap();

    if(data.isEmpty()) return false;

    QList<QVariant> items = data.value("releases").toList();

    if(items.isEmpty())  return false;

    for(auto item : items)
    {
        auto itemMap = item.toMap();

        if(this->info == INFO::TAGS || this->info == INFO::ALL)
        {
            PULPO::VALUE contexts;

            auto score = itemMap.value("score").toString();
            contexts.insert(CONTEXT::ALBUM_STAT,score);

            auto date = itemMap.value("date").toString();
            contexts.insert(CONTEXT::ALBUM_DATE,date);

            QStringList labels;
            for(auto label : itemMap.value("label-info").toList())
                labels << label.toMap().value("label").toMap().value("name").toString();

            contexts.insert(CONTEXT::ALBUM_LABEL,labels);

            emit this->infoReady(this->track, this->packResponse(ONTOLOGY::ALBUM, INFO::TAGS,contexts));
            if(this->info == INFO::TAGS  && !contexts.isEmpty()) return true;
        }

    }

    return false;
}

bool musicBrainz::parseTrack()
{

    QJsonParseError jsonParseError;
    QJsonDocument jsonResponse = QJsonDocument::fromJson(static_cast<QString>(array).toUtf8(), &jsonParseError);

    if (jsonParseError.error != QJsonParseError::NoError)
        return false;

    if (!jsonResponse.isObject()) return false;

    auto data = jsonResponse.object().toVariantMap();

    if(data.isEmpty()) return false;
    QList<QVariant> items = data.value("recordings").toList();

    if(items.isEmpty())  return false;

    auto id = items.first().toMap().value("id").toString();
    auto url =QString("http://musicbrainz.org/ws/2/recording/%1?inc=artist-rels+recording-rels&fmt=json&limit=5").arg(id);
    qDebug()<<"NEW TRACK INFO URL MUSICBRAINZ"<<url;
    auto rel = this->startConnection(url, this->header);

    if(rel.isEmpty()) return false;

    jsonResponse = QJsonDocument::fromJson(static_cast<QString>(rel).toUtf8(), &jsonParseError);

    if (jsonParseError.error != QJsonParseError::NoError)
        return false;

    if (!jsonResponse.isObject()) return false;

    data = jsonResponse.object().toVariantMap();

    if(data.isEmpty()) return false;


    if(this->info == INFO::TAGS || this->info == INFO::ALL)
    {
        items = data.value("relations").toList();

        if(items.isEmpty())  return false;

        QStringList people;

        for(auto item : items)
        {
            auto team = item.toMap().value("artist").toMap().value("name").toString();
            people<<team;
        }

        emit this->infoReady(this->track, this->packResponse(ONTOLOGY::TRACK, INFO::TAGS,CONTEXT::TRACK_TEAM, people));
        if(this->info == INFO::TAGS  && !people.isEmpty()) return true;
    }


    return false;
}
