#define ACCESS_H ADMIN_LEVEL_E
#define ACCESS_3 ADMIN_LEVEL_H
#define ACCESS_2 ADMIN_LEVEL_G
#define ACCESS_1 ADMIN_LEVEL_F
#define ACCESS_0 ADMIN_USER

new Handle:g_SqlTuple;
new Handle:SqlConnection;
new g_Error[512];

// MapID in kz_maps SQL Table
new kz_mapID;
new kz_maptype[25];
new delete_entity;

new gMapName[64];
new weapon_name[33];
new Float:timer_time[33];
new Float:Update_timer[33];
// my time in top15
new Float:kz_my_protime[33];
new Float:kz_my_nubtime[33];
// Speclist
new SpecList[33] = { true, ... };
new SpecAdmImm[33];
// SQL Config
new InvisUser[33];
new InvisWater[33];
new full_Invisible[33];
new noTeleport[32];
new ShowTime[33];
new SaveCfgDate[33][40];
enum {
  TOP_NULL,
  PRO_TOP,
  NUB_TOP,
  STATS_TOP,
  WeaponTop,
  PROGEN,
  LAST_PRO10,
  PRO_RECORDS,
  PLAYERS_RANKING,
  GENERAL_RANKING,
  MAPS_STATISTIC,
  PL_STATS,
  WR_PLAY,
  HELP
};

new const g_weaponsnames[][] = {
  "",
  "p228", "shield", "scout", "250", "240", "250",
  "mac10", "240", "250", "250", "250",
  "250", "210", "240", "240", "250", "250",
  "210", "250", "220", "230", "230", "tmp", "210",
  "250", "250", "235", "221", "250", "245",
  "250",  "250", "fn57", "mp5", "vest", "vesthelm",
  "250", "hegren", "sgren", "defuser", "nvgs", "primammo",
  "secammo", "km45", "9x19mm", "nighthawk", "228compact",
  "12gauge", "autoshotgun", "mp", "c90", "cv47", "defender",
  "clarion", "krieg552", "bullpup", "magnum", "d3au1",
  "krieg550"
};

new const other_weapons_name[8][] = {
  "weapon_p90", "weapon_famas", "weapon_sg552", "weapon_awp",
  "weapon_m4a1", "weapon_m249", "weapon_ak47", "weapon_awp"
};

public plugin_sql() {
  new ErrorCode;
  SqlConnection = SQL_Connect(g_SqlTuple,ErrorCode,g_Error,511);

  if(!SqlConnection) {
    server_print("[KZ] Could not connect to SQL database.!");
    return pause("a");
  }

  QueryInstallTable();

  return PLUGIN_CONTINUE;
}

public QueryHandle(iFailState, Handle:hQuery, szError[], iErrnum, cData[], iSize, Float:fQueueTime) {
  if(iFailState != TQUERY_SUCCESS) {
    log_amx("[KZ] TOP15 SQL: SQL Error #%d - %s", iErrnum, szError);
    client_print_color(0, print_chat, "$s ^x01 Error mySQL connect", prefix);
  }
  else if(iFailState == TQUERY_QUERY_FAILED)
    set_fail_state("Query failed. QueryHandle %s", szError);

  SQL_FreeHandle(hQuery);
  return PLUGIN_CONTINUE;
}

public QueryInstallTable() {
  new CreateInto[1001];

  formatex(CreateInto, 1000, "CREATE TABLE IF NOT EXISTS `kz_pro15` (`map_id` INT(10) NOT NULL,`mapname` VARCHAR(64) NOT NULL COLLATE 'utf8_general_ci',`authid` VARCHAR(64) NOT NULL COLLATE 'utf8_general_ci',`name` VARCHAR(64) NOT NULL COLLATE 'utf8_general_ci',`time` DECIMAL(65,2) NOT NULL,`date` DATETIME NOT NULL)");
  SQL_ThreadQuery(g_SqlTuple, "QueryHandle", CreateInto);

  formatex(CreateInto, 1000, "CREATE TABLE IF NOT EXISTS `kz_nub15` (`map_id` INT(10) NOT NULL,`mapname` VARCHAR(64) NOT NULL COLLATE 'utf8_general_ci',`authid` VARCHAR(64) NOT NULL COLLATE 'utf8_general_ci',`name` VARCHAR(64) NOT NULL COLLATE 'utf8_general_ci',`time` DECIMAL(65,2) NOT NULL,`date` DATETIME NOT NULL,`checkpoints` DOUBLE(22,0) NOT NULL,`gocheck` DOUBLE(22,0) NOT NULL)");
  SQL_ThreadQuery(g_SqlTuple, "QueryHandle", CreateInto);

  formatex(CreateInto, 1000, "CREATE TABLE IF NOT EXISTS `kz_maps` (`id` INT(11) NOT NULL AUTO_INCREMENT,`mapname` VARCHAR(64) NOT NULL COLLATE 'utf8_general_ci',`type` VARCHAR(64) NULL COLLATE 'utf8_general_ci',`challenge` INT(3) NOT NULL DEFAULT '0',`entity` INT(2) NOT NULL DEFAULT '1',`start` VARCHAR(50) NULL COLLATE 'utf8_general_ci',`finish` VARCHAR(50) NULL COLLATE 'utf8_general_ci',PRIMARY KEY (`id`))");
  SQL_ThreadQuery(g_SqlTuple, "QueryHandle", CreateInto);
}

public SQL_MapID() {
  new s_Error[128], startposition[64], finishposition[64], p_start[3][64], p_finish[3][64]
  new Handle:h_Query = SQL_PrepareQuery(SqlConnection, "SELECT * FROM `kz_maps` WHERE mapname='%s'", gMapName)

  if(!SQL_Execute(h_Query))
    SQL_QueryError(h_Query, s_Error, charsmax(s_Error));
  else {
    new mapid = SQL_FieldNameToNum(h_Query, "id");
    new type = SQL_FieldNameToNum(h_Query, "type");
    new delentity = SQL_FieldNameToNum(h_Query, "entity");
    new start = SQL_FieldNameToNum(h_Query, "start");
    new finish = SQL_FieldNameToNum(h_Query, "finish");

    while(SQL_MoreResults(h_Query)) {
      kz_mapID = SQL_ReadResult(h_Query, mapid);
      SQL_ReadResult(h_Query, type, kz_maptype, charsmax(kz_maptype));
      delete_entity = SQL_ReadResult(h_Query, delentity);
      SQL_ReadResult(h_Query, start, startposition, charsmax(startposition));
      SQL_ReadResult(h_Query, finish, finishposition, charsmax(finishposition));
      SQL_NextRow(h_Query);
    }
  }

  if(!equali(startposition, "")) {
    strtok(startposition, p_start[0], charsmax(p_start[]), startposition, charsmax(startposition), ' ', true);
    strtok(startposition, p_start[1], charsmax(p_start[]), startposition, charsmax(startposition), ' ', true);
    strtok(startposition, p_start[2], charsmax(p_start[]), startposition, charsmax(startposition), ' ', true);
    DefaultStartPos[0] = str_to_float(p_start[0]);
    DefaultStartPos[1] = str_to_float(p_start[1]);
    DefaultStartPos[2] = str_to_float(p_start[2]);
    Default_SF[0] = true;
  }
  else
    Default_SF[0] = false;

  if(!equali(finishposition, "")) {
    strtok(finishposition, p_finish[0], charsmax(p_finish[]), finishposition, charsmax(finishposition), ' ', true);
    strtok(finishposition, p_finish[1], charsmax(p_finish[]), finishposition, charsmax(finishposition), ' ', true);
    strtok(finishposition, p_finish[2], charsmax(p_finish[]), finishposition, charsmax(finishposition), ' ', true);
    DefaultFinishPos[0] = str_to_float(p_finish[0]);
    DefaultFinishPos[1] = str_to_float(p_finish[1]);
    DefaultFinishPos[2] = str_to_float(p_finish[2]);
    Default_SF[1] = true;
  }
  else
    Default_SF[1] = false;

  if(equali(kz_maptype, "slide")) mapIsSlide = true;
  if(equali(kz_maptype, "gravity")) mapIsGravity = true;
  if(equali(kz_maptype, "")) kz_maptype = "n/a";

  if(delete_entity)
    for(new i = 0; i < sizeof(g_remove_ent); i++)
      sx_remove_entity(g_remove_ent[i], "classname", 0, "");

  if(!kz_mapID) {
    new Handle:h_Query2 = SQL_PrepareQuery(SqlConnection, "INSERT INTO `kz_maps` (`mapname`) VALUES ('%s');", gMapName);
    if(SQL_Execute(h_Query2))
      kz_mapID = SQL_GetInsertId(h_Query2);
    SQL_FreeHandle(h_Query2);
  }

  SQL_FreeHandle(h_Query);

  server_print("[KZ_SQL] ID Map = %d", kz_mapID);
  server_print("[KZ_SQL] Type map = %s", kz_maptype);

  return PLUGIN_HANDLED;
}

public SQL_StartFinish(bool:L, Float:position[3]) {
  if(L)
    Default_SF[0] = true;
  else
    Default_SF[1] = true;

  new createinto[1001];
  formatex(createinto, sizeof createinto - 1, "UPDATE `kz_maps` SET `%s` = '%f %f %f' WHERE (`id` = %d)", (L ? "start":"finish"), position[0], position[1], position[2], kz_mapID);
  SQL_ThreadQuery(g_SqlTuple, "SQL_WorkHandle", createinto);
}

public SQL_StatsAdd(iFailState, Handle:hQuery, szError[], iErrnum, cData[], iSize, Float:fQueueTime) {
  new id = cData[0];
  new style = cData[1];
  new Float:time = Update_timer[id];
  new check = cData[3];
  new gocheck = cData[4];
  if(iFailState != TQUERY_SUCCESS) {
    log_amx("[KZ] TOP15 SQL: SQL Error #%d - %s", iErrnum, szError);
    client_print_color(0, print_chat,  "%s^x01 %F", prefix, LANG_PLAYER, "KZ_TOP15_SQL_ERROR");
  }
  new checkpoints[32], gochecks[32];
  new createinto[1001];
  new name[32], recdata[64];
  get_user_name(id, name, 31);
  get_time("%Y%m%d%H%M%S", recdata, sizeof recdata - 1);
  new wpn = get_user_weapon(id);
  replace_all(name, 31, "'", "");

  new bool:user_weapon = false;
  new weapon = get_user_weapon(id);
  get_weaponname(weapon, weapon_name, charsmax(weapon_name));

  for(new i = 0; i < 8; i++)
    if(equali(other_weapons_name[i], weapon_name))
      user_weapon = true;

  if(SQL_NumResults(hQuery) == 0) {
    formatex(checkpoints, 31, ", %d", check);
    formatex(gochecks, 31, ", %d", gocheck);

    if(user_weapon && get_pcvar_num(sv_airaccelerate) == 10) {
      formatex(createinto, sizeof createinto - 1, "INSERT INTO `%s` VALUES (%d, '%s', '%s', '%s', '%s', '%f', '%s'%s%s)", style == PRO_TOP ? "kz_weapon_pro" : "kz_weapon_nub", kz_mapID, gMapName, g_weaponsnames[wpn], kz_authid[id], name, time, recdata, style == PRO_TOP ? "" : checkpoints, style == PRO_TOP ? "" : gochecks);
      SQL_ThreadQuery(g_SqlTuple, "QueryHandle", createinto);
      GetNewRank(id, style, true);
    }
    else {
      formatex(createinto, sizeof createinto - 1, "INSERT INTO `%s` VALUES (%d, '%s', '%s', '%s', '%f', '%s'%s%s)", style == PRO_TOP ? "kz_pro15" : "kz_nub15", kz_mapID, gMapName, kz_authid[id], name, time, recdata, style == PRO_TOP ? "" : checkpoints, style == PRO_TOP ? "" : gochecks);
      SQL_ThreadQuery(g_SqlTuple, "QueryHandle", createinto);
      GetNewRank(id, style, false);
    }
  }
  else {
    new Float:oldtime, Float:thetime;
    SQL_ReadResult(hQuery, 0, oldtime);

    if(time < oldtime) {
      formatex(checkpoints, 31, ", checkpoints=%d", check);
      formatex(gochecks, 31, ", gocheck=%d", gocheck);
      thetime = oldtime - time;

      show_finish_message(id, thetime, false, true);

      if(user_weapon && get_pcvar_num(sv_airaccelerate) == 10) {
        formatex(createinto, sizeof createinto - 1, "UPDATE `%s` SET time='%f', date='%s' %s%s WHERE map_id=%d AND weapon='%s' AND authid='%s'", style == PRO_TOP ? "kz_weapon_pro" : "kz_weapon_nub", time, recdata, style == PRO_TOP ? "" : checkpoints, style == PRO_TOP ? "" : gochecks, kz_mapID, g_weaponsnames[wpn], kz_authid[id]);
        SQL_ThreadQuery(g_SqlTuple, "QueryHandle", createinto);
        GetNewRank(id, style, true);
      }
      else {
        formatex(createinto, sizeof createinto - 1, "UPDATE `%s` SET time='%f', date='%s' %s%s WHERE map_id=%d AND authid='%s'", style == PRO_TOP ? "kz_pro15" : "kz_nub15", time, recdata, style == PRO_TOP ? "" : checkpoints, style == PRO_TOP ? "" : gochecks, kz_mapID, kz_authid[id]);
        SQL_ThreadQuery(g_SqlTuple, "QueryHandle", createinto);
        GetNewRank(id, style, false);
      }
    }
    else {
      thetime = time - oldtime;
      show_finish_message(id, thetime, false, false);
    }
  }

  return PLUGIN_HANDLED;
}

stock GetNewRank(id, type, bool:user_weapon) {
  new createinto[1000];

  new cData[2];
  cData[0] = id;
  cData[1] = type;
  new wpn = get_user_weapon(id);

  if(user_weapon && get_pcvar_num(sv_airaccelerate) == 10)
    formatex(createinto, charsmax(createinto), "SELECT authid FROM `%s` WHERE map_id=%d AND weapon='%s' ORDER BY time", type == PRO_TOP ? "kz_weapon_pro" : "kz_weapon_nub", kz_mapID, g_weaponsnames[wpn]);
  else
    formatex(createinto, charsmax(createinto), "SELECT authid FROM `%s` WHERE map_id=%d ORDER BY time", type == PRO_TOP ? "kz_pro15" : "kz_nub15", kz_mapID);

  SQL_ThreadQuery(g_SqlTuple, "GetNewRank_QueryHandler", createinto, cData, 2);
}

public GetNewRank_QueryHandler(iFailState, Handle:hQuery, szError[], iErrnum, cData[], iSize, Float:fQueueTime) {
  new id = cData[0];
  if(iFailState != TQUERY_SUCCESS)
    return log_amx("TOP15 SQL: SQL Error #%d - %s", iErrnum, szError)

  new authid[32], namez[32], i = 0;
  get_user_name(id, namez, 31);

  new bool:user_weapon = false;
  new weapon = get_user_weapon(id);
  get_weaponname(weapon, weapon_name, charsmax(weapon_name));

  for(new i = 0; i < 8; i++)
    if(equali(other_weapons_name[i], weapon_name))
      user_weapon = true;

  while(SQL_MoreResults(hQuery)) {
    i++;
    SQL_ReadResult(hQuery, 0, authid, 31);
    if(equal(authid, kz_authid[id])) {
      if(user_weapon)
        client_print_color(0, print_chat, "^x04%s^x03 %s^x04 is now ^x03%d^x04 in^x03 %s^x04",prefix, namez, i, cData[1] == PRO_TOP ? "Professional Weapon Top" : "General Weapon Top");
      else
        client_print_color(0, print_chat, "^x04%s^x03 %s^x04 is now ^x03%d^x04 in^x03 %s^x04",prefix, namez, i, cData[1] == PRO_TOP ? "Professional Top" : "General Top");
      break;
    }
    SQL_NextRow(hQuery);
  }

  SQL_FreeHandle(hQuery);
  return PLUGIN_CONTINUE;
}

public mytime(id, type) {
  new createinto[256], cData[2];
  cData[0] = id;
  cData[1] = type;
  formatex(createinto, sizeof createinto - 1, "SELECT * FROM %s WHERE map_id=%d AND authid='%s'", type == PRO_TOP ? "kz_pro15" : "kz_nub15", kz_mapID, kz_authid[id]);
  SQL_ThreadQuery(g_SqlTuple, "SQL_MyTimeHandle", createinto, cData, 2);
}

public SQL_MyTimeHandle(failstate, Handle:hQuery, error[], errcode, cData[], iSize, Float:fQueueTime) {
  new id = cData[0];
  new type = cData[1];
  if(failstate == TQUERY_CONNECT_FAILED)
    set_fail_state("Could not connect to database.");
  else if(failstate == TQUERY_QUERY_FAILED)
    set_fail_state("Query failed. SQL_MyTimeHandle %s", error);
  else if(errcode)
    log_amx("Error on query: %s", error);
  else {
    if(SQL_NumResults(hQuery)) {
      if(type == PRO_TOP)
        SQL_ReadResult(hQuery, 4, kz_my_protime[id]);
      else
        SQL_ReadResult(hQuery, 4, kz_my_nubtime[id]);
    }
    else {
      if(type == PRO_TOP)
        kz_my_protime[id] = 0.0;
      else
        kz_my_nubtime[id] = 0.0;
    }
  }
  SQL_FreeHandle(hQuery);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SQL CFG ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public SQL_Config(id) {
  new createinto[128], cData[1];
  cData[0] = id;
  formatex(createinto, sizeof createinto - 1, "SELECT * FROM kzp_players WHERE auth='%s'", kz_authid[id]);
  g_SqlTuple = SQL_MakeStdTuple();
  SQL_ThreadQuery(g_SqlTuple, "SQL_ConfigHandle", createinto, cData, 1);
}

public SQL_ConfigHandle(failstate, Handle:hQuery, error[], errcode, cData[], iSize, Float:fQueueTime) {
  new id = cData[0];
  if(failstate == TQUERY_CONNECT_FAILED)
    set_fail_state("Could not connect to database.");
  else if(failstate == TQUERY_QUERY_FAILED )
    set_fail_state("Query failed. SQL_Config %s", error);
  else if(errcode)
    log_amx("Error on query: %s", error);
  else {
    if(SQL_NumResults(hQuery)) {
      ShowTime[id] = SQL_ReadResult(hQuery, 8);
      InvisUser[id] = SQL_ReadResult(hQuery, 9);
      InvisWater[id] = SQL_ReadResult(hQuery, 10);
      full_Invisible[id] = SQL_ReadResult(hQuery, 11);
      noTeleport[id] = SQL_ReadResult(hQuery, 12);
      SpecList[id] = SQL_ReadResult(hQuery, 13);
      SpecAdmImm[id] = SQL_ReadResult(hQuery, 14);
      SQL_ReadResult(hQuery, 4, SaveCfgDate[id], charsmax(SaveCfgDate));
    }
    else {
      InvisUser[id] = 0;
      InvisWater[id] = 0;
      full_Invisible[id] = 0;
      noTeleport[id] = 0;
      SpecList[id] = 1;
      SpecAdmImm[id] = 0;
      ShowTime[id] = 2;
    }

    //server_print("user: %d, i_user: %d, i_water: %d, fullinvis: %d, notp: %d, spec: %d, specadm: %d, stime: %d, lastsave: %s", id, InvisUser[id], InvisWater[id], full_Invisible[id], noTeleport[id], SpecList[id], SpecAdmImm[id], ShowTime[id], SaveCfgDate[id]);
  }
  SQL_FreeHandle(hQuery);
}


public SQL_ConfigSave(id) {
  new createinto[128], cData[1];
  cData[0] = id;
  formatex(createinto, sizeof createinto - 1, "SELECT * FROM kzp_players WHERE auth='%s'", kz_authid[id]);
  SQL_ThreadQuery(g_SqlTuple, "SQL_ConfigSaveHandle", createinto, cData, 1);
}

public SQL_ConfigSaveHandle(failstate, Handle:hQuery, error[], errcode, cData[], iSize, Float:fQueueTime) {
  new id = cData[0];
  new nowdate[40];
  get_time("%Y-%m-%d %H:%M:%S", nowdate, sizeof nowdate - 1);
  SaveCfgDate[id] = nowdate;

  if(failstate == TQUERY_CONNECT_FAILED)
    set_fail_state("Could not connect to database.");
  else if(failstate == TQUERY_QUERY_FAILED)
    set_fail_state("Query failed. SQL_ConfigSaveHandle %s", error);
  else if(errcode)
    log_amx("Error on query: %s", error);
  else {
    if(SQL_NumResults(hQuery)) {
      new createinto[1001];
      formatex(createinto, sizeof createinto - 1, "UPDATE `kzp_players` SET `showTime` = %d,`invisUser` = %d,`invisWater` = %d,`invisFull` = %d,`noTeleport` = %d,`specList` = %d,`specAdmin` = %d, `date` = '%s' WHERE (`auth` = '%s')", ShowTime[id], InvisUser[id], InvisWater[id], full_Invisible[id], noTeleport[id], SpecList[id], SpecAdmImm[id], SaveCfgDate[id], kz_authid[id]);
      SQL_ThreadQuery(g_SqlTuple, "SQL_WorkHandle", createinto);
      client_print_color(id, print_chat, "^x01%s^x03 The config was saved successfully.", prefix);
    }
    /*else {
      new createinto[1001];
      formatex(createinto, sizeof createinto - 1, "INSERT INTO `kzp_players` VALUES (null, '%s', %d, %d, %d, %d, %d, %d, %d, '%s')", kz_authid[id], ShowTime[id], InvisUser[id], InvisWater[id], full_Invisible[id], noTeleport[id], SpecList[id], SpecAdmImm[id], SaveCfgDate[id]);
      SQL_ThreadQuery(g_SqlTuple, "SQL_WorkHandle", createinto);
      client_print_color(id, print_chat, "^x01%s^x03 The config was saved successfully.", prefix);
    }*/
  }
  SQL_FreeHandle(hQuery);
}

public SQL_WorkHandle(failstate, Handle:hQuery, error[], errcode, cData[], iSize, Float:fQueueTime) {
  if(failstate == TQUERY_CONNECT_FAILED)
    set_fail_state("Could not connect to database.");
  else if(failstate == TQUERY_QUERY_FAILED)
    set_fail_state("Query failed. SQL_WorkHandle %s", error);
  else if(errcode)
    log_amx("Error on query: %s", error);
  SQL_FreeHandle(hQuery);
}
