#include "endo.h"
#include "glext.h"
#include "logfile.c"
#include "timer.c"
#include "display.c"
#include "particle.c"
#include "collide.c"
#include "object.c"
#include "scope.c"
#include "xfile.c"
#include "input.c"
#include "menu.c"


//-----------------------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
    unsigned int u, i, updates_to_perform;


    // Read the display settings from the config file...
    open_logfile();
    log_message("------------------------------------------");
    log_message("%s v%3.1f", APPLICATION_NAME, VERSION_NUMBER);
    log_message("------------------------------------------");
    if(input_dll_setup() == FALSE)
    {
        log_message("ERROR:  Cannot continue without input DLL");
        exit(1);
    }
    menu_load_settings(global_settings_filename);
    if(display_setup() == FALSE)
    {
        log_message("ERROR:  display_setup() failed");
        exit(1);
    }
    display_setup_multitexture();


    // Load the initial .X file...
    xfile_load_object(global_object_filename, global_load_inverted);


    // Load the extra textures
    light_texture = display_load_texture_file_rgba("FILES\\LIGHT.TGA");
    camlight_texture = display_load_texture_file_rgba("FILES\\CAMLIGHT.TGA");
    whiteout_texture = display_load_texture_file_rgba("FILES\\WHITEOUT.TGA");
    sphere_texture = display_load_texture_file_rgba("FILES\\SPHERE.TGA");
    scope_texture = display_load_texture_file_rgba("FILES\\SCOPE.TGA");
    slideon_texture = display_load_texture_file_rgba("FILES\\SLIDEON.TGA");
    slideoff_texture = display_load_texture_file_rgba("FILES\\SLIDEOFF.TGA");
    slidebar_texture = display_load_texture_file_rgba("FILES\\SLIDEBAR.TGA");
    font_texture = display_load_texture_file_rgba("FILES\\FONT.TGA");
    menu_texture[0] = display_load_texture_file_rgba("FILES\\MENU0.TGA");
    menu_texture[1] = display_load_texture_file_rgba("FILES\\MENU1.TGA");
    menu_texture[2] = display_load_texture_file_rgba("FILES\\MENU2.TGA");
    menu_texture[3] = display_load_texture_file_rgba("FILES\\MENU3.TGA");
    button_texture[0] = display_load_texture_file_rgba("FILES\\BUTTON0.TGA");
    button_texture[1] = display_load_texture_file_rgba("FILES\\BUTTON1.TGA");
    button_texture[2] = display_load_texture_file_rgba("FILES\\BUTTON2.TGA");
    button_texture[3] = display_load_texture_file_rgba("FILES\\BUTTON3.TGA");
    button_texture[4] = display_load_texture_file_rgba("FILES\\BUTTON4.TGA");
    button_texture[5] = display_load_texture_file_rgba("FILES\\BUTTON5.TGA");
    button_texture[6] = display_load_texture_file_rgba("FILES\\BUTTON6.TGA");
    button_texture[7] = display_load_texture_file_rgba("FILES\\BUTTON7.TGA");
    button_texture[8] = display_load_texture_file_rgba("FILES\\BUTTON8.TGA");
    button_texture[9] = display_load_texture_file_rgba("FILES\\BUTTON9.TGA");
    button_texture[10] = display_load_texture_file_rgba("FILES\\BUTTONA.TGA");
    button_texture[11] = display_load_texture_file_rgba("FILES\\BUTTONB.TGA");
    button_texture[12] = display_load_texture_file_rgba("FILES\\BUTTONC.TGA");
    button_texture[13] = display_load_texture_file_rgba("FILES\\BUTTOND.TGA");




    // Setup the endoscope...
    scope_initialize(global_scope_control_points, global_scope_length, global_scope_radius, 0.0f, 0.0f, global_scope_length/(global_scope_control_points+1));



    // Do the main loop...
    log_message("Starting main loop");
    timer_start();
	while(main_loop_active)
    {
        // Handle controls...
        input_read();
        input_camera_controls();




debug_space = key_down[SDLK_SPACE];

        // Determine how many updates to perform...
        updates_to_perform = timer_poll();
        repeat(u, updates_to_perform)
        {
            menu_update();
        }
        if(!global_permanent_whiteout)
        {
            global_whiteout_amount -= (updates_to_perform*global_whiteout_drain);
            global_whiteout_amount = (global_whiteout_amount > 0.0f) ? global_whiteout_amount : 0.0f;
        }
        global_tally_timer -= updates_to_perform;
        global_tally_timer = (global_tally_timer > 0) ? global_tally_timer : 0;
        if(global_tally_in_contact)
        {
            global_tally_contact_time += ((float) updates_to_perform) / ((float) UPDATES_PER_SECOND);
        }
        global_tally_in_contact = FALSE;
//        if(updates_to_perform > 4)
//        {
//            updates_to_perform = 4;
//        }
updates_to_perform = 1;



        if(key_pressed[SDLK_a])
        {
            object_auto_texpos();
        }



        // Clear the display...
        display_clear_buffers();


scope_camera(FALSE);
display_texture_off();


        // Do the physics simulation...
        if(!key_down[SDLK_p])
        {
            scope_clear_collision_list();
            repeat(u, updates_to_perform)
            {
                object_update();
                object_calculate_normals();
                object_keep_welded_vertices_together();
                input_limit();
                repeat(i, 5)
                {
                    scope_handle_entry_area();
                    scope_physics_update();
                    scope_handle_entry_area();
                    scope_physics_update();
                    scope_move_head(global_dll_headangle, 5);
                    scope_collide();
                }
                target_xyz[X]+=target_xyz[VX];
                target_xyz[Y]+=target_xyz[VY];
                target_xyz[Z]+=target_xyz[VZ];
                target_xyz[VX]*=CAMERA_DAMPEN;
                target_xyz[VY]*=CAMERA_DAMPEN;
                target_xyz[VZ]*=CAMERA_DAMPEN;
                object_keep_welded_vertices_together();
            }
        }














        // Setup the camera
        if(global_scope_cam)
        {
            // Draw the scope camera's scene...
            scope_camera(FALSE);
            glViewport(0, 0, screen_x, screen_y);
            scope_determine_spline();
            scope_draw();
            repeat(i, num_object)
            {
                object_draw((unsigned char) i, 0);
            }
        }
        else
        {
            // Change our projection matrix to accomodate a split screen view...
            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();
            glFrustum(-0.2, 0.2, -0.3, 0.3, ZNEAR, MAX_TERRAIN_DISTANCE);
            glMatrixMode(GL_MODELVIEW);



            // Draw the 90' right-angle external camera's scene...
            scope_camera(TRUE);
            glViewport((int) (screen_x*0.5f), 0, (int) (screen_x*0.5f), (int) (screen_y));
            scope_determine_spline();
            scope_draw();
            repeat(i, num_object)
            {
                object_draw((unsigned char) i, 0);
            }
            repeat(i, num_object)
            {
                object_draw((unsigned char) i, 1);
            }
            if(object_draw_spring)
            {
                object_draw_weight_hack();
            }



            // Draw the normal external camera's scene...
            scope_camera(FALSE);
            glViewport(0, 0, (int) (screen_x*0.5f), (int) (screen_y));
            scope_draw();
            repeat(i, num_object)
            {
                object_draw((unsigned char) i, 0);
            }
            repeat(i, num_object)
            {
                object_draw((unsigned char) i, 1);
            }
            if(object_draw_spring)
            {
                object_draw_weight_hack();
            }


            // Revert our projection matrix back to normal...
            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();
            glFrustum(-0.4, 0.4, -0.3, 0.3, ZNEAR, MAX_TERRAIN_DISTANCE);
            glMatrixMode(GL_MODELVIEW);
        }










        // Draw the options menu...
        glViewport(0, 0, screen_x, screen_y);
        menu_draw();


        // Display everything once it's drawn...
		display_swap();
        global_frame++;
    }



    return 0;
}

//-----------------------------------------------------------------------------------------------
