#include "generator.hpp"

const int rototation[4][16] = {
     {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},
     {12,8,4,0, 13,9,5,1, 14,10,6,2, 15,11,7,3},
     {15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0},
     {3,7,11,15, 2,6,10,14, 1,5,9,13, 0,4,8,12}
};

generator::~generator()
{
    _map.clear();
}

bool generator::_matchRotation(char * it, int m, int n=0)
{
    for (int j=0;j<16;j++)
        if (*(_map[m] + j) != *(it+rototation[n][j]))
            return false;
    return true;
}

bool generator::alreadyHere(char * it)
{
    for (int i=0;i<_map.size();i++)
        for (int j=0;j<4;j++)
            if (_matchRotation(it,i,j))
                return true;
    return false;
}

void generator::build(int index, int nIce, int nWater)
{
    for (int i=0;i<3;i++)
    {
        switch(i)
        {
        case 0:
            _tmpMap[index] = 'E';
            break;
        case 1:
            _tmpMap[index] = 'B';
            break;
        case 2:
            _tmpMap[index] = 'I';
        }
        if (index<16)
            build(index+1, 
                  nIce+(_tmpMap[index]=='B'), 
                  nWater+(_tmpMap[index]=='E'));
        else if (nWater >= 6 && nIce >= 5)// && !alreadyHere(_tmpMap))
        {
            //cout << "found so far " << _map.size() << endl;
            _map.push_back(new char[16]);
            for (int j=0;j<16;j++)
                *(_map.back()+j) = _tmpMap[j];
        }
    }
}

void generator::build()
{
    build(0,0,0);
}

int generator::qty()
{
    return _map.size();
}

void generator::rawTest()
{
    brute * tmp;
    vector<char*>::iterator it;
    for (it=_map.begin();it!=_map.end();it++)
    {
        brute test(*it);
        test.force();
   
        if (test.failed())
        {
            cout << "removed ";
            for (int i=0;i<16;i++)
                cout << *((*it)+i) << (i%4==3?"\n":"");
            cout << _map.size() << " left\n";
            _map.erase(it);

        }
//        else
//        {
//            test.printMap(cout);
//            cout << "________\n";
//            test.print(cout);
//        }
    }
}

void generator::removeDupRot()
{
    vector<char*>::iterator it;
    for (it=_map.begin();it!=_map.end();it++)
    {
        if (alreadyHere(*it))
        {
            cout << "remove duplicate ";
            for (int i=0;i<16;i++)
                cout << *((*it)+i) << (i%4==3?"\n":"");
            cout << _map.size() << " left\n";
            _map.erase(it);
            
        }
    }
}

char * generator::operator[](const int i)
{
    assert(i<_map.size());
    return _map[i];
}
