#include <unistd.h>
#include <GL/glut.h>


#include "globals.h"
#include "sizes.h"
#include "sound.h"
#include "network.h"
#include "netdata.h"
#include "key.h"
#include "menu.h"
#include "thread.h"
#include "score.h"
#include "configuration.h"
#include "serverconfig.h"
#include "object.h"
#include "screen.h"
#include "netvariables.h"
#include "ship.h"


void KeyDown(unsigned char key, int x, int y);
void KeyUp(unsigned char key, int x, int y);
void MainMenuSpecialKey(int key, int x, int y);
void ConfMenuSpecialKey(int key, int x, int y);
void ScoreMenuSpecialKey(int key, int x, int y);
void MainMenuKey(unsigned char key, int x, int y);
void ScoreMenuKey(unsigned char key, int x, int y);
void SetKeyValueKey(unsigned char key, int x, int y);
void TextEntryKey(unsigned char key, int x, int y);
void ScoreEntryKey(unsigned char key, int x, int y);
void IntTextEntryKey(unsigned char key, int x, int y);


ControlStruct controls;


// Function to handle key presses while game is running
void KeyDown(unsigned char key, int x, int y)
{
  int rc;

  if (!Ships[myShip]) {
    return;
  }

  if (key==controls.Fire) {
    if (Ships[myShip]->Lives) {
      TellServer(FIRE_KEY, 1);
    } else {
      TellServer(ABORT_KEY, 1);
      GameStop=1;

      CleanupSounds();

      rc=pthread_join(ServerThread, NULL);
      if (!rc) {
        ReadServerConfig(ServerConfigFileName);
      }
      pthread_mutex_unlock(&ClientLock);

      if (CheckForHighScore()) {
        // If a high score is obtained, ask player to enter name for list
        playsound(HighScoreSound);
        *HighScoreName=0;
        TextValue=HighScoreName;
        MaxTextLength=MAX_PLAYERNAME_LENGTH-1;
        InitMatrixMode();
        glutKeyboardFunc(ScoreEntryKey);
        glutKeyboardUpFunc(NULL);
        glutSpecialFunc(NULL);
        glutIdleFunc(NULL);
        glutDisplayFunc(ScoreEntry);
        ScoreEntry();
      } else {
        InitMatrixMode();
        SetupMainMenu();
      }
    }
  }

  /*
    if (key==controls.xForward) {
    KeyValues.xForwardKey=1;
    TellServer(X_FORWARD_KEY, 1);
    } else if (key==controls.xBackward) {
    KeyValues.xBackwardKey=1;
    TellServer(X_BACKWARD_KEY, 1);
    }
    if (key==controls.yForward) {
    KeyValues.yForwardKey=1;
    TellServer(Y_FORWARD_KEY, 1);
    } else if (key==controls.yBackward) {
    KeyValues.yBackwardKey=1;
    TellServer(Y_BACKWARD_KEY, 1);
    }
  */
  if (key==controls.zForward) {
    Ships[myShip]->Thrusting=1;
    KeyValues.zForwardKey=1;
    TellServer(Z_FORWARD_KEY, 1);
    if (Ships[myShip]) {
      if (Ships[myShip]->Alive) {
        if (ThrustSoundNum==-1) {
          ThrustSoundNum=playsoundinloop(ThrustSound);
        }
      }
    }
  } else if (key==controls.zBackward) {
    KeyValues.zBackwardKey=1;
    TellServer(Z_BACKWARD_KEY, 1);
  }

  if (key==controls.xFRotate) {
    KeyValues.xFRotateKey=1;
    TellServer(X_FROTATE_KEY, 1);
  } else if (key==controls.xBRotate) {
    KeyValues.xBRotateKey=1;
    TellServer(X_BROTATE_KEY, 1);
  }
  if (key==controls.yFRotate) {
    KeyValues.yFRotateKey=1;
    TellServer(Y_FROTATE_KEY, 1);
  } else if (key==controls.yBRotate) {
    KeyValues.yBRotateKey=1;
    TellServer(Y_BROTATE_KEY, 1);
  }
  if (key==controls.zFRotate) {
    KeyValues.zFRotateKey=1;
    TellServer(Z_FROTATE_KEY, 1);
  } else if (key==controls.zBRotate) {
    KeyValues.zBRotateKey=1;
    TellServer(Z_BROTATE_KEY, 1);
  }

  if (key==controls.Shield) {
    if (Ships[myShip]) {
      if (!Ships[myShip]->Shield && Ships[myShip]->Alive) {
        playsound(NoShieldSound);
      }
      if (Ships[myShip]->Alive && Ships[myShip]->Shield) {
        if (ShieldSoundNum==-1) {
          ShieldSoundNum=playsoundinloop(ShieldOnSound);
        }
      }
    }
    KeyValues.ShieldKey=1;
    TellServer(SHIELD_KEY, 1);
  }

  if (key==controls.Warp) {
    KeyValues.WarpKey=1;
    TellServer(WARP_KEY, 1);
  }

  if (key==controls.Nuke) {
    KeyValues.NukeKey=1;
    TellServer(NUKE_KEY, 1);
  }

  if (key==controls.Score) {
    ShowScore=1;
  }

  if (key==controls.rView) {
    ReverseView=1;
  }

  if (key==controls.Quit) {
    AbortGame();
  }
}


// Function to handle game releases while game is running
void KeyUp(unsigned char key, int x, int y)
{
  /*
    if (key==controls.xForward) {
    KeyValues.xForwardKey=0;
    TellServer(X_FORWARD_KEY, 0);
    } else if (key==controls.xBackward) {
    KeyValues.xBackwardKey=0;
    TellServer(X_BACKWARD_KEY, 0);
    }
    if (key==controls.yForward) {
    KeyValues.yForwardKey=0;
    TellServer(Y_FORWARD_KEY, 0);
    } else if (key==controls.yBackward) {
    KeyValues.yBackwardKey=0;
    TellServer(Y_BACKWARD_KEY, 0);
    }
  */
  if (key==controls.zForward) {
    Ships[myShip]->Thrusting=0;
    KeyValues.zForwardKey=0;
    TellServer(Z_FORWARD_KEY, 0);
    if (ThrustSoundNum!=-1) {
      stopsoundinloop(ThrustSoundNum);
      ThrustSoundNum=-1;
    }
  } else if (key==controls.zBackward) {
    KeyValues.zBackwardKey=0;
    TellServer(Z_BACKWARD_KEY, 0);
  }

  if (key==controls.xFRotate) {
    KeyValues.xFRotateKey=0;
    TellServer(X_FROTATE_KEY, 0);
  } else if (key==controls.xBRotate) {
    KeyValues.xBRotateKey=0;
    TellServer(X_BROTATE_KEY, 0);
  }
  if (key==controls.yFRotate) {
    KeyValues.yFRotateKey=0;
    TellServer(Y_FROTATE_KEY, 0);
  } else if (key==controls.yBRotate) {
    KeyValues.yBRotateKey=0;
    TellServer(Y_BROTATE_KEY, 0);
  }
  if (key==controls.zFRotate) {
    KeyValues.zFRotateKey=0;
    TellServer(Z_FROTATE_KEY, 0);
  } else if (key==controls.zBRotate) {
    KeyValues.zBRotateKey=0;
    TellServer(Z_BROTATE_KEY, 0);
  }

  if (key==controls.Shield) {
    KeyValues.ShieldKey=0;
    TellServer(SHIELD_KEY, 0);
    if (ShieldSoundNum!=-1) {
      stopsoundinloop(ShieldSoundNum);
      ShieldSoundNum=-1;
    }
  }

  if (key==controls.Score) {
    ShowScore=0;
  }

  if (key==controls.rView) {
    ReverseView=0;
  }
}


void MainMenuSpecialKey(int key, int x, int y)
{
  switch (key) {
  case GLUT_KEY_UP:
    playsound(BonkSound);
    MainMenuItemHighlighted--;
    if (MainMenuItemHighlighted < 0) {
      MainMenuItemHighlighted=NumMainMenuItems-1;
    }
    break;
  case GLUT_KEY_DOWN:
    playsound(BonkSound);
    MainMenuItemHighlighted++;
    if (MainMenuItemHighlighted >= NumMainMenuItems) {
      MainMenuItemHighlighted=0;
    }
    break;
  }
  MainMenu();
}


void ConfMenuSpecialKey(int key, int x, int y)
{
  switch (key) {
  case GLUT_KEY_UP:
    playsound(BonkSound);
    ConfMenuItemHighlighted--;
    if (ConfMenuItemHighlighted < 0) {
      ConfMenuItemHighlighted=NumConfMenuItems-1;
    }
    break;
  case GLUT_KEY_DOWN:
    playsound(BonkSound);
    ConfMenuItemHighlighted++;
    if (ConfMenuItemHighlighted >= NumConfMenuItems) {
      ConfMenuItemHighlighted=0;
    }
    break;
  }
  ConfMenu();
}


void ScoreMenuSpecialKey(int key, int x, int y)
{
  switch (key) {
  case GLUT_KEY_UP:
    playsound(BonkSound);
    ScoreMenuItemHighlighted--;
    if (ScoreMenuItemHighlighted < 0) {
      ScoreMenuItemHighlighted=NumScoreMenuItems-1;
    }
    break;
  case GLUT_KEY_DOWN:
    playsound(BonkSound);
    ScoreMenuItemHighlighted++;
    if (ScoreMenuItemHighlighted >= NumScoreMenuItems) {
      ScoreMenuItemHighlighted=0;
    }
    break;
  }
  ScoreMenu();
}


void MainMenuKey(unsigned char key, int x, int y)
{
  if (key=='\r') {
    MainMenuItemSelected();
  }
}


void ConfMenuKey(unsigned char key, int x, int y)
{
  if (key=='\r') {
    ConfMenuItemSelected();
  }
}


void ScoreMenuKey(unsigned char key, int x, int y)
{
  if (key=='\r') {
    ScoreMenuItemSelected();
  }
}


void SetKeyValueKey(unsigned char key, int x, int y)
{
  *KeyValue=key;

  glutKeyboardFunc(ConfMenuKey);
  glutSpecialFunc(ConfMenuSpecialKey);
  glutIdleFunc(NULL);
  glutDisplayFunc(ConfMenu);
  ConfMenu();
}


void TextEntryKey(unsigned char key, int x, int y)
{
  int i;

  if (key=='\b') {
    i=strlen(TextValue);
    *(TextValue+i-1)='\0';
    TextEntry();
  } else if (key=='\r') {
    glutKeyboardFunc(ConfMenuKey);
    glutSpecialFunc(ConfMenuSpecialKey);
    glutIdleFunc(NULL);
    glutDisplayFunc(ConfMenu);
    ConfMenu();
  } else {
    i=strlen(TextValue);
    if (i<MaxTextLength) {
      *(TextValue+i)=key;
      *(TextValue+i+1)='\0';
    }
    TextEntry();
  }
}


void ScoreEntryKey(unsigned char key, int x, int y)
{
  int i;

  if (key=='\b') {
    i=strlen(TextValue);
    *(TextValue+i-1)='\0';
    ScoreEntry();
  } else if (key=='\r') {
    playsound(LuckySound);
    AddHighScore(TextValue);
    SetupScoreMenu();
  } else {
    i=strlen(TextValue);
    if (i<MaxTextLength) {
      *(TextValue+i)=key;
      *(TextValue+i+1)='\0';
    }
    ScoreEntry();
  }
}


void IntTextEntryKey(unsigned char key, int x, int y)
{
  int i;
  char Value[80];

  sprintf(Value, "%d", *IntValue);

  if (key=='\b') {
    i=strlen(Value);
    *(Value+i-1)='\0';
    *IntValue=atoi(Value);
    IntTextEntry();
  } else if (key=='\r') {
    glutKeyboardFunc(ConfMenuKey);
    glutSpecialFunc(ConfMenuSpecialKey);
    glutIdleFunc(NULL);
    glutDisplayFunc(ConfMenu);
    *IntValue=atoi(Value);
    if (NewScreenWidth!=ScreenWidth || NewScreenHeight!=ScreenHeight) {
      ScreenWidth=NewScreenWidth;
      ScreenHeight=NewScreenHeight;
      glutReshapeWindow(ScreenWidth, ScreenHeight);
      InitMainMenu();
      InitConfMenu();
    }
    if (newvolume!=volume) {
      volume=newvolume;
      setvolume();
    }
    ConfMenu();
  } else if (key>='0' && key <='9') {
    i=strlen(Value);
    if (i<MaxTextLength) {
      *(Value+i)=key;
      *(Value+i+1)='\0';
      *IntValue=atoi(Value);
    } else if (i==1 && *IntValue==0) {
      *(Value)=key;
      *(Value+1)='\0';
      *IntValue=atoi(Value);
    }
    IntTextEntry();
  }
}
