/*********************************************************************
*                                                                    *          
*                              FLY                                   *
*                           --E#Y#E--				     *
*                         (==MUSCLE==)                               *
*                                                                    *
*********************************************************************/

/* C++ Header Files */
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <fstream>
#include <iostream>
#include <vector>
#include <cmath>
#include <ctime>
#include <cassert>
#include <limits>
/* X11 */
#include <X11/keysym.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
/* OpenGL */
#include <GL/glew.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <GL/glu.h>
#include <GL/glext.h>
#include <GL/glxext.h>
/* Flysimulator */
#include "WIN/help.h"
#include "WIN/win.h"
#include "WIN/fps.h"
#include "NET/point.h"
#include "NET/network.h"
#include "TEX/targa.h"
#include "TEX/texture.h"
#include "CONF/config.h"
#include "CONF/uniform.h"
#include "CONF/geometry.h"
#include "FONT/font.h"
#include "OGL/move.h"
#include "OGL/cube.h"
#include "OGL/flybox.h"
#include "OGL/cockpit.h"
#include "OGL/opengl.h"

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

/* Standard */
using namespace std;

using std::vector;
using std::string;
using std::ifstream;
using std::map;

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

/* Class */
HELP help;
WIND wind;
FPS fps;
LEO leo;
FLY fly;
MOV mov;
MOD mod;
TMFONT font;
FLYBOX box;

/* Network */
Network server1;
Network server2;
Network client1;

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

/* Set our window settings */
const int width = 1280;
const int height = 640;
const int BPP = 16;

/* Settings */
bool fwindow, fgrid, fserver, fclient, fversion, fhelp, wide = false;

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

/* Loader */
void Loader()
 {   	
	/* Notation */
	char nmove[DC];
	
	nmove[1] =  0;
	nmove[2] =  0;
	nmove[3] = 24;
	nmove[4] =  4;
 
        /* Create Window */
        std::cerr << " ---[ Window ]--------------------------------- " << std::endl; 
        wind.createWin(width, height, BPP, wide);
        wind.createRender(width, height, BPP, wide);        
        
        /* FPS */
        fps.InitTimeCounter();
        
        /* Texture Loader */
        std::cerr << " ---[ Texture ]-------------------------------- " << std::endl; 
        box.textureLoader();
        fly.loadTexture();
        
        /* GLEW Status */
        std::cerr << " ---[ Library ]-------------------------------- " << std::endl; 
        fly.glewStatus();
                
        /* Network */
        std::cerr << " ---[ Network ]-------------------------------- " << std::endl; 
        std::cout << " NETWORK PORT: " << PORT << std::endl;

        /* Cord */
	leo.init_Cord();
        leo.make_Cord(nmove[1], nmove[2]);
	leo.print_info();
        leo.print_path(nmove);
 }

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

/* Flysimulator */
void Flysimu()
{
        const float dt = 0.00001;
  
        /* Landscape */
        fly.initMain();
        fly.Landscape(width, height);
        
        /* Motor */
        fly.pointGrid(dt);
        mov.motorGrid(dt);
        
        /* Cockpit */
        mov.Motor();
        mod.Cockpit(); 
        mov.Terminal();

        /* Display */
        wind.perspective(width, height);
        wind.loadFont();
        wind.eventloop(); 
         
        /* FPS */
        fps.CalculateFPS();
        fps.UpdateTimeCounter(dt); 
}

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

/* Server */
void Server()
 {
 	/* TCP Server Network */
        std::cerr << " ---[ Server ]--------------------------------- " << std::endl; 
	server1.socket();
	std::cerr << " TCP-SERVER: SOCKET " << std::endl;
	server1.bind(PORT);
	std::cerr << " TCP-SERVER: BIND " << std::endl;
	server1.listen();	
	std::cerr << " TCP-SERVER: LISTEN " << std::endl;
	while(true)
	{
		server1.accept(server2);
		std::cerr << " TCP-SERVER: ACCEPT " << std::endl;
		while(true)
		{
                        if(fgrid) {
                        Flysimu(); }		
		}
		server2.close();
	}	
	server1.close();
 }

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

/* Client */
void Client()
 {
        /* Server IP */
        char ipadr[DC];
 
 	/* TCP Client Network */
	std::cerr << " ---[ Client ]--------------------------------- " << std::endl; 
	printf(" SERVER IP: ");
	fgets(ipadr, DC, stdin);
	client1.socket();
	std::cerr << " TCP-CLIENT: SOCKET " << std::endl;
	client1.connect(ipadr,PORT);
	std::cerr << " TCP-CLIENT: CONNECT " << std::endl;
	while(true)
	{
                  if(fgrid) {
                  Flysimu(); }	
	}	
	client1.close();
 }

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

/* Main Program */
int main (int egac, char **egav) 
{
	/* Settings */	
	int n = 0;
	int f = 0;
		
	for(n = 0; n < egac; n++)
	{
	for(f = 0; f < egav[n][f]; ++f)
	{
	switch(egav[n][f])    
	{
		case 'F': wide = true; break;
		case 'W': fwindow = true; Loader(); break;
	        case 'S': fserver = true; Server(); break;
		case 'C': fclient = true; Client(); break;
	        case 'G': fgrid = true; while(fgrid) { Flysimu(); } break;
		case 'v': fversion = true; help.version(); break;
		case 'h': fhelp = true; help.Desk(egac); break;
	}}}
	 
	return 0;
}

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

