#include <iostream>
#include <SDL.h>
#include <SDL_opengl.h>
#include <SDL_image.h>
#include "polygon.h"
#include "xml.h"
#include "matrix_calc.h"
#include "triangle.h"
#include "vertex.h"
#include "Span.h"
#include "SpanC.h"
#include "scene_graph_pack.h"
#include "error.h"
#include "viewer_types.h"
using namespace std;




Polygon::Polygon()
{
    position_init();
}

void
Polygon::position_init(void)
{

    xyz[0] = 0;
    xyz[1] = 0;
    xyz[2] = 0;
    xyz[3] = 1;
    c_xyz[0] = 0;
    c_xyz[1] = 0;
    c_xyz[2] = 0;
    c_xyz[3] = 1;
    angle[0] = 0;
    angle[1] = 0;
    angle[2] = 0;
    angle[3] = 1;
    scale[0] = 1;
    scale[1] = 1;
    scale[2] = 1;


}

void Polygon::pickup_coordinate(char *cont)
{

    // size は頂点の数, count は面の数
    char *tmp_cont = cont;
    int count = size / 3;

    for (int i = 0; i < pp_num; i++) {

      TrianglePackPtr tri =  pp[i].tri;
      // TrianglePack の size のチェック
      int tri_size = (count < MAX_SIZE_TRIANGLE) ? count : MAX_SIZE_TRIANGLE ;
      pp[i].info.size = tri_size;

      for (int j = 0; j < tri_size; j++) {

	tmp_cont = pickup_float(tmp_cont, &(tri[j].ver1.x));
        tmp_cont = pickup_float(tmp_cont, &(tri[j].ver1.y));
        tmp_cont = pickup_float(tmp_cont, &(tri[j].ver1.z));

	tmp_cont = pickup_float(tmp_cont, &(tri[j].ver2.x));
        tmp_cont = pickup_float(tmp_cont, &(tri[j].ver2.y));
        tmp_cont = pickup_float(tmp_cont, &(tri[j].ver2.z));

	tmp_cont = pickup_float(tmp_cont, &(tri[j].ver3.x));
        tmp_cont = pickup_float(tmp_cont, &(tri[j].ver3.y));
        tmp_cont = pickup_float(tmp_cont, &(tri[j].ver3.z));

	if (tmp_cont == NULL)
	  {
            cout << "Analyzing obj data failed coordinate\n";
	  }

	count -= 1;
	
      }
          
    }

    if (count != 0) {
          printf("miss pickup_coordinate size. diff size = %d\n", count);
    }

}

void Polygon::pickup_normal(char *cont)
{


    // size は頂点の数, count は面の数
    char *tmp_cont = cont;
    int count = size / 3;

    for (int i = 0; i < pp_num; i++) {

      TrianglePackPtr tri =  pp[i].tri;
      // TrianglePack の size のチェック
      int tri_size = (count < MAX_SIZE_TRIANGLE) ? count : MAX_SIZE_TRIANGLE ;
      pp[i].info.size = tri_size;

      for (int j = 0; j < tri_size; j++) {

	tmp_cont = pickup_float(tmp_cont, &(tri[j].normal1.x));
        tmp_cont = pickup_float(tmp_cont, &(tri[j].normal1.y));
        tmp_cont = pickup_float(tmp_cont, &(tri[j].normal1.z));

	tmp_cont = pickup_float(tmp_cont, &(tri[j].normal2.x));
        tmp_cont = pickup_float(tmp_cont, &(tri[j].normal2.y));
        tmp_cont = pickup_float(tmp_cont, &(tri[j].normal2.z));

	tmp_cont = pickup_float(tmp_cont, &(tri[j].normal3.x));
        tmp_cont = pickup_float(tmp_cont, &(tri[j].normal3.y));
        tmp_cont = pickup_float(tmp_cont, &(tri[j].normal3.z));


	if (tmp_cont == NULL)
	  {
            cout << "Analyzing obj data failed coordinate\n";
	  }

	count -= 1;
	
      }
      
    
    }

    if (count != 0) {
          printf("miss pickup_normal size. diff size = %d\n", count);
    }

}

void Polygon::pickup_model(char *cont)
{
    cont = pickup_float(cont,c_xyz);
    cont = pickup_float(cont,c_xyz+1);
    cont = pickup_float(cont,c_xyz+2);

    if (cont == NULL)
    {
        cout << "Analyzing obj data failed model\n";
    }
}

void Polygon::pickup_texture(char *cont)
{

    char *tmp_cont = cont;
    int count = size / 3;

    for (int i = 0; i < pp_num; i++) {

      TrianglePackPtr tri =  pp[i].tri;
      // TrianglePack の size のチェック
      int tri_size = (count < MAX_SIZE_TRIANGLE) ? count : MAX_SIZE_TRIANGLE ;
      pp[i].info.size = tri_size;

      for (int j = 0; j < tri_size; j++) {

	tmp_cont = pickup_float(tmp_cont, &(tri[j].ver1.tex_x));
        tmp_cont = pickup_float(tmp_cont, &(tri[j].ver1.tex_y));

	tmp_cont = pickup_float(tmp_cont, &(tri[j].ver2.tex_x));
        tmp_cont = pickup_float(tmp_cont, &(tri[j].ver2.tex_y));

	tmp_cont = pickup_float(tmp_cont, &(tri[j].ver3.tex_x));
        tmp_cont = pickup_float(tmp_cont, &(tri[j].ver3.tex_y));


	if (tmp_cont == NULL)
	  {
            cout << "Analyzing obj data failed coordinate\n";
	  }

	count -= 1;
	
      }
      
    
    }

    if (count != 0) {
          printf("miss pickup_texture size. diff size = %d\n", count);
    }



}

char *get_pixel(int tx, int ty, SDL_Surface *texture_image)
{
    return (char*)texture_image->pixels+(texture_image->format->BytesPerPixel*((texture_image->w)*ty+tx));
}

unsigned my_ntohl(unsigned u) {
    //     rr gg bb 00
    //           rr
    //     bb gg rr
    //unsigned u1 =   ((u&0xff)<<24) +
    //         ((u&0xff00)<<8) +
    //         ((u&0xff0000)>>8) +
    //         ((u&0xff000000)>>24);
    unsigned u1;
    unsigned b = (u&0xff000000)>>24;
    unsigned g = (u&0xff0000)>>16;
    unsigned r = (u&0xff00)>>8;
    u1 = r + (g<<8) + (b<<16);
    //printf("pixel %x->%x\n",u,u1);
    return u1;
}

Uint32 Polygon::get_rgb(int tx, int ty)
{
    SDL_PixelFormat *fmt;
    //Uint32 temp, pixel;
    Uint8 red, green, blue;

    fmt = texture_info->texture_image->format;

    if (tx<0) tx = 0;
    if (texture_info->texture_image->w-1< tx) tx = texture_info->texture_image->w-1 ;
    if (ty<0) ty = 0;
    if (texture_info->texture_image->h-1< ty) ty = texture_info->texture_image->h-1 ;


    //SDL_LockSurface(texture_image);
    char *p = get_pixel(tx,ty,texture_info->texture_image);
    blue  = (Uint8) p[0];
    green = (Uint8) p[1];
    red   = (Uint8) p[2];

    //printf("tx = %d ty = %d ", tx,ty);
    //printf("pixel color =>  R: %d,  G: %d,  B: %d\n", red, green, blue);

    SDL_PixelFormat *pf = NULL;
    //pf = viewer->screen->format;

    //cout << SDL_MapRGB(pf, red, green, blue) << endl;
    return SDL_MapRGB(pf, red, green, blue);
}
