#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <math.h>
#include <sys/time.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include "dms/Util.h"

static char * versionString = "libdms OpenGL Class Library, Version 1.0 -"
                              " Compiled " __DATE__;

namespace dms
{

void checkGLError(const char *prefix)
    {
    GLenum err = glGetError();
    if (err != GL_NO_ERROR)
        printf("%s GL error '%s'\n",prefix,gluErrorString(err));
    }


void drawString(char *s,void *font)
    {
    while (*s)
        glutBitmapCharacter(font, *s++);
    }


void drawString(char *s,const Vector2& position,void *font)
    {
    glRasterPos2fv(position.vec);
    drawString(s,font);
    }


void drawString(char *s,const Vector3& position,void *font)
    {
    glRasterPos3fv(position.vec);
    drawString(s,font);
    }


void drawAxes(void)
    {
    Vector3::X_Axis.drawLine();
    drawString("X",Vector3::X_Axis,GLUT_BITMAP_TIMES_ROMAN_10);
    Vector3::Y_Axis.drawLine();
    drawString("Y",Vector3::Y_Axis,GLUT_BITMAP_TIMES_ROMAN_10);
    Vector3::Z_Axis.drawLine();
    drawString("Z",Vector3::Z_Axis,GLUT_BITMAP_TIMES_ROMAN_10);
    }


GLfloat degreesToRadians(GLfloat a)
    {
    return a * M_PI / 180.0f;
    }


GLfloat radiansToDegrees(GLfloat a)
    {
    return a * 180.0f / M_PI;
    }




float currentTime(void)
    {
    static struct timeval startTime;
    static int firstCall=1;
    struct timeval t;
    if (firstCall)
        {
        firstCall = 0;
        gettimeofday(&startTime, NULL);
        }
    gettimeofday(&t,NULL);
    return (t.tv_sec-startTime.tv_sec) +
           (t.tv_usec - startTime.tv_usec) / 1000000.0;
    }


static float dmsFrameTime = -1;
static float dmsDeltaTime = 1;


void beginFrame(void)
    {
    float t = currentTime();
    dmsDeltaTime = t - dmsFrameTime;
    dmsFrameTime = t;
    }


float frameTime(void)
    {
    return dmsFrameTime;
    }


float deltaTime(void)
    {
    return dmsDeltaTime;
    }


/* computeNormal - takes 3 vertex positions as input (v0, v1, v2), and
    returns a unit length normal vector for the polygon (normal) */
void computeNormal(const GLfloat *v0, const GLfloat *v1, const GLfloat *v2,
                   GLfloat *normal)
    {
    GLfloat A[3], B[3], product[3], length;
    A[0] = v2[0] - v1[0];
    A[1] = v2[1] - v1[1];
    A[2] = v2[2] - v1[2];
    B[0] = v0[0] - v1[0];
    B[1] = v0[1] - v1[1];
    B[2] = v0[2] - v1[2];
    product[0] = A[1] * B[2] - A[2] * B[1];
    product[1] = A[2] * B[0] - A[0] * B[2];
    product[2] = A[0] * B[1] - A[1] * B[0];
    length = sqrt(product[0]*product[0] + product[1]*product[1] +
                  product[2]*product[2]);
    if (length == 0)    /* If there's a problem, */
        {               /* return an arbitrary result */
        normal[0] = 0;
        normal[1] = 1;
        normal[2] = 0;
        }
    else
        {
        normal[0] = product[0] / length;
        normal[1] = product[1] / length;
        normal[2] = product[2] / length;
        }
    }


void computeNormal(const Vector3& v0, const Vector3& v1,
                        const Vector3& v2, Vector3& normal)
    {
    computeNormal(v0.vec, v1.vec, v2.vec, normal.vec);
    }


}
