/// This file has been generated, if you wish to
/// modify it in a permanent way, please refer
/// to the script file : gen/generator_java.rb

#include "interface.hh"

// In case of errors...
template<typename Lang, typename Cxx>
Cxx lang2cxx(Lang in)
{
  return in.error_should_not_happens;
}

template<typename Cxx, typename Lang>
Lang cxx2lang(Cxx in)
{
  return in.error_should_not_happens;
}

template<typename Lang, typename Cxx>
std::vector<Cxx> lang2cxx_array(jobject in);

template<typename Cxx, typename Lang>
jarray cxx2lang_array(std::vector<Cxx> in);

// Basic type wrappers
template <>
jboolean cxx2lang<boolean, jboolean>(boolean in)
{
  return (jboolean)in;
}

template <>
boolean lang2cxx<jboolean, boolean>(jboolean in)
{
  return (boolean)in;
}

template <>
jarray cxx2lang_array<boolean, jboolean>(std::vector<boolean> in)
{
  jbooleanArray out = jrt.env->NewBooleanArray((jsize)in.size());
  jrt.env->SetBooleanArrayRegion(out, (jsize)0, (jsize)in.size(), (const jboolean*)in.data());
  return (jarray)out;
}

template <>
std::vector<boolean> lang2cxx_array<jboolean, boolean>(jobject in)
{
  jbooleanArray array = (jbooleanArray)in;
  jsize size = jrt.env->GetArrayLength(array);
  jboolean* datas = jrt.env->GetBooleanArrayElements(array, NULL);
  std::vector<boolean> out(datas, datas + size);
  jrt.env->ReleaseBooleanArrayElements(array, datas, JNI_ABORT);
  return out;
}

template <>
jbyte cxx2lang<byte, jbyte>(byte in)
{
  return (jbyte)in;
}

template <>
byte lang2cxx<jbyte, byte>(jbyte in)
{
  return (byte)in;
}

template <>
jarray cxx2lang_array<byte, jbyte>(std::vector<byte> in)
{
  jbyteArray out = jrt.env->NewByteArray((jsize)in.size());
  jrt.env->SetByteArrayRegion(out, (jsize)0, (jsize)in.size(), (const jbyte*)in.data());
  return (jarray)out;
}

template <>
std::vector<byte> lang2cxx_array<jbyte, byte>(jobject in)
{
  jbyteArray array = (jbyteArray)in;
  jsize size = jrt.env->GetArrayLength(array);
  jbyte* datas = jrt.env->GetByteArrayElements(array, NULL);
  std::vector<byte> out(datas, datas + size);
  jrt.env->ReleaseByteArrayElements(array, datas, JNI_ABORT);
  return out;
}

template <>
jchar cxx2lang<char, jchar>(char in)
{
  return (jchar)in;
}

template <>
char lang2cxx<jchar, char>(jchar in)
{
  return (char)in;
}

template <>
jarray cxx2lang_array<char, jchar>(std::vector<char> in)
{
  jcharArray out = jrt.env->NewCharArray((jsize)in.size());
  jrt.env->SetCharArrayRegion(out, (jsize)0, (jsize)in.size(), (const jchar*)in.data());
  return (jarray)out;
}

template <>
std::vector<char> lang2cxx_array<jchar, char>(jobject in)
{
  jcharArray array = (jcharArray)in;
  jsize size = jrt.env->GetArrayLength(array);
  jchar* datas = jrt.env->GetCharArrayElements(array, NULL);
  std::vector<char> out(datas, datas + size);
  jrt.env->ReleaseCharArrayElements(array, datas, JNI_ABORT);
  return out;
}

template <>
jshort cxx2lang<short, jshort>(short in)
{
  return (jshort)in;
}

template <>
short lang2cxx<jshort, short>(jshort in)
{
  return (short)in;
}

template <>
jarray cxx2lang_array<short, jshort>(std::vector<short> in)
{
  jshortArray out = jrt.env->NewShortArray((jsize)in.size());
  jrt.env->SetShortArrayRegion(out, (jsize)0, (jsize)in.size(), (const jshort*)in.data());
  return (jarray)out;
}

template <>
std::vector<short> lang2cxx_array<jshort, short>(jobject in)
{
  jshortArray array = (jshortArray)in;
  jsize size = jrt.env->GetArrayLength(array);
  jshort* datas = jrt.env->GetShortArrayElements(array, NULL);
  std::vector<short> out(datas, datas + size);
  jrt.env->ReleaseShortArrayElements(array, datas, JNI_ABORT);
  return out;
}

template <>
jint cxx2lang<int, jint>(int in)
{
  return (jint)in;
}

template <>
int lang2cxx<jint, int>(jint in)
{
  return (int)in;
}

template <>
jarray cxx2lang_array<int, jint>(std::vector<int> in)
{
  jintArray out = jrt.env->NewIntArray((jsize)in.size());
  jrt.env->SetIntArrayRegion(out, (jsize)0, (jsize)in.size(), (const jint*)in.data());
  return (jarray)out;
}

template <>
std::vector<int> lang2cxx_array<jint, int>(jobject in)
{
  jintArray array = (jintArray)in;
  jsize size = jrt.env->GetArrayLength(array);
  jint* datas = jrt.env->GetIntArrayElements(array, NULL);
  std::vector<int> out(datas, datas + size);
  jrt.env->ReleaseIntArrayElements(array, datas, JNI_ABORT);
  return out;
}

template <>
jlong cxx2lang<long, jlong>(long in)
{
  return (jlong)in;
}

template <>
long lang2cxx<jlong, long>(jlong in)
{
  return (long)in;
}

template <>
jarray cxx2lang_array<long, jlong>(std::vector<long> in)
{
  jlongArray out = jrt.env->NewLongArray((jsize)in.size());
  jrt.env->SetLongArrayRegion(out, (jsize)0, (jsize)in.size(), (const jlong*)in.data());
  return (jarray)out;
}

template <>
std::vector<long> lang2cxx_array<jlong, long>(jobject in)
{
  jlongArray array = (jlongArray)in;
  jsize size = jrt.env->GetArrayLength(array);
  jlong* datas = jrt.env->GetLongArrayElements(array, NULL);
  std::vector<long> out(datas, datas + size);
  jrt.env->ReleaseLongArrayElements(array, datas, JNI_ABORT);
  return out;
}

template <>
jfloat cxx2lang<float, jfloat>(float in)
{
  return (jfloat)in;
}

template <>
float lang2cxx<jfloat, float>(jfloat in)
{
  return (float)in;
}

template <>
jarray cxx2lang_array<float, jfloat>(std::vector<float> in)
{
  jfloatArray out = jrt.env->NewFloatArray((jsize)in.size());
  jrt.env->SetFloatArrayRegion(out, (jsize)0, (jsize)in.size(), (const jfloat*)in.data());
  return (jarray)out;
}

template <>
std::vector<float> lang2cxx_array<jfloat, float>(jobject in)
{
  jfloatArray array = (jfloatArray)in;
  jsize size = jrt.env->GetArrayLength(array);
  jfloat* datas = jrt.env->GetFloatArrayElements(array, NULL);
  std::vector<float> out(datas, datas + size);
  jrt.env->ReleaseFloatArrayElements(array, datas, JNI_ABORT);
  return out;
}

template <>
jdouble cxx2lang<double, jdouble>(double in)
{
  return (jdouble)in;
}

template <>
double lang2cxx<jdouble, double>(jdouble in)
{
  return (double)in;
}

template <>
jarray cxx2lang_array<double, jdouble>(std::vector<double> in)
{
  jdoubleArray out = jrt.env->NewDoubleArray((jsize)in.size());
  jrt.env->SetDoubleArrayRegion(out, (jsize)0, (jsize)in.size(), (const jdouble*)in.data());
  return (jarray)out;
}

template <>
std::vector<double> lang2cxx_array<jdouble, double>(jobject in)
{
  jdoubleArray array = (jdoubleArray)in;
  jsize size = jrt.env->GetArrayLength(array);
  jdouble* datas = jrt.env->GetDoubleArrayElements(array, NULL);
  std::vector<double> out(datas, datas + size);
  jrt.env->ReleaseDoubleArrayElements(array, datas, JNI_ABORT);
  return out;
}

// String wrappers
template <>
jstring cxx2lang<std::string, jstring>(std::string in)
{
  return jrt.env->NewStringUTF(in.data());
}

template <>
std::string lang2cxx<jstring, std::string>(jstring in)
{
  jboolean is_copy;
  const jchar* datas = jrt.env->GetStringChars(in, &is_copy);
  jsize size = jrt.env->GetStringLength(in);
  std::string out((const char*)datas, (size_t)size);
  if (is_copy)
    jrt.env->ReleaseStringChars(in, datas);
  return out;
}

// Object array wrappers (assume Lang::class exists)
template <typename Cxx, typename Lang>
jarray cxx2lang_array(std::vector<Cxx> in)
{
  jobjectArray out = jrt.env->NewObjectArray((jsize)in.size(), Lang::Class(), NULL);
  for (size_t i = 0; i < in.size(); i++)
    jrt.env->SetObjectArrayElement(out, (jsize)i, cxx2lang<Cxx, jobject>(in[i]));
  return out;
}

template <typename Lang, typename Cxx>
std::vector<Cxx> lang2cxx_array(jobject in)
{
  jobjectArray array = (jobjectArray)in;
  size_t size = (size_t)jrt.env->GetArrayLength(array);
  std::vector<Cxx> out;
  for (size_t i = 0; i < size; i++)
    out.push_back(lang2cxx<jobject, Cxx>(jrt.env->GetObjectArrayElement(array, (jsize)i)));
  return out;
}

/// Types de cases
template<>
case_type lang2cxx<jobject, case_type>(jobject in)
{
  jmethodID ordinal = jrt.env->GetMethodID(CaseType::Class(), "ordinal", "()I");
  return case_type(lang2cxx<jint, int>(jrt.env->CallIntMethod(in, ordinal)));
}

template<>
jobject cxx2lang<case_type, jobject>(case_type in)
{
  jmethodID method = jrt.env->GetStaticMethodID(CaseType::Class(), "values", "()[LCaseType;");
  jobjectArray values = (jobjectArray)jrt.env->CallStaticObjectMethod(CaseType::Class(), method);
  return jrt.env->GetObjectArrayElement(values, (jsize)in);
}


/// Points cardinaux
template<>
direction lang2cxx<jobject, direction>(jobject in)
{
  jmethodID ordinal = jrt.env->GetMethodID(Direction::Class(), "ordinal", "()I");
  return direction(lang2cxx<jint, int>(jrt.env->CallIntMethod(in, ordinal)));
}

template<>
jobject cxx2lang<direction, jobject>(direction in)
{
  jmethodID method = jrt.env->GetStaticMethodID(Direction::Class(), "values", "()[LDirection;");
  jobjectArray values = (jobjectArray)jrt.env->CallStaticObjectMethod(Direction::Class(), method);
  return jrt.env->GetObjectArrayElement(values, (jsize)in);
}


/// Erreurs possibles
template<>
erreur lang2cxx<jobject, erreur>(jobject in)
{
  jmethodID ordinal = jrt.env->GetMethodID(Erreur::Class(), "ordinal", "()I");
  return erreur(lang2cxx<jint, int>(jrt.env->CallIntMethod(in, ordinal)));
}

template<>
jobject cxx2lang<erreur, jobject>(erreur in)
{
  jmethodID method = jrt.env->GetStaticMethodID(Erreur::Class(), "values", "()[LErreur;");
  jobjectArray values = (jobjectArray)jrt.env->CallStaticObjectMethod(Erreur::Class(), method);
  return jrt.env->GetObjectArrayElement(values, (jsize)in);
}


/// Types d'actions
template<>
action_type lang2cxx<jobject, action_type>(jobject in)
{
  jmethodID ordinal = jrt.env->GetMethodID(ActionType::Class(), "ordinal", "()I");
  return action_type(lang2cxx<jint, int>(jrt.env->CallIntMethod(in, ordinal)));
}

template<>
jobject cxx2lang<action_type, jobject>(action_type in)
{
  jmethodID method = jrt.env->GetStaticMethodID(ActionType::Class(), "values", "()[LActionType;");
  jobjectArray values = (jobjectArray)jrt.env->CallStaticObjectMethod(ActionType::Class(), method);
  return jrt.env->GetObjectArrayElement(values, (jsize)in);
}


/// Types de drapeaux de débug
template<>
debug_drapeau lang2cxx<jobject, debug_drapeau>(jobject in)
{
  jmethodID ordinal = jrt.env->GetMethodID(DebugDrapeau::Class(), "ordinal", "()I");
  return debug_drapeau(lang2cxx<jint, int>(jrt.env->CallIntMethod(in, ordinal)));
}

template<>
jobject cxx2lang<debug_drapeau, jobject>(debug_drapeau in)
{
  jmethodID method = jrt.env->GetStaticMethodID(DebugDrapeau::Class(), "values", "()[LDebugDrapeau;");
  jobjectArray values = (jobjectArray)jrt.env->CallStaticObjectMethod(DebugDrapeau::Class(), method);
  return jrt.env->GetObjectArrayElement(values, (jsize)in);
}


/// Position sur la banquise, donnée par deux coordonnées.
template <>
position lang2cxx<jobject, position>(jobject in)
{
  position out;
  out.ligne = lang2cxx<jint, int>(jrt.env->GetIntField(in, jrt.env->GetFieldID(Position::Class(), "ligne", "I")));
  out.colonne = lang2cxx<jint, int>(jrt.env->GetIntField(in, jrt.env->GetFieldID(Position::Class(), "colonne", "I")));
  return out;
}

template <>
jobject cxx2lang<position, jobject>(position in)
{
  jobject out = jrt.env->NewObject(Position::Class(), jrt.env->GetMethodID(Position::Class(), "<init>", "()V"));
  jrt.env->SetIntField(out, jrt.env->GetFieldID(Position::Class(), "ligne", "I"), cxx2lang<int, jint>(in.ligne));
  jrt.env->SetIntField(out, jrt.env->GetFieldID(Position::Class(), "colonne", "I"), cxx2lang<int, jint>(in.colonne));
  return out;
}


/// Alien à capturer durant la mission.
template <>
alien_info lang2cxx<jobject, alien_info>(jobject in)
{
  alien_info out;
  out.pos = lang2cxx<jobject, position>(jrt.env->GetObjectField(in, jrt.env->GetFieldID(AlienInfo::Class(), "pos", "LPosition;")));
  out.points_capture = lang2cxx<jint, int>(jrt.env->GetIntField(in, jrt.env->GetFieldID(AlienInfo::Class(), "points_capture", "I")));
  out.tour_invasion = lang2cxx<jint, int>(jrt.env->GetIntField(in, jrt.env->GetFieldID(AlienInfo::Class(), "tour_invasion", "I")));
  out.duree_invasion = lang2cxx<jint, int>(jrt.env->GetIntField(in, jrt.env->GetFieldID(AlienInfo::Class(), "duree_invasion", "I")));
  out.capture_en_cours = lang2cxx<jint, int>(jrt.env->GetIntField(in, jrt.env->GetFieldID(AlienInfo::Class(), "capture_en_cours", "I")));
  return out;
}

template <>
jobject cxx2lang<alien_info, jobject>(alien_info in)
{
  jobject out = jrt.env->NewObject(AlienInfo::Class(), jrt.env->GetMethodID(AlienInfo::Class(), "<init>", "()V"));
  jrt.env->SetObjectField(out, jrt.env->GetFieldID(AlienInfo::Class(), "pos", "LPosition;"), cxx2lang<position, jobject>(in.pos));
  jrt.env->SetIntField(out, jrt.env->GetFieldID(AlienInfo::Class(), "points_capture", "I"), cxx2lang<int, jint>(in.points_capture));
  jrt.env->SetIntField(out, jrt.env->GetFieldID(AlienInfo::Class(), "tour_invasion", "I"), cxx2lang<int, jint>(in.tour_invasion));
  jrt.env->SetIntField(out, jrt.env->GetFieldID(AlienInfo::Class(), "duree_invasion", "I"), cxx2lang<int, jint>(in.duree_invasion));
  jrt.env->SetIntField(out, jrt.env->GetFieldID(AlienInfo::Class(), "capture_en_cours", "I"), cxx2lang<int, jint>(in.capture_en_cours));
  return out;
}


/// Action de déplacement représentée dans l'historique.
template <>
action_hist lang2cxx<jobject, action_hist>(jobject in)
{
  action_hist out;
  out.atype = lang2cxx<jobject, action_type>(jrt.env->GetObjectField(in, jrt.env->GetFieldID(ActionHist::Class(), "atype", "LActionType;")));
  out.id_agent = lang2cxx<jint, int>(jrt.env->GetIntField(in, jrt.env->GetFieldID(ActionHist::Class(), "id_agent", "I")));
  out.dir = lang2cxx<jobject, direction>(jrt.env->GetObjectField(in, jrt.env->GetFieldID(ActionHist::Class(), "dir", "LDirection;")));
  return out;
}

template <>
jobject cxx2lang<action_hist, jobject>(action_hist in)
{
  jobject out = jrt.env->NewObject(ActionHist::Class(), jrt.env->GetMethodID(ActionHist::Class(), "<init>", "()V"));
  jrt.env->SetObjectField(out, jrt.env->GetFieldID(ActionHist::Class(), "atype", "LActionType;"), cxx2lang<action_type, jobject>(in.atype));
  jrt.env->SetIntField(out, jrt.env->GetFieldID(ActionHist::Class(), "id_agent", "I"), cxx2lang<int, jint>(in.id_agent));
  jrt.env->SetObjectField(out, jrt.env->GetFieldID(ActionHist::Class(), "dir", "LDirection;"), cxx2lang<direction, jobject>(in.dir));
  return out;
}


/// Déplace l'agent ``id_agent`` d'une case dans la direction choisie.
jobject deplacer(JNIEnv* _env, jobject _obj, jint id_agent, jobject dir)
{
  return cxx2lang<erreur, jobject>(api_deplacer(lang2cxx<jint, int>(id_agent), lang2cxx<jobject, direction>(dir)));
}


/// Propulse l'agent ``id_agent`` dans la direction choisie jusqu'à ce qu'il heurte un obstacle, c'est-à-dire soit un mur soit un autre agent.
jobject glisser(JNIEnv* _env, jobject _obj, jint id_agent, jobject dir)
{
  return cxx2lang<erreur, jobject>(api_glisser(lang2cxx<jint, int>(id_agent), lang2cxx<jobject, direction>(dir)));
}


/// L'agent ``id_agent`` pousse tout autre agent se trouvant sur la case adjacente dans la direction indiquée. Ce dernier est propulsé jusqu'à ce qu'il rencontre un obstacle, c'est-à-dire soit un mur soit un autre agent.
jobject pousser(JNIEnv* _env, jobject _obj, jint id_agent, jobject dir)
{
  return cxx2lang<erreur, jobject>(api_pousser(lang2cxx<jint, int>(id_agent), lang2cxx<jobject, direction>(dir)));
}


/// Affiche le drapeau spécifié sur la case indiquée.
jobject debug_afficher_drapeau(JNIEnv* _env, jobject _obj, jobject pos, jobject drapeau)
{
  return cxx2lang<erreur, jobject>(api_debug_afficher_drapeau(lang2cxx<jobject, position>(pos), lang2cxx<jobject, debug_drapeau>(drapeau)));
}


/// Renvoie le nombre de points d'action de l'agent ``id_agent`` restants pour le tour. Si le numéro d'agent est invalide, la fonction renvoie -1.
jint points_action_agent(JNIEnv* _env, jobject _obj, jint id_agent)
{
  return cxx2lang<int, jint>(api_points_action_agent(lang2cxx<jint, int>(id_agent)));
}


/// Renvoie le plus court chemin entre deux positions de la banquise sous la forme d'une suite de direction à emprunter. Ce chemin ne contient pas de glissade, uniquement des déplacements simples. Si la position est invalide ou que le chemin n'existe pas, le chemin renvoyé est vide.
jarray chemin(JNIEnv* _env, jobject _obj, jobject pos1, jobject pos2)
{
  return cxx2lang_array<direction, Direction>(api_chemin(lang2cxx<jobject, position>(pos1), lang2cxx<jobject, position>(pos2)));
}


/// Renvoie le type d'une case donnée.
jobject type_case(JNIEnv* _env, jobject _obj, jobject pos)
{
  return cxx2lang<case_type, jobject>(api_type_case(lang2cxx<jobject, position>(pos)));
}


/// Renvoie le numéro du joueur à qui appartient l'agent sur la case indiquée. Renvoie -1 s'il n'y a pas d'agent ou si la position est invalide.
jint agent_sur_case(JNIEnv* _env, jobject _obj, jobject pos)
{
  return cxx2lang<int, jint>(api_agent_sur_case(lang2cxx<jobject, position>(pos)));
}


/// Indique si un alien se trouve sur une case donnée. Renvoie vrai si l'alien est en train d'envahir la banquise et qu'il n'a pas encore été capturé. Renvoie faux autremement, ou si la position est invalide.
jboolean alien_sur_case(JNIEnv* _env, jobject _obj, jobject pos)
{
  return cxx2lang<boolean, jboolean>(api_alien_sur_case(lang2cxx<jobject, position>(pos)));
}


/// Indique la position de l'agent sur la banquise désigné par le numéro ``id_agent`` appartenant au joueur ``id_joueur``. Si la description de l'agent est incorrecte, la position (-1, -1) est renvoyée.
jobject position_agent(JNIEnv* _env, jobject _obj, jint id_joueur, jint id_agent)
{
  return cxx2lang<position, jobject>(api_position_agent(lang2cxx<jint, int>(id_joueur), lang2cxx<jint, int>(id_agent)));
}


/// Renvoie la description d'un alien en fonction d'une position donnée. Si l'alien n'est pas présent sur la carte, ou si la position est invalide, tous les membres de la structure ``alien_info`` renvoyée sont initialisés à -1.
jobject info_alien(JNIEnv* _env, jobject _obj, jobject pos)
{
  return cxx2lang<alien_info, jobject>(api_info_alien(lang2cxx<jobject, position>(pos)));
}


/// Renvoie la liste de tous les aliens présents durant la partie.
jarray liste_aliens(JNIEnv* _env, jobject _obj)
{
  return cxx2lang_array<alien_info, AlienInfo>(api_liste_aliens());
}


/// Renvoie la liste des actions effectuées par l’adversaire durant son tour, dans l'ordre chronologique. Les actions de débug n'apparaissent pas dans cette liste.
jarray historique(JNIEnv* _env, jobject _obj)
{
  return cxx2lang_array<action_hist, ActionHist>(api_historique());
}


/// Renvoie le score du joueur ``id_joueur``. Renvoie -1 si le joueur est invalide.
jint score(JNIEnv* _env, jobject _obj, jint id_joueur)
{
  return cxx2lang<int, jint>(api_score(lang2cxx<jint, int>(id_joueur)));
}


/// Renvoie votre numéro de joueur.
jint moi(JNIEnv* _env, jobject _obj)
{
  return cxx2lang<int, jint>(api_moi());
}


/// Renvoie le numéro de joueur de votre adversaire.
jint adversaire(JNIEnv* _env, jobject _obj)
{
  return cxx2lang<int, jint>(api_adversaire());
}


/// Annule la dernière action. Renvoie faux quand il n'y a pas d'action à annuler ce tour-ci.
jboolean annuler(JNIEnv* _env, jobject _obj)
{
  return cxx2lang<boolean, jboolean>(api_annuler());
}


/// Retourne le numéro du tour actuel.
jint tour_actuel(JNIEnv* _env, jobject _obj)
{
  return cxx2lang<int, jint>(api_tour_actuel());
}


/// Affiche le contenu d'une valeur de type case_type
void afficher_case_type(JNIEnv* _env, jobject _obj, jobject v)
{
  api_afficher_case_type(lang2cxx<jobject, case_type>(v));
}


/// Affiche le contenu d'une valeur de type direction
void afficher_direction(JNIEnv* _env, jobject _obj, jobject v)
{
  api_afficher_direction(lang2cxx<jobject, direction>(v));
}


/// Affiche le contenu d'une valeur de type erreur
void afficher_erreur(JNIEnv* _env, jobject _obj, jobject v)
{
  api_afficher_erreur(lang2cxx<jobject, erreur>(v));
}


/// Affiche le contenu d'une valeur de type action_type
void afficher_action_type(JNIEnv* _env, jobject _obj, jobject v)
{
  api_afficher_action_type(lang2cxx<jobject, action_type>(v));
}


/// Affiche le contenu d'une valeur de type debug_drapeau
void afficher_debug_drapeau(JNIEnv* _env, jobject _obj, jobject v)
{
  api_afficher_debug_drapeau(lang2cxx<jobject, debug_drapeau>(v));
}


/// Affiche le contenu d'une valeur de type position
void afficher_position(JNIEnv* _env, jobject _obj, jobject v)
{
  api_afficher_position(lang2cxx<jobject, position>(v));
}


/// Affiche le contenu d'une valeur de type alien_info
void afficher_alien_info(JNIEnv* _env, jobject _obj, jobject v)
{
  api_afficher_alien_info(lang2cxx<jobject, alien_info>(v));
}


/// Affiche le contenu d'une valeur de type action_hist
void afficher_action_hist(JNIEnv* _env, jobject _obj, jobject v)
{
  api_afficher_action_hist(lang2cxx<jobject, action_hist>(v));
}


/// Fonction appelée au début de la partie.
extern "C" void partie_init()
{
  bool attached = jrt.function_enter();
  jmethodID method = jrt.env->GetMethodID(Prologin::Class(), "partie_init", "()V");
  jrt.env->CallVoidMethod(jrt.prologin, method);
  if (jrt.env->ExceptionOccurred())
  {
    jrt.env->ExceptionDescribe();
    exit(1);
  }
  jrt.function_exit(attached);
}


/// Fonction appelée à chaque tour.
extern "C" void jouer_tour()
{
  bool attached = jrt.function_enter();
  jmethodID method = jrt.env->GetMethodID(Prologin::Class(), "jouer_tour", "()V");
  jrt.env->CallVoidMethod(jrt.prologin, method);
  if (jrt.env->ExceptionOccurred())
  {
    jrt.env->ExceptionDescribe();
    exit(1);
  }
  jrt.function_exit(attached);
}


/// Fonction appelée à la fin de la partie.
extern "C" void partie_fin()
{
  bool attached = jrt.function_enter();
  jmethodID method = jrt.env->GetMethodID(Prologin::Class(), "partie_fin", "()V");
  jrt.env->CallVoidMethod(jrt.prologin, method);
  if (jrt.env->ExceptionOccurred())
  {
    jrt.env->ExceptionDescribe();
    exit(1);
  }
  jrt.function_exit(attached);
}


jclass Prologin::Class()
{
  return jrt.env->FindClass("Prologin");
}

jclass CaseType::Class()
{
  return jrt.env->FindClass("CaseType");
}

jclass Direction::Class()
{
  return jrt.env->FindClass("Direction");
}

jclass Erreur::Class()
{
  return jrt.env->FindClass("Erreur");
}

jclass ActionType::Class()
{
  return jrt.env->FindClass("ActionType");
}

jclass DebugDrapeau::Class()
{
  return jrt.env->FindClass("DebugDrapeau");
}

jclass Position::Class()
{
  return jrt.env->FindClass("Position");
}

jclass AlienInfo::Class()
{
  return jrt.env->FindClass("AlienInfo");
}

jclass ActionHist::Class()
{
  return jrt.env->FindClass("ActionHist");
}

static void _register_native_methods(JNIEnv* env)
{
  JNINativeMethod methods[] = {
    {(char*)"deplacer", (char*)"(ILDirection;)LErreur;", (void*)&deplacer},
    {(char*)"glisser", (char*)"(ILDirection;)LErreur;", (void*)&glisser},
    {(char*)"pousser", (char*)"(ILDirection;)LErreur;", (void*)&pousser},
    {(char*)"debug_afficher_drapeau", (char*)"(LPosition;LDebugDrapeau;)LErreur;", (void*)&debug_afficher_drapeau},
    {(char*)"points_action_agent", (char*)"(I)I", (void*)&points_action_agent},
    {(char*)"chemin", (char*)"(LPosition;LPosition;)[LDirection;", (void*)&chemin},
    {(char*)"type_case", (char*)"(LPosition;)LCaseType;", (void*)&type_case},
    {(char*)"agent_sur_case", (char*)"(LPosition;)I", (void*)&agent_sur_case},
    {(char*)"alien_sur_case", (char*)"(LPosition;)Z", (void*)&alien_sur_case},
    {(char*)"position_agent", (char*)"(II)LPosition;", (void*)&position_agent},
    {(char*)"info_alien", (char*)"(LPosition;)LAlienInfo;", (void*)&info_alien},
    {(char*)"liste_aliens", (char*)"()[LAlienInfo;", (void*)&liste_aliens},
    {(char*)"historique", (char*)"()[LActionHist;", (void*)&historique},
    {(char*)"score", (char*)"(I)I", (void*)&score},
    {(char*)"moi", (char*)"()I", (void*)&moi},
    {(char*)"adversaire", (char*)"()I", (void*)&adversaire},
    {(char*)"annuler", (char*)"()Z", (void*)&annuler},
    {(char*)"tour_actuel", (char*)"()I", (void*)&tour_actuel},
    {(char*)"afficher_case_type", (char*)"(LCaseType;)V", (void*)&afficher_case_type},
    {(char*)"afficher_direction", (char*)"(LDirection;)V", (void*)&afficher_direction},
    {(char*)"afficher_erreur", (char*)"(LErreur;)V", (void*)&afficher_erreur},
    {(char*)"afficher_action_type", (char*)"(LActionType;)V", (void*)&afficher_action_type},
    {(char*)"afficher_debug_drapeau", (char*)"(LDebugDrapeau;)V", (void*)&afficher_debug_drapeau},
    {(char*)"afficher_position", (char*)"(LPosition;)V", (void*)&afficher_position},
    {(char*)"afficher_alien_info", (char*)"(LAlienInfo;)V", (void*)&afficher_alien_info},
    {(char*)"afficher_action_hist", (char*)"(LActionHist;)V", (void*)&afficher_action_hist}
  };
  env->RegisterNatives(Prologin::Class(), methods, sizeof(methods)/sizeof(methods[0]));
}

ProloginJavaRunTime jrt;

ProloginJavaRunTime::ProloginJavaRunTime()
{
 std::string classpath = "-Djava.class.path=";
  char* champion_path = getenv("CHAMPION_PATH");
  if (champion_path == NULL)
    champion_path = (char*)"./";
  classpath.append(champion_path);

  JavaVMInitArgs vm_args; /* JDK/JRE 6 VM initialization arguments */
  JavaVMOption options[4];
  options[0].optionString = (char*) classpath.c_str();
  options[1].optionString = (char*) "-ea";
  options[2].optionString = (char*) "-XX:MaxHeapSize=512m";
  options[3].optionString = (char*) "-XX:CompressedClassSpaceSize=64m";
  vm_args.version = JNI_VERSION_1_6;
  vm_args.nOptions = 4;
  vm_args.options = options;
  vm_args.ignoreUnrecognized = false;
  JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
  prologin = env->NewObject(Prologin::Class(), env->GetMethodID(Prologin::Class(), "<init>", "()V"));
  _register_native_methods(env);
}

ProloginJavaRunTime::~ProloginJavaRunTime()
{
  jvm->DestroyJavaVM();
}

bool ProloginJavaRunTime::function_enter()
{
  if (jvm->GetEnv((void**)&env, JNI_VERSION_1_6) == JNI_OK)
    return false;
  jvm->AttachCurrentThread((void**)&env, NULL);
  return true;
}

void ProloginJavaRunTime::function_exit(bool attached)
{
  if (attached)
    jvm->DetachCurrentThread();
}

