// GridTracker Copyright © 2024 GridTracker.org
// All rights reserved.
// See LICENSE for more information.

GT.lotwCallsigns = Object();
GT.lotwFile = "";
GT.lotwWhenDate = 0;
GT.lotwLoadTimer = null;

GT.eqslCallsigns = Object();
GT.eqslFile = "";
GT.eqslWhenDate = 0;
GT.eqslLoadTimer = null;

GT.ulsCallsigns = Object();
GT.ulsCallsignsCount = 0;
GT.ulsLoadTimer = null;
GT.ulsFile = "";

GT.cacCallsigns = Object();
GT.cacFile = "";
GT.cacWhenDate = 0;
GT.cacLoadTimer = null;

GT.oqrsCallsigns = Object();
GT.oqrsFile = "";
GT.oqrsWhenDate = 0;
GT.oqrsLoadTimer = null;

function dumpFile(file)
{
  try
  {
    if (fs.existsSync(file)) fs.unlinkSync(file);
  }
  catch (e) {}
}

function dumpDir(dir)
{
  try
  {
    if (fs.existsSync(dir)) fs.rmdirSync(dir);
  }
  catch (e) {}
}

function callsignServicesInit()
{
  // Dump old data files we no longer reference
  dumpFile(GT.jsonDir + "uls-callsigns.json");
  dumpFile(GT.jsonDir + "us-callsigns.json");
  dumpFile(GT.jsonDir + "lotw-callsigns.json");
  dumpFile(GT.jsonDir + "lotw-ts-callsigns.json");
  dumpFile(GT.jsonDir + "eqsl-callsigns.json");
  dumpFile(GT.jsonDir + "cloqrs-callsigns.json");
  dumpFile(GT.jsonDir + "internal_qso.json");
  dumpFile(GT.jsonDir + "spots.json");
  dumpDir(GT.jsonDir);

  GT.lotwFile = GT.NWappData + "lotw-ts-callsigns.json";
  GT.eqslFile = GT.NWappData + "eqsl-callsigns.json";
  GT.oqrsFile = GT.NWappData + "cloqrs-callsigns.json";
  GT.cacFile = GT.NWappData + "canada-callsigns.txt";
  GT.ulsFile = GT.NWappData + "uls-callsigns.txt";

  if (GT.callsignLookups.lotwUseEnable)
  {
    lotwLoadCallsigns();
  }
  if (GT.callsignLookups.eqslUseEnable)
  {
    eqslLoadCallsigns();
  }
  if (GT.callsignLookups.ulsUseEnable)
  {
    ulsLoadCallsigns();
  }
  if (GT.callsignLookups.cacUseEnable)
  {
    cacLoadCallsigns();
  }
  if (GT.callsignLookups.oqrsUseEnable)
  {
    oqrsLoadCallsigns();
  }

  lotwSettingsDisplay();
  eqslSettingsDisplay();
  ulsSettingsDisplay();
  cacSettingsDisplay();
  oqrsSettingsDisplay();
}

function saveCallsignSettings()
{
  GT.localStorage.callsignLookups = JSON.stringify(GT.callsignLookups);
}

function lotwLoadCallsigns()
{
  var now = timeNowSec();
  if (now - GT.callsignLookups.lotwLastUpdate > 86400 * 7)
  { GT.callsignLookups.lotwLastUpdate = 0; }
  else
  {
    var lotwWhenTimer = 86400 * 7 - (now - GT.callsignLookups.lotwLastUpdate);
    GT.lotwWhenDate = now + lotwWhenTimer;
    GT.lotwLoadTimer = nodeTimers.setTimeout(lotwDownload, lotwWhenTimer * 1000);
  }

  try
  {
    if (!fs.existsSync(GT.lotwFile))
    {
      GT.callsignLookups.lotwLastUpdate = 0;
    }
    else
    {
      GT.lotwCallsigns = require(GT.lotwFile);
      if (Object.keys(GT.lotwCallsigns).length < 100)
      {
        lotwDownload();
      }
    }
    if (GT.callsignLookups.lotwLastUpdate == 0)
    {
      lotwDownload();
    }
  }
  catch (e)
  {
    console.log(e);
    GT.callsignLookups.lotwLastUpdate = 0;
    lotwDownload();
  }
}

function lotwSettingsDisplay()
{
  lotwUseEnable.checked = GT.callsignLookups.lotwUseEnable;

  if (GT.callsignLookups.lotwLastUpdate == 0)
  {
    lotwUpdatedTd.innerHTML = "Never";
  }
  else
  {
    lotwUpdatedTd.innerHTML = userTimeString(
      GT.callsignLookups.lotwLastUpdate * 1000
    );
  }

  if (!GT.callsignLookups.lotwUseEnable)
  {
    if (GT.lotwLoadTimer != null) nodeTimers.clearTimeout(GT.lotwLoadTimer);
    GT.lotwLoadTimer = null;
    GT.lotwCallsigns = Object();
  }
  lotwCountTd.innerHTML = Object.keys(GT.lotwCallsigns).length;
}

function removeLotwFile()
{
  try
  {
    fs.unlinkSync(GT.lotwFile);
  }
  catch (err)
  {
    // handle the error
  }
  GT.callsignLookups.lotwLastUpdate = 0;
  if (GT.lotwLoadTimer != null)
  {
    nodeTimers.clearTimeout(GT.lotwLoadTimer);
    GT.lotwLoadTimer = null;
  }
}

function lotwValuesChanged()
{
  let wasEnabled = GT.callsignLookups.lotwUseEnable;
  GT.callsignLookups.lotwUseEnable = lotwUseEnable.checked;
  saveCallsignSettings();
  if (GT.callsignLookups.lotwUseEnable == true)
  {
    if (wasEnabled == false)
    {
      removeLotwFile();
    }
    lotwLoadCallsigns();
  }
  else
  {
    removeLotwFile();
    lotwSettingsDisplay();
  }

  setAlertVisual();
  goProcessRoster();
  if (GT.rosterInitialized) GT.callRosterWindowHandle.window.resize();
}

function lotwDownload(fromSettings)
{
  lotwUpdatedTd.innerHTML = "<b><i>Downloading...</i></b>";
  getBuffer(
    "https://lotw.arrl.org/lotw-user-activity.csv",
    processLotwCallsigns,
    null,
    "https",
    443
  );
}

function processLotwCallsigns(result, flag)
{
  // var result = String(buffer);
  var lines = Array();
  lines = result.split("\n");

  var lotwCallsigns = Object();
  for (x in lines)
  {
    var breakout = lines[x].split(",");
    if (breakout.length == 3)
    {
      var dateTime = new Date(
        Date.UTC(
          breakout[1].substr(0, 4),
          parseInt(breakout[1].substr(5, 2)) - 1,
          breakout[1].substr(8, 2),
          0,
          0,
          0
        )
      );
      lotwCallsigns[breakout[0]] = parseInt(dateTime.getTime() / 1000) / 86400;
    }
  }

  GT.callsignLookups.lotwLastUpdate = timeNowSec();
  saveCallsignSettings();

  var now = timeNowSec();
  if (GT.lotwLoadTimer != null) nodeTimers.clearTimeout(GT.lotwLoadTimer);

  var lotwWhenTimer = 86400 * 7 - (now - GT.callsignLookups.lotwLastUpdate);
  GT.lotwWhenDate = now + lotwWhenTimer;
  GT.lotwLoadTimer = nodeTimers.setTimeout(lotwDownload, lotwWhenTimer * 1000);

  if (Object.keys(lotwCallsigns).length > 100)
  {
    GT.lotwCallsigns = lotwCallsigns;
    fs.writeFileSync(GT.lotwFile, JSON.stringify(GT.lotwCallsigns));
  }

  lotwSettingsDisplay();
}

function cacLoadCallsigns()
{
  var now = timeNowSec();
  if (now - GT.callsignLookups.cacLastUpdate > 86400 * 7)
  { GT.callsignLookups.cacLastUpdate = 0; }
  else
  {
    var cacWhenTimer = 86400 * 7 - (now - GT.callsignLookups.cacLastUpdate);
    GT.cacWhenDate = now + cacWhenTimer;
    GT.cacLoadTimer = nodeTimers.setTimeout(cacDownload, cacWhenTimer * 1000);
  }

  try
  {
    if (!fs.existsSync(GT.cacFile))
    {
      GT.callsignLookups.cacLastUpdate = 0;
    }
    else
    {
      parseCacCallsigns(fs.readFileSync(GT.cacFile, "UTF-8"));
    }
    if (GT.callsignLookups.cacLastUpdate == 0)
    {
      cacDownload();
    }
  }
  catch (e)
  {
    GT.callsignLookups.cacLastUpdate = 0;
    cacDownload();
  }
}

function parseCacCallsigns(data)
{
  let callsignRows = data.split("\n");
  for (let x = 0; x < callsignRows.length; x++)
  {
    if (callsignRows[x].length > 1)
    {
      GT.cacCallsigns[callsignRows[x].substr(8)] = callsignRows[x].substr(6, 2);
    }
  }
  fs.writeFileSync(GT.cacFile, data, "UTF-8");
}

function processCacCallsigns(buffer, flag)
{
  let data = (typeof buffer == "object") ? String(buffer) : buffer;
  parseCacCallsigns(data);

  GT.callsignLookups.cacLastUpdate = timeNowSec();
  saveCallsignSettings();

  var now = timeNowSec();
  if (GT.cacLoadTimer != null) nodeTimers.clearTimeout(GT.cacLoadTimer);

  var cacWhenTimer = 86400 * 7 - (now - GT.callsignLookups.cacLastUpdate);
  GT.cacWhenDate = now + cacWhenTimer;
  GT.cacLoadTimer = nodeTimers.setTimeout(cacDownload, cacWhenTimer * 1000);

  cacSettingsDisplay();
}

function cacDownload(fromSettings)
{
  cacUpdatedTd.innerHTML = "<b><i>Downloading...</i></b>";
  getBuffer(
    "https://storage.googleapis.com/gt_app/canada.txt",
    processCacCallsigns,
    null,
    "http",
    80
  );
}

function cacSettingsDisplay()
{
  cacUseEnable.checked = GT.callsignLookups.cacUseEnable;

  if (GT.callsignLookups.cacLastUpdate == 0)
  {
    cacUpdatedTd.innerHTML = "Never";
  }
  else
  {
    cacUpdatedTd.innerHTML = userTimeString(GT.callsignLookups.cacLastUpdate * 1000);
  }

  if (!GT.callsignLookups.cacUseEnable)
  {
    if (GT.cacLoadTimer != null) nodeTimers.clearTimeout(GT.cacLoadTimer);
    GT.cacLoadTimer = null;
    GT.cacCallsigns = Object();
  }
  cacCountTd.innerHTML = Object.keys(GT.cacCallsigns).length;
}

function removeCacFile()
{
  try
  {
    fs.unlinkSync(GT.cacFile);
  }
  catch (err)
  {
    // handle the error
  }
  GT.callsignLookups.cacLastUpdate = 0;
  if (GT.cacLoadTimer != null)
  {
    nodeTimers.clearTimeout(GT.cacLoadTimer);
    GT.cacLoadTimer = null;
  }
}

function cacValuesChanged()
{
  let wasEnabled = GT.callsignLookups.cacUseEnable;
  GT.callsignLookups.cacUseEnable = cacUseEnable.checked;
  saveCallsignSettings();
  if (GT.callsignLookups.cacUseEnable == true)
  {
    if (wasEnabled == false)
    {
      removeCacFile();
    }
    cacLoadCallsigns();
  }
  else
  {
    removeCacFile();
    cacSettingsDisplay();
  }
}

function oqrsLoadCallsigns()
{
  var now = timeNowSec();
  if (now - GT.callsignLookups.oqrsLastUpdate > 86400 * 7)
  { GT.callsignLookups.oqrsLastUpdate = 0; }
  else
  {
    var oqrsWhenTimer = 86400 * 7 - (now - GT.callsignLookups.oqrsLastUpdate);
    GT.oqrsWhenDate = now + oqrsWhenTimer;
    GT.oqrsLoadTimer = nodeTimers.setTimeout(oqrsDownload, oqrsWhenTimer * 1000);
  }

  try
  {
    if (!fs.existsSync(GT.oqrsFile))
    {
      GT.callsignLookups.oqrsLastUpdate = 0;
    }
    else
    {
      GT.oqrsCallsigns = require(GT.oqrsFile);
    }
    if (GT.callsignLookups.oqrsLastUpdate == 0)
    {
      oqrsDownload();
    }
  }
  catch (e)
  {
    GT.callsignLookups.oqrsLastUpdate = 0;
    oqrsDownload();
  }
}

function oqrsSettingsDisplay()
{
  oqrsUseEnable.checked = GT.callsignLookups.oqrsUseEnable;

  if (GT.callsignLookups.oqrsLastUpdate == 0)
  {
    oqrsUpdatedTd.innerHTML = "Never";
  }
  else
  {
    oqrsUpdatedTd.innerHTML = userTimeString(
      GT.callsignLookups.oqrsLastUpdate * 1000
    );
  }

  if (!GT.callsignLookups.oqrsUseEnable)
  {
    if (GT.oqrsLoadTimer != null) nodeTimers.clearTimeout(GT.oqrsLoadTimer);
    GT.oqrsLoadTimer = null;
    GT.oqrsCallsigns = Object();
  }
  oqrsCountTd.innerHTML = Object.keys(GT.oqrsCallsigns).length;
}

function removeOqrsFile()
{
  try
  {
    fs.unlinkSync(GT.oqrsFile);
  }
  catch (err)
  {
    // handle the error
  }
  GT.callsignLookups.oqrsLastUpdate = 0;
  if (GT.oqrsLoadTimer != null)
  {
    nodeTimers.clearTimeout(GT.oqrsLoadTimer);
    GT.oqrsLoadTimer = null;
  }
}

function oqrsValuesChanged()
{
  let wasEnabled = GT.callsignLookups.oqrsUseEnable;
  GT.callsignLookups.oqrsUseEnable = oqrsUseEnable.checked;
  saveCallsignSettings();
  if (GT.callsignLookups.oqrsUseEnable == true)
  {
    if (wasEnabled == false)
    {
      removeOqrsFile();
    }
    oqrsLoadCallsigns();
  }
  else
  {
    removeOqrsFile();
    oqrsSettingsDisplay();
  }

  setAlertVisual();
  goProcessRoster();
  if (GT.rosterInitialized) GT.callRosterWindowHandle.window.resize();
}

function oqrsDownload(fromSettings)
{
  oqrsUpdatedTd.innerHTML = "<b><i>Downloading...</i></b>";
  getBuffer(
    "https://storage.googleapis.com/gt_app/callsigns/clublog.json",
    processoqrsCallsigns,
    null,
    "http",
    80
  );
}

function processoqrsCallsigns(buffer, flag)
{
  GT.oqrsCallsigns = JSON.parse(buffer);

  GT.callsignLookups.oqrsLastUpdate = timeNowSec();
  saveCallsignSettings();

  var now = timeNowSec();
  if (GT.oqrsLoadTimer != null) nodeTimers.clearTimeout(GT.oqrsLoadTimer);

  var oqrsWhenTimer = 86400 * 7 - (now - GT.callsignLookups.oqrsLastUpdate);
  GT.oqrsWhenDate = now + oqrsWhenTimer;
  GT.oqrsLoadTimer = nodeTimers.setTimeout(oqrsDownload, oqrsWhenTimer * 1000);

  fs.writeFileSync(GT.oqrsFile, JSON.stringify(GT.oqrsCallsigns));
  oqrsSettingsDisplay();
}

function eqslLoadCallsigns()
{
  var now = timeNowSec();
  if (now - GT.callsignLookups.eqslLastUpdate > 86400 * 7)
  { GT.callsignLookups.eqslLastUpdate = 0; }
  else
  {
    var eqslWhenTimer = 86400 * 7 - (now - GT.callsignLookups.eqslLastUpdate);
    GT.eqslWhenDate = now + eqslWhenTimer;
    GT.eqslLoadTimer = nodeTimers.setTimeout(eqslDownload, eqslWhenTimer * 1000);
  }

  try
  {
    if (!fs.existsSync(GT.eqslFile))
    {
      GT.callsignLookups.eqslLastUpdate = 0;
    }
    else
    {
      GT.eqslCallsigns = require(GT.eqslFile);
    }
    if (GT.callsignLookups.eqslLastUpdate == 0)
    {
      eqslDownload();
    }
  }
  catch (e)
  {
    console.log(e);
    GT.callsignLookups.eqslLastUpdate = 0;
    eqslDownload();
  }
}

function eqslSettingsDisplay()
{
  eqslUseEnable.checked = GT.callsignLookups.eqslUseEnable;

  if (GT.callsignLookups.eqslLastUpdate == 0)
  {
    eqslUpdatedTd.innerHTML = "Never";
  }
  else
  {
    eqslUpdatedTd.innerHTML = userTimeString(
      GT.callsignLookups.eqslLastUpdate * 1000
    );
  }

  if (!GT.callsignLookups.eqslUseEnable)
  {
    if (GT.eqslLoadTimer != null) nodeTimers.clearTimeout(GT.eqslLoadTimer);
    GT.eqslLoadTimer = null;
    GT.eqslCallsigns = Object();
  }
  eqslCountTd.innerHTML = Object.keys(GT.eqslCallsigns).length;
}

function removeEqslFile()
{
  try
  {
    fs.unlinkSync(GT.eqslFile);
  }
  catch (err)
  {
    // handle the error
  }
  GT.callsignLookups.eqslLastUpdate = 0;
  if (GT.eqslLoadTimer != null)
  {
    nodeTimers.clearTimeout(GT.eqslLoadTimer);
    GT.eqslLoadTimer = null;
  }
}

function eqslValuesChanged()
{
  let wasEnabled = GT.callsignLookups.eqslUseEnable;
  GT.callsignLookups.eqslUseEnable = eqslUseEnable.checked;
  saveCallsignSettings();
  if (GT.callsignLookups.eqslUseEnable == true)
  {
    if (wasEnabled == false)
    {
      removeEqslFile();
    }
    eqslLoadCallsigns();
  }
  else
  {
    removeEqslFile();
    eqslSettingsDisplay();
  }

  setAlertVisual();
  goProcessRoster();
  if (GT.rosterInitialized) GT.callRosterWindowHandle.window.resize();
}

function eqslDownload(fromSettings)
{
  eqslUpdatedTd.innerHTML = "<b><i>Downloading...</i></b>";
  getBuffer(
    "https://www.eqsl.cc/qslcard/DownloadedFiles/AGMemberList.txt",
    processeqslCallsigns,
    null,
    "https",
    443
  );
}

function processeqslCallsigns(buffer, flag)
{
  var result = String(buffer);
  var lines = Array();
  lines = result.split("\n");
  GT.eqslCallsigns = Object();
  for (x in lines)
  {
    GT.eqslCallsigns[lines[x].trim()] = true;
  }
  GT.callsignLookups.eqslLastUpdate = timeNowSec();
  saveCallsignSettings();

  var now = timeNowSec();
  if (GT.eqslLoadTimer != null) nodeTimers.clearTimeout(GT.eqslLoadTimer);

  var eqslWhenTimer = 86400 * 7 - (now - GT.callsignLookups.eqslLastUpdate);
  GT.eqslWhenDate = now + eqslWhenTimer;
  GT.eqslLoadTimer = nodeTimers.setTimeout(eqslDownload, eqslWhenTimer * 1000);

  if (Object.keys(GT.eqslCallsigns).length > 10000)
  { fs.writeFileSync(GT.eqslFile, JSON.stringify(GT.eqslCallsigns)); }

  eqslSettingsDisplay();
}

function ulsLoadCallsigns()
{
  var now = timeNowSec();
  if (now - GT.callsignLookups.ulsLastUpdate > 86400 * 7) ulsDownload();
  else
  {
    if (!fs.existsSync(GT.ulsFile))
    {
      GT.callsignLookups.ulsLastUpdate = 0;
      ulsDownload();
    }
    else
    {
      loadULSFile();
    }
  }
}

function stateCheck()
{
  if (GT.callsignLookups.ulsUseEnable)
  {
    for (let hash in GT.QSOhash)
    {
      let details = GT.QSOhash[hash];
      if (isKnownCallsignUSplus(details.dxcc))
      {
        let lookupCall = false;
        if ((details.cnty == null || details.state == null))
        {
          lookupCall = true;
        }
        else if (details.cnty != null)
        {
          if (!(details.cnty in GT.cntyToCounty))
          {
            if (details.cnty.indexOf(",") == -1)
            {
              if (!(details.state + "," + details.cnty in GT.cntyToCounty))
              {
                lookupCall = true;
              }
            }
            else
            {
              lookupCall = true;
            }
          }
        }
        if (lookupCall == true)
        {
          lookupKnownCallsign(details);
        }
      }
    }
  }

  if (GT.callsignLookups.cacUseEnable)
  {
    for (let hash in GT.QSOhash)
    {
      let details = GT.QSOhash[hash];
      if (details.dxcc == 1 && details.state == null)
      {
        if (details.DEcall in GT.cacCallsigns)
        {
          details.state = "CA-" + GT.cacCallsigns[details.DEcall];
        }
      }
    }
  }
}

function updateCallsignCount()
{
  GT.ulsCallsignsCount = Object.keys(GT.ulsCallsigns).length;
  ulsCountTd.innerHTML = GT.ulsCallsignsCount;
}

function ulsSettingsDisplay()
{
  ulsUseEnable.checked = GT.callsignLookups.ulsUseEnable;

  if (GT.callsignLookups.ulsLastUpdate == 0)
  {
    ulsUpdatedTd.innerHTML = "Never";
  }
  else
  {
    ulsUpdatedTd.innerHTML = userTimeString(GT.callsignLookups.ulsLastUpdate * 1000);
  }

  if (!GT.callsignLookups.ulsUseEnable)
  {
    GT.ulsCallsignsCount = 0;
    ulsCountTd.innerHTML = GT.ulsCallsignsCount;
  }
}

function removeUlsFile()
{
  try
  {
    fs.unlinkSync(GT.ulsFile);
  }
  catch (err)
  {
    // handle the error
  }
  GT.callsignLookups.eqslLastUpdate = 0;
  if (GT.ulsLoadTimer != null)
  {
    nodeTimers.clearTimeout(GT.ulsLoadTimer);
    GT.ulsLoadTimer = null;
  }
}

function ulsValuesChanged()
{
  GT.callsignLookups.ulsUseEnable = ulsUseEnable.checked;
 
  if (GT.callsignLookups.ulsUseEnable == true)
  {
    ulsLoadCallsigns();
  }
  else
  {
    removeUlsFile();
    resetULSDatabase();
    ulsSettingsDisplay();
    ulsCountTd.innerHTML = 0;
  }
  saveCallsignSettings();

  goProcessRoster();
  if (GT.rosterInitialized) GT.callRosterWindowHandle.window.resize();
}

function ulsDownload()
{
  ulsUpdatedTd.innerHTML = "<b><i>Downloading...</i></b>";
  ulsCountTd.innerHTML = 0;
  getBuffer(
    "https://storage.googleapis.com/gt_app/callsigns/callsigns.txt",
    ulsDownloadHandler,
    null,
    "http",
    80
  );
}

function resetULSDatabase()
{
  GT.callsignLookups.ulsLastUpdate = 0;
  GT.ulsCallsignsCount = 0;
  GT.ulsCallsigns = {};

  saveCallsignSettings();
}

function ulsDownloadHandler(data)
{
  fs.writeFileSync(GT.ulsFile, data);

  GT.callsignLookups.ulsLastUpdate = timeNowSec();
  saveCallsignSettings();

  loadULSFile();
}

function loadULSFile()
{
  ulsUpdatedTd.innerHTML = "<b><i>Processing...</i></b>";
  fs.readFile(GT.ulsFile, "utf-8", processulsCallsigns);
}

function processulsCallsigns(error, buffer)
{
  if (error)
  {
    console.log("File Read Error: " + error);
  }

  if (buffer && buffer.length > 0)
  {
    GT.ulsCallsigns = {};

    var startPos = 0;
    var endPos = buffer.length;
    while (startPos != endPos)
    {
      let eol = buffer.substring(startPos).indexOf("\n");
      if (eol > -1)
      {
        let row = buffer.substring(startPos, startPos + eol);
        GT.ulsCallsigns[row.substring(7)] = row.substring(0, 7);
        startPos += eol + 1; // skip \n
      }
      else
      {
        break;
      }
    }
  }

  updateCallsignCount();
  ulsSettingsDisplay();

  if (GT.ulsLoadTimer != null)
  {
    nodeTimers.clearTimeout(GT.ulsLoadTimer);
    GT.ulsLoadTimer = null;
  }

  var whenTimer = (86400 * 7) - (timeNowSec() - GT.callsignLookups.ulsLastUpdate);
  GT.ulsLoadTimer = nodeTimers.setTimeout(ulsDownload, whenTimer * 1000);
}

function lookupKnownCallsign(object)
{
  if (object.DEcall in GT.ulsCallsigns)
  {
    if (object.state == null)
    {
      object.state = "US-" + GT.ulsCallsigns[object.DEcall].substring(5);
    }
    object.zipcode = GT.ulsCallsigns[object.DEcall].substring(0, 5);
    
    if (object.cnty == null && object.zipcode in GT.zipToCounty)
    {
      var counties = GT.zipToCounty[object.zipcode];
      if (counties.length > 1)
      {
        object.qual = false;
      }
      else
      {
        object.qual = true;
      }
      object.cnty = counties[0];
    }
  }
}

function downloadCtyDat()
{
  ctyDatStatus.innerHTML = "<b><i>Downloading...</i></b>";
  getBuffer(
    "https://storage.googleapis.com/gt_app/ctydat.json?cb=" + Date.now(),
    processCtyDat,
    null,
    "https",
    443
  );
}

function processCtyDat(buffer)
{
  var data = String(buffer);
  ctyDatStatus.innerHTML = "Update: " + data.length + " bytes read";
  try
  {
    var ctydata = JSON.parse(data);
    var file = "./data/mh-root-prefixed.json";
    if (fs.existsSync(file))
    {
      var dxccInfo = JSON.parse(fs.readFileSync(file, "UTF-8"));
      for (const key in dxccInfo)
      {
        dxccInfo[key].ituzone = null;
        dxccInfo[key].cqzone = null;
        dxccInfo[key].prefixITU = {};
        dxccInfo[key].prefixCQ = {};
        dxccInfo[key].directITU = {};
        dxccInfo[key].directCQ = {};

        if (key in ctydata)
        {
          dxccInfo[key].cqzone = padNumber(Number(ctydata[key].cqzone), 2);
          dxccInfo[key].ituzone = padNumber(Number(ctydata[key].ituzone), 2);

          // Skip Guantanamo Bay, hand crafted with love
          if (key != "105")
          {
            dxccInfo[key].prefix = [];
            dxccInfo[key].direct = [];

            var arr = ctydata[key].prefix.substr(0, ctydata[key].prefix.length - 1).split(" ");
            for (const x in arr)
            {
              var test = arr[x];
              var direct = false;
              var cq = null;
              var itu = null;
              
              if (test.charAt(0) == "=")
              {
                direct = true;
                test = test.substr(1);
              }
              var cqTest = test.match(/\((.*)\)/);
              if (cqTest)
              {
                cq = padNumber(Number(cqTest[1]), 2);
              }
              var ituTest = test.match(/\[(.*)\]/);
              if (ituTest)
              {
                itu = padNumber(Number(ituTest[1]), 2);
              }
    
              var i = test.indexOf("(");
              if (i > -1)
              {
                test = test.substr(0, i);
              }
              i = test.indexOf("[");
              if (i > -1)
              {
                test = test.substr(0, i);
              }
              i = test.indexOf("<");
              if (i > -1)
              {
                test = test.substr(0, i);
              }
              i = test.indexOf("{");
              if (i > -1)
              {
                test = test.substr(0, i);
              }
              i = test.indexOf("~");
              if (i > -1)
              {
                test = test.substr(0, i);
              }
              
              if (direct)
              {
                dxccInfo[key].direct.push(test);
                if (cq)
                {
                  dxccInfo[key].directCQ[test] = cq;
                }
                if (itu)
                {
                  dxccInfo[key].directITU[test] = itu;
                }
              }
              else
              {
                dxccInfo[key].prefix.push(test);
                if (cq)
                {
                  dxccInfo[key].prefixCQ[test] = cq;
                }
                if (itu)
                {
                  dxccInfo[key].prefixITU[test] = itu;
                }
              }
            }
            dxccInfo[key].prefix = uniqueArrayFromArray(dxccInfo[key].prefix);
            dxccInfo[key].prefix.sort();
            dxccInfo[key].direct = uniqueArrayFromArray(dxccInfo[key].direct);
            dxccInfo[key].direct.sort();
          }
        }
      }
      fs.writeFileSync(file, JSON.stringify(dxccInfo, null, 2));
      ctyDatFinal.innerHTML = file + " updated!";
    }
  }
  catch (e)
  {
    console.log(e);
  }
}
