context: #region using directives
  
  using System;
  using System.Collections.Generic;
  using System.IO;
  using Newtonsoft.Json;
  using Newtonsoft.Json.Converters;
  using PoGo.PokeMobBot.Logic.Logging;
  using PokemonGo.RocketAPI;
  using PokemonGo.RocketAPI.Enums;
  using POGOProtos.Enums;
  using POGOProtos.Inventory.Item;
  using System.Linq;
  using GeoCoordinatePortable;
  using PoGo.PokeMobBot.Logic.API;
  
  #endregion
  
  namespace PoGo.PokeMobBot.Logic
  {
      internal class AuthSettings
      {
          [JsonIgnore]
          private string _filePath;
          public AuthType AuthType;
          public string GoogleRefreshToken = "";
          public string GoogleUsername;
          public string GooglePassword;
          public string PtcUsername;
          public string PtcPassword;
          public bool UseProxy;
          public string ProxyLogin;
          public string ProxyPass;
          public string ProxyUri;
  
          public void Load(string path)
          {
              try
              {
                  _filePath = path;
  
                  if (File.Exists(_filePath))
                  {
                      //if the file exists, load the settings
                      var input = File.ReadAllText(_filePath);
  
                      var settings = new JsonSerializerSettings();
                      settings.Converters.Add(new StringEnumConverter { CamelCaseText = true });
  
                      JsonConvert.PopulateObject(input, this, settings);
                  }
                  else
                  {
                      Save(_filePath);
                  }
              }
              catch (JsonReaderException exception)
              {
                  if (exception.Message.Contains("Unexpected character") && exception.Message.Contains("PtcUsername"))
                      Logger.Write("JSON Exception: You need to properly configure your PtcUsername using quotations.",
                          LogLevel.Error);
                  else if (exception.Message.Contains("Unexpected character") && exception.Message.Contains("PtcPassword"))
                      Logger.Write(
                          "JSON Exception: You need to properly configure your PtcPassword using quotations.",
                          LogLevel.Error);
                  else if (exception.Message.Contains("Unexpected character") &&
                           exception.Message.Contains("GoogleUsername"))
                      Logger.Write(
                          "JSON Exception: You need to properly configure your GoogleUsername using quotations.",
                          LogLevel.Error);
                  else if (exception.Message.Contains("Unexpected character") &&
                           exception.Message.Contains("GooglePassword"))
                      Logger.Write(
                          "JSON Exception: You need to properly configure your GooglePassword using quotations.",
                          LogLevel.Error);
                  else
                      Logger.Write("JSON Exception: " + exception.Message, LogLevel.Error);
              }
          }
  
          public void Save(string path)
          {
              var output = JsonConvert.SerializeObject(this, Formatting.Indented,
                  new StringEnumConverter { CamelCaseText = true });
  
              var folder = Path.GetDirectoryName(path);
              if (folder != null && !Directory.Exists(folder))
              {
                  Directory.CreateDirectory(folder);
              }
  
              File.WriteAllText(path, output);
          }
  
          public void Save()
          {
              if (!string.IsNullOrEmpty(_filePath))
              {
                  Save(_filePath);
              }
          }
      }
  
      public static class RuntimeSettings
      {
          public static int StopsHit = 0;
          public static DateTime startTime = DateTime.Now;
          public static bool DelayingScan = false;
          public static int PokemonScanDelay = 10000;// in ms
          public static bool BreakOutOfPathing = false;
          public static string lastPokeStopId = "69694201337";//these don't matter
          public static string TargetStopID = "420Ayylmao";//so keep them funny. Stop PRing lame changes to these. Go crazy
          public static GeoCoordinatePortable.GeoCoordinate lastPokeStopCoordinate = new GeoCoordinate(0,0);
          public static bool CheckScan()
          {
              if (DelayingScan)
              {
                  if ((DateTime.Now.Subtract(startTime).TotalMilliseconds > PokemonScanDelay) && DelayingScan)
                  {
                      DelayingScan = false;
                  }
                  return false;
              }
              else
              {
                  startTime = DateTime.Now;
                  DelayingScan = true;
                  return true;
              }
          }
      }
  
  
      public class DeviceSettings
      {
  
          private static Random random = new Random();
          public static IDictionary<string, string> phone_item = RandomPhone();
          #region DeviceSettingsTemplate
          //public string DeviceId = RandomString(16,"0123456789abcdef"); // "ro.build.id";
          //public string AndroidBoardName = "thunderc"; // "ro.product.board";
          //public string AndroidBootLoader = "unknown"; //"ro.product.bootloader; //I think
          //public string DeviceBrand = "LGE";// "product.brand";
          //public string DeviceModel = "thunderc"; //"product.device";
          //public string DeviceModelIdentifier = "GWK74 10282011";// "build.display.id";
          //public string DeviceModelBoot = "thunderc"; //"boot.hardware";
          //public string HardwareManufacturer = "LGE"; //"product.manufacturer";
          //public string HardWareModel = "LG-VS660"; //"product.model";
          //public string FirmwareBrand = "thunderc"; //"product.name"; //iOS is "iPhone OS"
          //public string FirmwareTags = "test-keys"; //"build.tags";
          //public string FirmwareType = "eng"; //"build.type"; //iOS is "iOS version"
          //public string FirmwareFingerprint = "lge/lge_gelato/VM701:2.3.4/GRJ22/ZV4.19cd75186d:user/release-keys"; //"build.fingerprint";
          #endregion
          #region New Format by Lars
          /*
          public string DeviceId = RandomString(16, "0123456789abcdef"); // "ro.build.id";
          public string AndroidBoardName = phone_item["AndriodBoardName"]; // "ro.product.board";
          public string AndroidBootLoader = phone_item["AndroidBootLoader"]; //"ro.product.bootloader; //I think
          public string DeviceBrand = phone_item["DeviceBrand"];// "product.brand";
          public string DeviceModel = phone_item["DeviceModel"]; //"product.device";
          public string DeviceModelIdentifier = phone_item["DeviceModelIdentifier"] + "_" + RandomString(random.Next(4, 10), "0123456789abcdef");// "build.display.id";
          public string DeviceModelBoot = phone_item["DeviceModelBoot"]; //"boot.hardware";
          public string HardwareManufacturer = phone_item["DeviceModelBoot"]; //"product.manufacturer";
          public string HardWareModel = phone_item["DeviceModelIdentifier"]; //"product.model";
          public string FirmwareBrand = phone_item["DeviceModel"]; //"product.name"; //iOS is "iPhone OS"
          public string FirmwareTags = "test-keys"; //"build.tags";
          public string FirmwareType = "en"; //"build.type"; //iOS is "iOS version"
          public string FirmwareFingerprint = phone_item["DeviceBrand"] + "/" + 
                                                      phone_item["DeviceModel"] + "/" +
                                                      phone_item["FirmwareBrand"] + ":" + 
                                                      RandomAndroidVersion() + "/" +
                                                      RandomString(random.Next(4, 10), "0123456789abcdef") + 
                                                      ":user/release-keys";
  
          */
          #endregion
          public string DeviceId = RandomString(16, "0123456789abcdef"); // "ro.build.id";
          public string AndroidBoardName = phone_item["board"]; // "ro.product.board";
          public string AndroidBootLoader = "unknown"; //"ro.product.bootloader; //I think
          public string DeviceBrand = phone_item["mft"];// "product.brand";
          public string DeviceModel = phone_item["model"]; //"product.device";
          public string DeviceModelIdentifier = phone_item["name"] + "_" + RandomString(random.Next(4, 10), "0123456789abcdef");// "build.display.id";
          public string DeviceModelBoot = phone_item["board"]; //"boot.hardware";
          public string HardwareManufacturer = phone_item["mft"]; //"product.manufacturer";
          public string HardWareModel = phone_item["model"]; //"product.model";
          public string FirmwareBrand = phone_item["board"]; //"product.name"; //iOS is "iPhone OS"
          public string FirmwareTags = "test-keys"; //"build.tags";
          public string FirmwareType = "eng"; //"build.type"; //iOS is "iOS version"
          public string FirmwareFingerprint =
             phone_item["mft"] + "/" +
              phone_item["mft"] + "_" + phone_item["board"] + ":" +
                                                      RandomAndroidVersion() + "/" +
                                                      RandomString(random.Next(4, 10), "0123456789abcdef") +
                                                      ":user/release-keys";
  
  
  
          private static string RandomString(int length, string chars)
          {
              return new string(Enumerable.Repeat(chars, length)
                .Select(s => s[random.Next(s.Length)]).ToArray());
          }
          private static string RandomAndroidVersion()
          {
              //possible android versions based on PokemonGo requirements
              List<string> possibleAndroidVersions = new List<string>() { "4.4", "4.4.1", "4.4.2", "4.4.3", "4.4.4", "5.0", "5.0.1", "5.0.2", "5.1", "5.1.1", "6.0", "6.0.1" };
              //generate a random index to choose version
              int index = random.Next(0, possibleAndroidVersions.Count);
              //return random vserion
              return possibleAndroidVersions[index];
          }
          public static IDictionary<string, string> RandomPhone()
          {
              List<IDictionary<string, string>> phone_list = GetPhoneList();
              Random rnd = new Random();
  
              int phone_index = rnd.Next(0, phone_list.Count);
              IDictionary<string, string> phone_item = phone_list[phone_index];
              return phone_item;
          }
  
          #region GetPhoneList
          // data from https://conf.skype.com/whitelist26.txt
          private static List<IDictionary<string, string>> GetPhoneList()
          {
              List<IDictionary<string, string>> phone_list = new List<IDictionary<string, string>>();
  
  
              IDictionary<string, string> phone_item = new Dictionary<string, string>();
  
  
              // ******* Samsung ******* //
  
              phone_item = new Dictionary<string, string>();
              phone_item["name"] = "Nexus S";
              phone_item["mft"] = "samsung";
              phone_item["board"] = "herring";
              phone_item["model"] = "Nexus S";
              phone_item["product"] = "soju.*";
              phone_item["device"] = "crespo.*";
              phone_list.Add(phone_item);
  
              phone_item = new Dictionary<string, string>();
              phone_item["name"] = "Galaxy Tab 10.1 (Wifi)";
              phone_item["mft"] = "samsung";
              phone_item["board"] = "samsung";
              phone_item["board"] = "GT-P7510";
              phone_item["model"] = "GT-P7510";
              phone_item["product"] = "GT-P7510";
              phone_item["device"] = "GT-P7510";
              phone_list.Add(phone_item);
  
              phone_item = new Dictionary<string, string>();
              phone_item["name"] = "Galaxy Nexus";
              phone_item["mft"] = "samsung";
              phone_item["board"] = "google";
              phone_item["board"] = "tuna";
              phone_item["model"] = "Galaxy Nexus";
              phone_item["product"] = "mysid";
              phone_item["device"] = "toro";
              phone_list.Add(phone_item);
  
              phone_item = new Dictionary<string, string>();
              phone_item["name"] = "Galaxy Nexus";
              phone_item["mft"] = "samsung";
              phone_item["board"] = "google";
              phone_item["board"] = "tuna";
              phone_item["model"] = "Galaxy Nexus";
              phone_item["product"] = "yakju";
              phone_item["device"] = "maguro";
              phone_list.Add(phone_item);
  
              phone_item = new Dictionary<string, string>();
              phone_item["name"] = "Samsung Galaxy S 4G";
              phone_item["mft"] = "Samsung";
              phone_item["board"] = "TMOUS";
              phone_item["board"] = "SGH-T959V";
              phone_item["model"] = "SGH-T959V";
              phone_item["product"] = "SGH-T959V";
              phone_item["device"] = "SGH-T959V";
              phone_list.Add(phone_item);
  
              phone_item = new Dictionary<string, string>();
  
gt:             phone_item["name"] = "Samsung Galaxy S";