#include "aliens.h"

//using std::vector;

Aliens::Aliens(int TmpDestx, int TmpDesty, int afw, int afh, int alcellsize)
{
    cellsize = alcellsize;
    DestPoint.setX(TmpDestx - 1);
    DestPoint.setY(TmpDesty);
    fw = afw;
	fh = afh;
    //AliensCnt = -1;
    CurWave = -1;
    Cells = new int*[fw];
    TmpCells = new int*[fw];
	for (int i = 0; i < fw; i++) {
        Cells[i] = new int[fh];
        TmpCells[i] = new int[fh];
	}
    clearCells();
    Alien al;
    al.PicType = 0;
    al.PathIndex = 1;
    al.PicFrame = 0;
    al.Speed = 0.1;
    srcAliens.push_back(al);
    CurWave = 0;
}


bool Aliens::loadPixmaps(Alien * al)
{
    if (AliensPixmaps.size() != 0) {
        for (int i = 0; i < AliensPixmaps.size(); i++) {
            if (AliensPixmaps[i].type == al->PicType) {
                qDebug() << "Pictures exist!";
                return true;
            }
        }
    }
    AlienImages * pixmaps;
    pixmaps = new AlienImages;
    if (loadPixmap(al->PicType,pixmaps) > 0) AliensPixmaps.push_back(* pixmaps);
    else return false;
    qDebug() << "Pictures loaded!";
    return true;
}


int Aliens::loadPixmap(int PicType, AlienImages * pixmaps)
{
    int i = 1;
    QString str1,str2;
    QPixmap tmpAlPixmap;
    str1.setNum(i);
    str2.setNum(PicType);
    qDebug() << PicType;
    while (i != 0) {
        str1.setNum(i);
        tmpAlPixmap.load("./images/Aliens/Al_" + str2 + "_" + str1 + ".png");
        //qDebug() << tmpAlPixmap.isNull();
        if (!tmpAlPixmap.isNull()) {
            //AlienPix.push_back(tmpAlPixmap);
            pixmaps->pix.push_back(tmpAlPixmap);
            pixmaps->type = PicType;
            tmpAlPixmap = 0;
            i++;
        }
        else i = 0;
    }
    qDebug() << "pictures:" << pixmaps->pix.size();
    return pixmaps->pix.size();
}


void Aliens::clearCells()
{
    for (int i = 0; i < fw; i++) for (int j = 0; j < fh; j++) Cells[i][j] = 0;
}


bool Aliens::AddAlien()
{
    //bool ok;
    //Alien al;
    //AliensCnt++;
    //if (CurWave < 0) CurWave = 0;
    //if (AliensCnt > curAliens.size()) ReDim Preserve Aliens(AliensCnt) As Alien
    //Aliens(AliensCnt) = SrcAliens(CurWave)
    curAliens.push_back(srcAliens.at(CurWave));
    //curAliens[AliensCnt].Level = CurWave + 1;
    curAliens[curAliens.size()-1].Position.pnt.setX(0*cellsize);
    curAliens[curAliens.size()-1].Position.pnt.setY(fh/2*cellsize); //(int)(fh/2+(1-0.58)*6);
    //DestPoint.setX(fw - 1);
    //DestPoint.setY(fh / 2); //curAliens[AliensCnt].Position.pnt.y();
    curAliens[curAliens.size()-1].DestPnt = DestPoint;
//    curAliens[AliensCnt].MaxFrame = 0;  //srcAliens[CurWave].MaxFrame;
//    curAliens[AliensCnt].PicFrame = 0;
    for (int i = 0; i < fw; i++) {
        for (int j = 0; j < fh; j++) TmpCells[i][j] = Cells[i][j];
    }
    return (CreatePath(&curAliens[curAliens.size()-1]) && loadPixmaps(&curAliens[curAliens.size()-1]));
}


bool Aliens::CreatePath(Alien * al)
{
    QPointF tp;
    QVector<QPointF> tmpPnt;
    if (WaveTrace(al))
    {
        for (int j=0; j<4; j++)
        {
            tmpPnt.clear();
            tp = al->path[0];
            //qDebug() << al->path.at(0);
            tmpPnt.push_back(tp);
            for (int i = 0; i < al->path.size() - 1; i++)
            {
                tp.setX((al->path[i].x() + al->path[i + 1].x()) / 2);
                tp.setY((al->path[i].y() + al->path[i + 1].y()) / 2);
                tmpPnt.push_back(tp);
            }
            tp = al->path[al->path.size() - 1];
            tmpPnt.push_back(tp);
            //qDebug() << tmpPnt.size();
            al->path = tmpPnt;
            al->Position.pnt.setX(al->path.at(0).x()*cellsize);
            al->Position.pnt.setY(al->path.at(0).y()*cellsize);
        }
        tmpPnt.clear();
        return true;
    }
    return false;
}


void Aliens::updateAliens()
{
    for (int i = 0; i < curAliens.size(); i++) updateAlienPos(&curAliens[i]);
}


void Aliens::updateAlienPos(Alien * al)
{
    float arctg = 0;
    qreal dx,dy,fdx,fdy;
    dx = (al->path[al->PathIndex - 1].x() - al->path.at(al->PathIndex).x());
    dy = (al->path[al->PathIndex - 1].y() - al->path.at(al->PathIndex).y());
    qDebug("=========");
    qDebug() << dx << ";" << dy;
    qDebug() << al->path[al->PathIndex];
    qDebug() << al->path[al->PathIndex-1];
    if (al->PathIndex + 1 < al->path.size()) {
        fdx = al->Position.pnt.x() - al->path.at(al->PathIndex+1).x()*cellsize;
        fdy = al->Position.pnt.y() - al->path.at(al->PathIndex+1).y()*cellsize;
        if (fdy != 0) arctg = atanf(fdx/fdy);
        else  if (fdx < 0) arctg = -3.1415/2;
              else arctg = 3.1415/2;
    }
    //qDebug() << fdx << ";" << fdy;
    al->Position.angle = 180*(-arctg)/3.1415;
    if (fdy < 0) al->Position.angle = 180 + al->Position.angle;
    qDebug() << al->Position.angle;
    if (qAbs(dx) < 1 && qAbs(dy) < 1) al->PathIndex++;
    else {
        al->Position.pnt.setX(al->Position.pnt.x()-dx*al->Speed);
        al->Position.pnt.setY(al->Position.pnt.y()-dy*al->Speed);
    }
    qDebug() << al->Position.pnt;
    al->PicIndex++;

    if (al->PicIndex >= AliensPixmaps[al->PicType].pix.size()) al->PicIndex = 0;
    if (al->PathIndex >= al->path.size()) {
        qDebug() << "run agan";
        al->PathIndex = 1;
        al->Position.pnt.setX(al->path.at(0).x()*cellsize);
        al->Position.pnt.setY(al->path.at(0).y()*cellsize);
    }
}


/*bool Aliens::PathIntersect(Alien* Al, Rectangle rect)
{
    //PathIntersect = False
    for (int i = Al->PathIndex; i<=Al->path.size(); i++) // To UBound(Al.path(), 1)
        if (Al->path[i].x + 0.5 >= rect.x0 - 1 && Al->path[i].x + 0.5 <= rect.x1 + 1)
            if (Al->path[i].y + 0.5 >= rect.y0 - 1 && Al->path[i].y + 0.5 <= rect.y1 + 1)
                return true; //PathIntersect = True //Exit Function
    return false;
}*/


bool Aliens::recreatePath()
{
    //QPointF ap;
    bool trace;
    for (int i = 0; i < fw; i++)
        for (int j = 0; j < fh; j++) TmpCells[i][j] = Cells[i][j];
    for (int i = 0; i < curAliens.size(); i++) {
        //ap = curAliens[i].Position.pnt;
        //curAliens[i].Position.pnt.setX(0);
        //curAliens[i].Position.pnt.setY(fh/2);
        qDebug() << "Alinen N" << i;
        curAliens[i].path.clear();
        trace = CreatePath(&curAliens[i]);
        if (!trace) return false;
        //curAliens[i].Position.pnt = ap;
    }
    return true;
}


bool Aliens::WaveTrace(Alien * al)
{
	bool stop = false;
	int step = 2;
    QPoint cp, tp;
	QRect fr(0, 0, fw, fh);
    QVector<QPoint> tmpp, curp;
    cp.setX(al->Position.pnt.x()/cellsize);
    cp.setY(al->Position.pnt.y()/cellsize);
    curp.push_back(cp);
    TmpCells[cp.x()][cp.y()] = 1;
	while (!stop) {
        //qDebug() << "trace";
        tmpp = curp;
		curp.clear();
        qDebug() << tmpp.size();
		stop = true;
        for (int i = 0; i < tmpp.size(); i++) {
			cp = tmpp[i];
			if (cp == al->DestPnt) {
                TmpCells[cp.x()][cp.y()] = step;
                qDebug() << "Wawe trace done";
				InvWaveTrace(cp, step, al);
				qDebug() << al->path.size();
				return true;
			}
			tp.setX(cp.x() - 1);
			tp.setY(cp.y());
            if (fr.contains(tp) && TmpCells[tp.x()][tp.y()] == 0) {
                TmpCells[tp.x()][tp.y()] = step;
				curp.push_back(tp);
				stop = false;
			}
			tp.setX(cp.x() + 1);
            if (fr.contains(tp) && TmpCells[tp.x()][tp.y()] == 0) {
                TmpCells[tp.x()][tp.y()] = step;
				curp.push_back(tp);
				stop = false;
			}
			tp.setX(cp.x());
			tp.setY(cp.y() - 1);
            if (fr.contains(tp) && TmpCells[tp.x()][tp.y()] == 0) {
                TmpCells[tp.x()][tp.y()] = step;
				curp.push_back(tp);
				stop = false;
			}
			tp.setY(cp.y() + 1);
            if (fr.contains(tp) && TmpCells[tp.x()][tp.y()] == 0) {
                TmpCells[tp.x()][tp.y()] = step;
				curp.push_back(tp);
				stop = false;
			}
		}
		step++;
	}
    qDebug() << "false wawetrace";
	return false;
}


void Aliens::InvWaveTrace(QPoint cp, int cnt, Alien * al)
{
	QPoint wp, Ppnt;
    int Ind, c, AliensTmpDestX, AliensTmpDestY, xpp, ypp, xnn, ynn;
	unsigned char chk;
	Ppnt = wp = cp;
    xnn=0;
    xpp=0;
    ynn=0;
    ypp=0;
    cnt--;
    al->path.push_front(Ppnt);
	AliensTmpDestX = al->Position.pnt.x();
	AliensTmpDestY = al->Position.pnt.y();
	while (cnt > 1)
    {
		cnt--;
        chk = 0;
        Ind = 0;
        c = 0;
        if (wp.x() - 1 >= 0 && TmpCells[wp.x()-1][wp.y()] == cnt)
        {
			chk = chk | 0x01;
            c++;
        }
        if (wp.x() + 1 < fw && TmpCells[wp.x()+1][wp.y()] == cnt)
        {
            chk = chk | 0x02;
            c++;
        }
        if (wp.y() - 1 >= 0 && TmpCells[wp.x()][wp.y()-1] == cnt)
        {
            chk = chk | 0x04;
            c++;
        }
        if (wp.y() + 1 < fh && TmpCells[wp.x()][wp.y()+1] == cnt)
        {
            chk = chk | 0x08;
            c++;
        }
        if (c == 0 || chk == 0) qDebug() << "ERROR!!!";
        if (c > 1)
        {
            if ((chk & 0x01)==0x01 && (chk & 0x04)==0x04)
            {
                if (xnn <= ynn && Ind == 0){
                    wp.rx()--;
                    xnn++;
                    if (xnn == ynn) xnn++;
                    Ind = 1;
                } else if (Ind == 0) {
                    wp.ry()--;
                    ynn++;
                    ynn++;
                    Ind = 1;
                }
            }
            if ((chk & 0x02)==0x02 && (chk & 0x04)==0x04)
            {
                if (xpp <= ynn && Ind == 0){
                    wp.rx()++;
                    xpp++;
                    if (xpp == ynn) xpp++;
                    Ind = 1;
                } else if (Ind == 0) {
                    wp.ry()--;
                    ynn++;
                    ynn++;
                    Ind = 1;
                }
            }
            if ((chk & 0x01)==0x01 && (chk & 0x08)==0x08)
            {
                if (xnn <= ypp && Ind == 0){
                    wp.rx()--;
                    xnn++;
                    if (xnn == ypp) xnn++;
                    Ind = 1;
                } else if (Ind == 0) {
                    wp.ry()++;
                    ypp++;
                    ypp++;
                    Ind = 1;
                }
            }
            if ((chk & 0x02)==0x02 && (chk & 0x08)==0x08)
            {
                if (xpp <= ypp && Ind == 0){
                    wp.rx()++;
                    xpp++;
                    if (xpp == ypp) xpp++;
                    Ind = 1;
                } else if (Ind == 0) {
                    wp.ry()++;
                    ypp++;
                    ypp++;
                    Ind = 1;
                }
            }
        }
        if (c == 1 || Ind == 0)
        {
            xnn=0;
            xpp=0;
            ynn=0;
            ypp=0;
            if ((chk & 0x01)==0x01) {
                wp.rx()--;
                xnn++;
            }
            else if ((chk & 0x02)==0x02) {
                wp.rx()++;
                xpp++;
            }
            else if ((chk & 0x04)==0x04) {
                wp.ry()--;
                ynn++;
            }
            else if ((chk & 0x08)==0x08) {
                wp.ry()++;
                ypp++;
            }
        }
		Ppnt = wp;
        al->path.push_front(Ppnt);
    }
}


void Aliens::clearAliens()
{
    curAliens.clear();
}
