#include "Spells.h"
#include <QDebug>
#include <QSet>

Spells::Spells(QVector<Spell> spells)
    : _spells(spells)
    , _filteredSpells(spells)
{}

int Spells::size() const
{
    return _filteredSpells.size();
}

Spell Spells::at(int index) const
{
    return _filteredSpells.at(index);
}

int Spells::indexOf(const Spell &spell) const
{
    return _filteredSpells.indexOf(spell);
}

void Spells::sort(QString key, Qt::SortOrder order)
{
    qSort(_filteredSpells.begin(), _filteredSpells.end(), [&](const Spell& s1, const Spell& s2){
        bool reverse = order == Qt::DescendingOrder;
        int ret = 0;

        if(key == "name")
        {
            if(s1.name() < s2.name())
            {
                ret = -1;
            }
            else if(s1.name() > s2.name())
            {
                ret = 1;
            }
        }
        else if(key == "school")
        {
            if(s1.school() < s2.school())
            {
                ret = -1;
            }
            else if(s1.school() > s2.school())
            {
                ret = 1;
            }
        }
        else if(key == "level")
        {
            if(s1.level() < s2.level())
            {
                ret = -1;
            }
            else if(s1.level() > s2.level())
            {
                ret = 1;
            }
        }
        else if(key == "casttime")
        {
            if(s1.castingtime() < s2.castingtime())
            {
                ret = -1;
            }
            else if(s1.castingtime() > s2.castingtime())
            {
                ret = 1;
            }
        }
        else if(key == "duration")
        {
            if(s1.duration() < s2.duration())
            {
                ret = -1;
            }
            else if(s1.duration() > s2.duration())
            {
                ret = 1;
            }
        }
        else if(key == "range")
        {
            if(s1.range() < s2.range())
            {
                ret = -1;
            }
            else if(s1.range() > s2.range())
            {
                ret = 1;
            }
        }
        else if(key == "components")
        {
            if(s1.components().humanReadable() < s2.components().humanReadable())
            {
                ret = -1;
            }
            else if(s1.components().humanReadable() > s2.components().humanReadable())
            {
                ret = 1;
            }
        }

        if(reverse)
        {
            if(ret == 0)
            {
                // Secondary sort is always ascending.
                return s1.name() < s2.name();
            }
            else
            {
                return ret == 1;
            }
        }
        else
        {
            if(ret == 0)
            {
                return s1.name() < s2.name();
            }
            else
            {
                return ret == -1;
            }
        }
    });
}

void Spells::setSpellFilter(SpellFilter *filter)
{
    _filteredSpells = _spells;
    QVector<int> toDelete;
    for(int i = _filteredSpells.size() - 1; i >= 0; --i)
    {
        if((filter->hasNameFilter() && !_filteredSpells[i].name().contains(filter->nameFilter(), Qt::CaseInsensitive)) ||
           (filter->hasSchoolFilter() && !_filteredSpells[i].school().contains(filter->schoolFilter(), Qt::CaseInsensitive)) ||
           (filter->hasLevelFilter() && _filteredSpells[i].level() != filter->levelFilter()) ||
           (filter->hasClassFilter() && !_filteredSpells[i].classes().contains(filter->classFilter(), Qt::CaseInsensitive)) ||
           (filter->hasRitualFilter() && _filteredSpells[i].ritual() != filter->ritualFilter()) ||
           (filter->hasConcentrationFilter() && _filteredSpells[i].concentration() != filter->concentrationFilter()) ||
           (filter->hasVocalFilter() && _filteredSpells[i].components().hasVocal() != filter->vocalFilter()) ||
           (filter->hasSomaticFilter() && _filteredSpells[i].components().hasSomatic() != filter->somaticFilter()) ||
           (filter->hasMaterialFilter() && _filteredSpells[i].components().hasMaterial() != filter->materialFilter()) ||
           (filter->hasMaterialExpensiveFilter() && _filteredSpells[i].components().materialComponentIsExpensive() != filter->materialExpensiveFilter()) ||
           (filter->hasMaterialConsumedFilter() && _filteredSpells[i].components().expensiveMaterialComponentIsConsumed() != filter->materialConsumedFilter()))
        {
            toDelete.append(i);
            continue;
        }
    }

    for(int i : toDelete)
    {
        _filteredSpells.remove(i);
    }
}
