// global_var.h - [2020-04-13 11:57:47]
#ifndef _GLOBAL_FUNC_H_
#define _GLOBAL_FUNC_H_

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <wchar.h>
#include "CFTTMemPool_Resizing.h"
#include "common_type.h"

using namespace std;

extern int lang_47AEA8;
extern bool g_bNeonAvailable;

struct TSprintfParam {
  int field_0;
  int field_4;
  int field_8;
  int field_c;
  int field_10;
  int field_14;
  int field_18;
  int field_1c;
  int field_20;
  int field_24;
  int field_28;
  int field_2c;
  int field_30;
  int field_34;
  int field_38;
  int field_3c;
  int field_40;
  int field_44;
  int field_48;
  int field_4c;
};

//-------------------------------------------------------------------------------------------------
//自定义了一个组 arm 指令集的宏，用于生成特定arm指令
#define UXTB_00(X) ((uint)X & 0xFF)
#define UXTB_08(X) (((uint)X >> 8) & 0xFF)
#define UXTB_16(X) (((uint)X >> 16) & 0xFF)
#define UXTB_24(X) (((uint)X >> 24) & 0xFF)

#define UXTB16_00(X) ((uint)X & 0xFF00FF)
#define UXTB16_08(X) (((uint)X >> 8) & 0xFF00FF)
#define UXTB16_16(X) (((uint)X >> 16) & 0xFF00FF)
#define UXTB16_24(X) (((uint)X >> 24) & 0xFF00FF)

#define UBFX(Rn, lsb, width) ((Rn >> lsb) & (0xFFFFFFFF >> (32 - width)))

// must uint
#define BFC(Rn, lsb, width) (((Rn >> ((lsb + width) >= 32 ? 31 : (lsb + width))) << ((lsb + width) >= 32 ? 31 : (lsb + width))) | ((Rn << (32 - lsb)) >> (32 - lsb)))

uint bfi(uint rd, uint rn, uint lsb, uint width);
//-------------------------------------------------------------------------------------------------
#define UXTH_00(X) (X & 0xFFFF)
//-------------------------------------------------------------------------------------------------
template <typename T>
uchar GetByte(T s, int pos) {
  uchar cret;
  uchar* p = reinterpret_cast<uchar*>(&s);
  p += pos;
  cret = *p;
  return cret;
}

//#define BYTE1(x) GetByte<uint>(x, 0)
//#define BYTE2(x) GetByte<uint>(x, 1)
//#define BYTE3(x) GetByte<uint>(x, 2)
//#define BYTE4(x) GetByte<uint>(x, 3)
//#define BYTE5(x) GetByte<uint64>(x, 4)
//#define BYTE6(x) GetByte<uint64>(x, 5)
//#define BYTE7(x) GetByte<uint64>(x, 6)
//#define BYTE8(x) GetByte<uint64>(x, 7)

#define BYTEn(x, n) (*((uchar*)&(x) + n))

#define BYTE0(x)  BYTEn(x, 0)
#define BYTE1(x)  BYTEn(x, 1)
#define BYTE2(x)  BYTEn(x, 2)
#define BYTE3(x)  BYTEn(x, 3)
#define BYTE4(x)  BYTEn(x, 4)
#define BYTE5(x)  BYTEn(x, 5)
#define BYTE6(x)  BYTEn(x, 6)
#define BYTE7(x)  BYTEn(x, 7)
#define BYTE8(x)  BYTEn(x, 8)
#define BYTE9(x)  BYTEn(x, 9)
#define BYTE10(x) BYTEn(x, 10)
#define BYTE11(x) BYTEn(x, 11)
#define BYTE12(x) BYTEn(x, 12)
#define BYTE13(x) BYTEn(x, 13)
#define BYTE14(x) BYTEn(x, 14)
#define BYTE15(x) BYTEn(x, 15)

#define __PAIR64__(high, low) (((uint64)(high) << 32) | (uint32)(low))

float int64_to_float_2A42A0(int64);
//-------------------------------------------------------------------------------------------------
// 00265868
uint32 FTTHash(char const* pdata);

// 002659F0
uint32 FTTHash(void const* pdata, int len);
//-------------------------------------------------------------------------------------------------
int32_t int64_2_int32(int64_t d);
int64_t int32_2_int64(int32_t d);
//-------------------------------------------------------------------------------------------------
// 002635AC
void FTTEncode(int* result, int len, uint a3);

// 002635C4
void FTTDecode(void* pdata, int dlen, uint dkey);
//-------------------------------------------------------------------------------------------------
std::string hexstring(uchar* p, int dlen);
std::string hexstring_line(const uint8_t* buffer, size_t size);
//-------------------------------------------------------------------------------------------------
struct TPoint {
  int dx_0;
  int dy_4;

  TPoint(){
      // dx_0 = 0;
      // dy_4 = 0;
  };

  TPoint(int i0, int i1) {
    dx_0 = i0;
    dy_4 = i1;
  };

  TPoint(TPoint* point) {
    if ((void*)point != (void*)this) {
      this->dx_0 = point->dx_0;
      this->dy_4 = point->dy_4;
    }
  };

  TPoint* operator=(const TPoint* point) {
    if ((void*)this != (void*)point) {
      this->dx_0 = point->dx_0;
      this->dy_4 = point->dy_4;
    }
    return this;
  };

  // TPoint& operator=(const TPoint& other) {
  //   if (this != &other) {
  //     this->dx_0 = other.dx_0;
  //     this->dy_4 = other.dy_4;
  //   }
  //   return *this;
  // };

  bool operator!=(const TPoint& other) {
    if ((this->dx_0 == other.dx_0) && (this->dy_4 == other.dy_4))
      return true;
    else
      return false;
  };

  bool operator==(const TPoint& other) {
    if ((this->dx_0 == other.dx_0) && (this->dy_4 == other.dy_4))
      return true;
    else
      return false;
  };
};
extern TPoint g_vZero;
//-------------------------------------------------------------------------------------------------
// 001F5630
float atof_1F5630(const char* a1);
//-------------------------------------------------------------------------------------------------
TPoint StrToPos(const char* pTxt);
//-------------------------------------------------------------------------------------------------
struct TPointF {
  float fx_0;
  float fy_4;
  TPointF() {
  }

  TPointF(float fX, float fY) {
    fx_0 = fX;
    fy_4 = fY;
  }

  TPointF& operator=(const TPointF& other) {
    this->fx_0 = other.fx_0;
    this->fy_4 = other.fy_4;
    return *this;
  };
};

TPointF StrToPosF(char const* p_c_r1_arg);  // 001F5A68
//-------------------------------------------------------------------------------------------------
struct TPointF3D {
  float fx_0;
  float fy_4;
  float fz_8;
  TPointF3D& operator=(const TPointF3D& other) {
    this->fx_0 = other.fx_0;
    this->fy_4 = other.fy_4;
    this->fz_8 = other.fz_8;
    return *this;
  }
};
TPointF3D StrToPosF3D(const char* pTxt);
//-------------------------------------------------------------------------------------------------
struct TPoint3D {
  TPoint point_0;
  int dz_8;

  TPoint3D(){
      // point_0.dx_0 = 0;
      // point_0.dy_4 = 0;
      // dz_8 = 0;
  };

  TPoint3D(int i0, int i1, int i2) {
    point_0.dx_0 = i0;
    point_0.dy_4 = i1;
    dz_8 = i2;
  };

  TPoint3D(TPoint& point) {
    point_0 = point;
  };

  TPoint3D& operator=(const TPoint3D& other) {
    point_0.dx_0 = other.point_0.dx_0;
    point_0.dy_4 = other.point_0.dy_4;
    dz_8 = other.dz_8;
    // memcpy(this, &other, sizeof(TPoint3D));
    return *this;
  };

  TPoint3D* operator+=(const TPoint3D& other) {
    point_0.dx_0 += other.point_0.dx_0;
    point_0.dy_4 += other.point_0.dy_4;
    this->dz_8 += other.dz_8;
    return this;
  };

  TPoint3D operator*(float f2) {
    int iX = point_0.dx_0 * f2;
    int iY = point_0.dy_4 * f2;
    int iZ = dz_8 * f2;

    TPoint3D tp;
    tp.point_0.dx_0 = iX;
    tp.point_0.dy_4 = iY;
    tp.dz_8 = iZ;
    return tp;
  }
};
TPoint3D StrToPos3D(const char* pTxt);
extern TPointF3D g_vZeroF3;
//-------------------------------------------------------------------------------------------------
struct TPoint4D {
  int dx_0;
  int dy_4;
  int dz_8;
  int di_C;

  TPoint4D& operator=(const TPoint4D& other) {
    this->dx_0 = other.dx_0;
    this->dy_4 = other.dy_4;
    this->dz_8 = other.dz_8;
    this->di_C = other.di_C;
    return *this;
  };
};
//-------------------------------------------------------------------------------------------------
// 001F5CA8
void StrToPos4D(char const* p_c_r0, int* p_d_r1);
//-------------------------------------------------------------------------------------------------
uint StrHexToInt(const char* pTxt);
//-------------------------------------------------------------------------------------------------

// uint StrToEaser(char const* p_c_r0); //0014BAC8
//返回值不确定，int or uint
// uint StrToCol(char const* p_c_r0_arg);	//001F5DD0

extern const TPoint3D g_vZero3;

bool PASS_FW_SPIN(int val1);
bool FTTLicence_IsData();

extern uint32 algn_47BC88[2];
extern uint32 dword_47BC90;

extern uint32 dword_47BBB0[54];

int sync_log(int prio, const char* tag, const char* fmt, ...);
int sync_log_file(int prio, const char* tag, const char* fmt, ...);

// 001BCD30
float Log2(float f_r0);

bool NIS_Active();
string hash_buf(uint8_t* const pBuf, int dlen);

#endif  //_GLOBAL_FUNC_H_