// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.

#ifndef tools_platform
#define tools_platform

// We do not byteswap on intel (LE) (common platform).
// We have then a better compression on these machines.
// NOTE : this is the contrary to what is done in CERN-ROOT (and Rio).

namespace tools {

inline bool is_little_endian() {
  unsigned int i = 1;
  unsigned char* b = (unsigned char*)&i;
  // BE = Big Endian, LE = Little Endian.
  // The Intels x86 are LE.
  // Mac PPC b[3] is 1 (BE)
  // Mac Intel b[0] is 1 (LE)
  // Linux i386 b[0] is 1 (LE)
  // Linux x86_64 b[0] is 1 (LE)
  return (b[0]==1?true:false);
}

}

#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif

namespace tools {
namespace device {

#if TARGET_OS_IPHONE
inline bool is_iOS() {return true;}
#else
inline bool is_iOS() {return false;}
#endif

#ifdef ANDROID
inline bool is_Android() {return true;}
#else
inline bool is_Android() {return false;}
#endif

#ifdef EMSCRIPTEN
inline bool is_emscripten() {return true;}
#else
inline bool is_emscripten() {return false;}
#endif


#if defined(ANDROID) || TARGET_OS_IPHONE
inline bool small_screen()     {return true;}
//inline bool no_cursor()        {return true;}
inline bool stop_app_button()  {return true;} //the device has a button to stop the app.
#elif defined(EMSCRIPTEN)
inline bool small_screen()     {return false;}
//inline bool no_cursor()        {return false;}
inline bool stop_app_button()  {return true;} //the device has a button to stop the app.
#else
inline bool small_screen()     {return false;}
//inline bool no_cursor()        {return false;}
inline bool stop_app_button()  {return false;}
#endif
#if TARGET_OS_IPHONE
inline bool slow_cpu()         {return true;}
#else
inline bool slow_cpu()         {return false;}
#endif

inline unsigned int tex_mem_limit() {
  // glGet(GL_MAX_TEXTURE_SIZE) :
  //   MacBookPro : it returns 8192.
  //   SGS : it returns 2048.
  //   iPad1 : it returns 2048.
  //   iPod : it returns ?
  //   Nexus 10 : it returns ?

  // 1024*1024  //*3 =   3 145 728
  // 2048*2048  //*3 =  12 582 912
  // 4096*4096  //*3 =  50 331 648
  // 8192*8192  //*3 = 201 326 592
  // 8192*4096  //*3 = 100 663 296
  if(small_screen()) {
    //iOS : Apple says that max 2D tex size is 1024*1024 with two units
    //      texture available. From doc on PowerVR MBX.
    return 2048*2048*3;
  } else {
    //limit = 4096*4096*3; //=8192*2048 //permit to pass ATLAS big image.
    //permit to pass fete_science_2010/power2/image_0.jpg
    return 8192*4096*3; //100663296
  }
}

}}

///////////////////////////////////////////////////////////////////
/// backcomp : for OnX/source/Core/atat.cxx : /////////////////////
///////////////////////////////////////////////////////////////////

//NOTE : we avoid to have std includes here to be sure
//       that in the below ifdef things come only from the compiler.

namespace tools {

inline const char* os() {

#if TARGET_OS_IPHONE
  static const char s_s[] = "iOS";
#elif defined(ANDROID)
  static const char s_s[] = "Android";
#elif defined(EMSCRIPTEN)
  static const char s_s[] = "emscripten";
#elif defined(_WIN32)
  static const char s_s[] = "Windows_NT";
#elif __APPLE__
  static const char s_s[] = "Darwin";
#elif defined(__linux)
  static const char s_s[] = "Linux";
#elif defined(__alpha)
  static const char s_s[] = "OSF1";
#elif defined(__CYGWIN__)
  static const char s_s[] = "CYGWIN";
#else
  static const char s_s[] = "unknown";
#endif
  return s_s;
}

inline bool _WIN32_defined() {
#ifdef _WIN32
  return true;
#else
  return false;
#endif
}

inline const char* processor() {

#if defined(__GNUC__)

#if defined(__ppc__)
  static const char s_s[] = "ppc";
#elif defined(__ppc64__)
  static const char s_s[] = "ppc64";
#elif defined(__i386__)
  static const char s_s[] = "i386";
#elif defined(__x86_64__)
  static const char s_s[] = "x86_64";
#elif defined(__ia64__)
  static const char s_s[] = "ia64";
#else
  static const char s_s[] = "unknown";
#endif

#elif defined(_MSC_VER)

#if defined(_M_IX86)
  static const char s_s[] = "ix86";
#elif defined(_M_X64)
  static const char s_s[] = "x64";
#else
  static const char s_s[] = "unknown";
#endif

#elif defined(__alpha)
  static const char s_s[] = "alpha";

#else
  static const char s_s[] = "unknown";
#endif
  return s_s;
}

inline const char* compiler_name() {

#if defined(__clang__)
  static const char s_s[] = "clang";
#elif defined(__GNUC__)
  static const char s_s[] = "gcc";
#elif defined(_MSC_VER)
  static const char s_s[] = "cl";
#elif defined(__alpha)
  static const char s_s[] = "cxx";
#else
  static const char s_s[] = "unknown";
#endif
  return s_s;
}

}

#include "tosu" //does not bring any std include.

namespace tools {

inline void compiler(char a_s[128]) {
  char* pos = a_s;
  unsigned int l;
  toss(compiler_name(),pos,l);pos += l;

#if defined(__clang__)
  *pos = '_';pos++;
  tosu<unsigned int>(__clang_major__,pos,l);pos += l;
  tosu<unsigned int>(__clang_minor__,pos,l);pos += l;
  tosu<unsigned int>(__clang_patchlevel__,pos,l);pos += l;
#elif defined(__GNUC__)
  *pos = '_';pos++;
  tosu<unsigned int>(__GNUC__,pos,l);pos += l;
  tosu<unsigned int>(__GNUC_MINOR__,pos,l);pos += l;
  tosu<unsigned int>(__GNUC_PATCHLEVEL__,pos,l);pos += l;
#elif defined(_MSC_VER)
  *pos = '_';pos++;
  tosu<unsigned int>(_MSC_VER,pos,l);pos += l;
  //_mfc_
  //tosu<unsigned int>(_MFC_VER,pos,l);pos += l;
#elif defined(__alpha)
#else
#endif
  *pos = 0;
}

}

#endif


/* We prefer to handle endianity dynamically, but with cpp macro
   it would looks like (from luaconf.h) :
#if defined(__i386__) || defined(__i386) || \
    defined(__X86__)  || defined (__x86_64)
#define TOOLS_IS_BE 0
#define TOOLS_IS_LE 1
#elif defined(__POWERPC__) || defined(__ppc__)
#define TOOLS_IS_BE 1
#define TOOLS_IS_LE 0
#endif
*/
