#include "level.h"
#include "line2d.h"
#include "tinerxml.h"

#include "glex.h"
#include "simplefont.h"

#include "SDL/SDL.h"
#include "iostream"
using namespace std;

simplefontT myfont;
void level::init(Uint8* keys)
{
    myfont.BuildFont("font.tga");
    float WHYSCALE = 1;//named such, cos i cant remember why im scaling everything up...

    key = keys;

    winner = -2;

    int texnum = 0;
    int* texlist;

    xmlfile hoverlvl;
    TiXmlElement *xLevel = hoverlvl.getxmlfirstelement("hoverlvl.xml");
    {
        TiXmlElement *xTextures = hoverlvl.getelement(xLevel, "textures");

        gridtexid = LoadGLTexture(xTextures->Attribute("skytex"));
        texnum = hoverlvl.countchildren(xTextures);
        texlist = new int[texnum];
        texnum = 0;
        TiXmlElement *xTexturei = xTextures->FirstChildElement();
        while( xTexturei )
        {
            //lvltexture[texturenum].floor = atof(xTexturei->Attribute("floor"))*WHYSCALE;
            //lvltexture[texturenum].roof = atof(xTexturei->Attribute("roof"))*WHYSCALE;
            texlist[texnum] = LoadGLTexture(xTexturei->Attribute("texture"));
            texnum++;
            xTexturei = xTexturei->NextSiblingElement();
        }

        TiXmlElement *xVerts = hoverlvl.getelement(xLevel, "verts");
        vertnum = hoverlvl.countchildren(xVerts);
        lvlvert = new vector2d[vertnum];
        vertnum = 0;
        TiXmlElement *xVerti = xVerts->FirstChildElement();
        while( xVerti )
        {
            lvlvert[vertnum].setpos(atof(xVerti->Attribute("x"))*WHYSCALE, atof(xVerti->Attribute("y"))*WHYSCALE);
            vertnum++;
            xVerti = xVerti->NextSiblingElement();
        }


        TiXmlElement *xLines = hoverlvl.getelement(xLevel, "lines");
        linenum = hoverlvl.countchildren(xLines);
        lvlline = new line2d[linenum];
        linenum = 0;
        TiXmlElement *xLinei = xLines->FirstChildElement();
        while( xLinei )
        {
            //lvlline[linenum].p1 = &lvlvert[atoi(xLinei->Attribute("v1"))];
            //lvlline[linenum].p2 = &lvlvert[atoi(xLinei->Attribute("v2"))];
            lvlline[linenum].setup(lvlvert[atoi(xLinei->Attribute("v1"))],lvlvert[atoi(xLinei->Attribute("v2"))]);
            linenum++;
            xLinei = xLinei->NextSiblingElement();
        }


        TiXmlElement *xPolys = hoverlvl.getelement(xLevel, "polys");
        polynum = hoverlvl.countchildren(xPolys);
        lvlpoly = new poly2d[polynum];
        polynum = 0;
        TiXmlElement *xPolyi = xPolys->FirstChildElement();
        int checktex = 0;
        while( xPolyi )
        {
            lvlpoly[polynum].lnum = hoverlvl.countchildren(xPolyi);
            lvlpoly[polynum].l = new lc[lvlpoly[polynum].lnum];
            lvlpoly[polynum].floor = atof(xPolyi->Attribute("floor"))*WHYSCALE;
            lvlpoly[polynum].roof = atof(xPolyi->Attribute("roof"))*WHYSCALE;
            checktex = atoi(xPolyi->Attribute("ftex"));
            if(checktex >= 0)
                lvlpoly[polynum].floortex = texlist[checktex];
            else
                lvlpoly[polynum].floortex = -1;

            checktex = atoi(xPolyi->Attribute("rtex"));
            if(checktex >= 0)
                lvlpoly[polynum].rooftex = texlist[checktex];
            else
                lvlpoly[polynum].rooftex = -1;

            TiXmlElement *xPLinei = xPolyi->FirstChildElement();
            for(int i = 0;i<lvlpoly[polynum].lnum;i++)
            {
                lvlpoly[polynum].l[i].l = &lvlline[atoi(xPLinei->Attribute("l"))];
                checktex = atoi(xPLinei->Attribute("tex"));
                if(checktex >= 0)
                    lvlpoly[polynum].l[i].ltexid = texlist[checktex];
                else
                    lvlpoly[polynum].l[i].ltexid = -1;
                xPLinei = xPLinei->NextSiblingElement();
            }
            polynum++;
            xPolyi = xPolyi->NextSiblingElement();
        }



        dudenum = 2;
        dude = new player[dudenum];
        TiXmlElement *xStarts = hoverlvl.getelement(xLevel, "starts");
        //dudenum = countchildren(xStarts);//nono, this would be silly!
        //dude = new player[dudenum];//as would this!
        //dudenum = 0;
        TiXmlElement *xDudei = xStarts->FirstChildElement();
        int currentdude = 0;
        while( xDudei && currentdude<dudenum )
        {
            dude[currentdude].init(
                atof(xDudei->Attribute("x"))*WHYSCALE,
                atof(xDudei->Attribute("y"))*WHYSCALE,
                atof(xDudei->Attribute("z"))*WHYSCALE
            );
            //cout << "current dude is " << currentdude << endl;
            currentdude++;
            xDudei = xDudei->NextSiblingElement();
        }
        delete[] texlist;
    }
    hoverlvl.endxml();


    for (int pid = 0; pid <polynum;pid++)
    {
        //wallrangeT initialrange;
        //initialrange.low = lvlpoly[pid].floor;
        //initialrange.high = lvlpoly[pid].roof;
        for (int lid = 0; lid <lvlpoly[pid].lnum;lid++)
        {
            lvlpoly[pid].l[lid].low = lvlpoly[pid].floor;
            lvlpoly[pid].l[lid].high = lvlpoly[pid].roof;
            //    lvlpoly[pid].l[lid].range.push_back(initialrange);
        }
    }

    for (int pid = 0; pid <polynum;pid++)
    {
        for (int lid = 0; lid <lvlpoly[pid].lnum;lid++)
        {
            lvlpoly[pid].l[lid].alone = 1;
        }
    }
    for (int pid = 0; pid <polynum;pid++)
    {
        lvlpoly[pid].getcentre();
        lvlpoly[pid].sortflipped();
    }

    for (int pid = 0; pid <polynum;pid++)
    {
        for (int dip = 0; dip <polynum;dip++)
        {
            if(dip!=pid)
                for (int lid = 0; lid <lvlpoly[pid].lnum;lid++)
                {
                    for (int dil = 0; dil <lvlpoly[dip].lnum;dil++)
                    {
                        lvlpoly[pid].l[lid].checkagainst(lvlpoly[dip].l[dil]);
                    }
                }
        }
    }

    for (int pid = 0; pid <polynum;pid++)
    {
        wallrangeT initialrange;
        initialrange.low = lvlpoly[pid].floor;
        initialrange.high = lvlpoly[pid].roof;
        for (int lid = 0; lid <lvlpoly[pid].lnum;lid++)
        {
            //lvlpoly[pid].l[lid].low = lvlpoly[pid].floor;
            //lvlpoly[pid].l[lid].high = lvlpoly[pid].roof;
            if(lvlpoly[pid].l[lid].alone)
                lvlpoly[pid].l[lid].range.push_back(initialrange);
        }
    }



    dude[0].setrgb(1,0,0);
    dude[0].setdirkeys(SDLK_LSHIFT,274,276,275);//,303,305);
    dude[0].setotherkeys(SDLK_UP,SDLK_RCTRL,SDLK_TAB);
    if(dudenum>0)
    {
        dude[1].setrgb(0,1,1);

        dude[1].setdirkeys('w','s','a','d');//,304,306);
        dude[1].setotherkeys(65,65,65);
    }


    winpush = 0;
    winlimit = 1;

    //gridtexid = LoadGLTexture("img/GGR.png");
}

void level::update(float mxx, float myy)
{
    mx = mxx+camavg.x;
    my = myy+camavg.y;


    for (int i = 0; i <dudenum;i++)
    {
        dude[i].update();
    }
    //physicks
    float repeatnum = 2;
    for(int repeat = 0; repeat<repeatnum;repeat++)
    {
        //if(!repeat)
        for (int i = 0; i <dudenum;i++)
            dude[i].dophys(repeatnum);

        //input

        for (int i = 0; i <dudenum;i++)
        {
            dude[i].applyforces(key, repeatnum);
        }

        //DRAGGING A POINT
        if (mmb)
        {
            //lvlvert[dragpoint].c.setpos(mx,my);
            float mmbmulti = 0.01/repeatnum;
            float ammbmulti = 1-mmbmulti;
            dude[0].pos.c.x = dude[0].pos.c.x*ammbmulti + mx*mmbmulti;
        }

        //collision
        int colilits = 2;//why arnt i using a for loop? why should i?
        for (int i = 0; i <dudenum;i++)
        {
            dude[i].onground = 0;
        }
        while(colilits--)
        {

            for (int i = 0; i <dudenum;i++)
            {
                for (int r = 0; r <dudenum;r++)
                {
                    if(r!=i)
                        dude[i].playercol(dude[r]);
                }
                for (int pid = 0; pid <polynum;pid++)
                {
                    lvlpoly[pid].docolfloor(dude[i].pos, dude[i].onground);
                }
                for (int pid = 0; pid <polynum;pid++)
                {
                    lvlpoly[pid].docolwall(dude[i].pos, dude[i].onground);
                }
            }

        }
    }

    //GAMEGOALS
    /*for (int i = 0; i <dudenum;i++)
    {
        //dude[i].checktailcross(dude[i]);
        for (int r = 0; r <dudenum;r++)
        {
            //if(i!=r)
            {
                //cout << i << " vs " << r << endl;
                //cout << dude[i].c.x << " and " << dude[i].o.x << endl;
                dude[i].checktailcross(dude[r]);
            }
        }
    }*/
    //cout << dude[1].c.x << " and " << dude[1].o.x << endl;
    //cout << "newloop" << endl;


    winner = -2;


    /*if(!lvlpoly[0].pnpoly(dude[0].pos.c.x,dude[0].pos.c.x)){
        //winner = 1;
    }*/


    /*int numalive = 0;
       for (int i = 0; i <dudenum;i++)
       {
        //cout << "player " << i << " has " << dude[i].hp << " hp" << endl;
        if (dude[i].hp>0){
         numalive++;
         winner = i;
        }
       }*/
    //cout << "nuimalive is" << numalive << endl;

    //cout << "numalive is " << numalive << endl;
    //if (numalive > 1)winner = -2;
    //if (numalive > 1)winner = -2;
    //if (numalive == 0)winner = -1;



}
int gametime = 0;
void level::draw()
{
    glColor3f(1,1,1);
    float newscale = 1;
    glScalef(newscale, newscale, newscale);


    glBindTexture( GL_TEXTURE_2D, gridtexid);
    float xrot = -dude[0].dirangle/2;
    glDisable(GL_DEPTH_TEST);
    glPushMatrix();
    glTranslatef(0,0,-10);
    glScalef(7,7,7);
    glBegin(GL_QUADS);
    glTexCoord2f(1.0f-xrot, 1.0f);
    glVertex3f(  1.f,-1.f,0.f );
    glTexCoord2f(1.0f-xrot, 0.0f);
    glVertex3f(  1.f, 1.f,0.f );
    glTexCoord2f(0.0f-xrot, 0.0f);
    glVertex3f( -1.f, 1.f,0.f );
    glTexCoord2f(0.0f-xrot, 1.0f);
    glVertex3f( -1.f,-1.f,0.f );
    glEnd();
    glPopMatrix();
    glEnable(GL_DEPTH_TEST);


    camavg = dude[0].pos.c;//+dude[1].pos.c;
    //gluLookAt(camavg.x,camavg.y-150,150,camavg.x,camavg.y,0,0,1,0);
    vector2d v (-sinf(dude[0].dirangle), -cosf(dude[0].dirangle));
    gluLookAt(camavg.x+v.x*5,   camavg.y+v.y*5, 2+dude[0].pos.c.z,
              camavg.x,         camavg.y,       1+dude[0].pos.c.z,
              0,0,1);

    for (int i = 0; i <polynum;i++)
    {
        lvlpoly[i].draw();
    }
    //myShader->begin();
    for (int i = 0; i <dudenum;i++)
    {
        dude[i].draw();
    }
    glColor3f(1,1,1);
    //    static Uint32 next_time = 0;
    //Uint32 now = SDL_GetTicks();
    static float ctime = 0;
    float ntime = SDL_GetTicks();
    myfont.PrintText(0.0,0.0,"hi %i there!!", ntime-ctime);
    //myShader->end();
}

void level::close()
{
    delete[] lvlvert;
    //delete[] tlvlvert;
    delete[] lvlline;
    delete[] lvlpoly;
    delete[] dude;
}
