let PreParedReportDataObject = null;

//////////////////////////////////
// Pre render function
//
async function ayPreRender(ayAllData) {
  if (typeof ayPrepareData === "function") {
    PreParedReportDataObject = await ayPrepareData(ayAllData);
  } else {
    PreParedReportDataObject = ayAllData;
  }
  return true;
}

///////////////////////////////////////
// Set our stock handlebars helpers
//
function ayRegisterHelpers() {
  Handlebars.registerHelper("ayCaps", function (ayValue) {
    return ayValue.toUpperCase();
  });

  Handlebars.registerHelper("ayDateTime", function (ayValue) {
    return utcDateToShortDateAndTimeLocalized(ayValue);
  });

  Handlebars.registerHelper("ayDate", function (ayValue) {
    return utcDateToShortDateLocalized(ayValue);
  });

  Handlebars.registerHelper("ayTime", function (ayValue) {
    return utcDateToShortTimeLocalized(ayValue);
  });

  Handlebars.registerHelper("ayDecimal", function (ayValue) {
    return decimalLocalized(ayValue);
  });

  Handlebars.registerHelper("ayCurrency", function (ayValue) {
    return currencyLocalized(ayValue);
  });

  Handlebars.registerHelper("ayWiki", function (ayValue) {
    if (ayValue == null) {
      return "";
    }

    //replace attachment urls with tokenized local urls
    let src = ayValue.replace(/\[ATTACH:(.*)\]/g, function (match, p1) {
      return attachmentDownloadUrl(p1);
    });
    return new Handlebars.SafeString(
      DOMPurify.sanitize(marked(src, { breaks: true }))
    );
  });

  Handlebars.registerHelper("ayJSON", function (obj) {
    return JSON.stringify(obj, null, 3);
  });

  Handlebars.registerHelper("ayLink", function (text, url) {
    var url = Handlebars.escapeExpression(url),
      text = Handlebars.escapeExpression(text);

    return new Handlebars.SafeString("<a href='" + url + "'>" + text + "</a>");
  });

  Handlebars.registerHelper("ayLogo", function (size) {
    if (this.ayServerMetaData) {
      switch (size) {
        case "small":
          if (!this.ayServerMetaData.HasSmallLogo) {
            return "";
          }
          break;
        case "medium":
          if (!this.ayServerMetaData.HasMediumLogo) {
            return "";
          }
          break;
        case "large":
          if (!this.ayServerMetaData.HasLargeLogo) {
            return "";
          }
          break;
      }
    }
    var url = `${Handlebars.escapeExpression(
      this.ayServerMetaData.ayApiUrl
    )}logo/${size}`;
    return new Handlebars.SafeString("<img src='" + url + "'/>");
  });

  Handlebars.registerHelper("ayT", function (translationKey) {
    if (ayTranslationKeyCache[translationKey] == undefined) {
      throw `ayT reporting helper error: the key "${translationKey}" is not present in the translation cache, did you forget to include it in your call to "await ayGetTranslations([KeyList]);" in ayPrepareData()\nTranslationKeyCache contains: ${JSON.stringify(
        ayTranslationKeyCache,
        null,
        3
      )}?`;
      // return translationKey;
    }
    return ayTranslationKeyCache[translationKey];
  });

  ///////////////////////////////////////////
  // BarCode helper using
  //  https://github.com/metafloor/bwip-js#browser-usage
  //
  Handlebars.registerHelper("ayBC", function (text, options) {
    let canvas = document.getElementById("aybarcode");
    if (canvas == null) {
      canvas = document.createElement("canvas");
      canvas.id = "aybarcode";
    }
    let opt = JSON.parse(options);
    if (text == null) {
      text = "";
    } else {
      text = text.toString();
    }
    opt.text = text;
    opt.textxalign = opt.textxalign || "center";

    bwipjs.toCanvas(canvas, opt);
    var url = canvas.toDataURL("image/png");
    return new Handlebars.SafeString("<img src='" + url + "'/>");
  });
} //eof

///////////////////////////////////////////
// Turn a utc date into a displayable
// short date and time
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString
//
function utcDateToShortDateAndTimeLocalized(ayValue) {
  if (!ayValue) {
    return "";
  }

  //parse the date which is identified as utc ("2020-02-06T18:18:49.148011Z")
  let parsedDate = new Date(ayValue);

  //is it a valid date?
  if (!(parsedDate instanceof Date && !isNaN(parsedDate))) {
    return "not valid";
  }

  return parsedDate.toLocaleString(
    AYMETA.ayClientMetaData.LanguageName || "en-US",
    {
      timeZone: AYMETA.ayClientMetaData.TimeZoneName || "America/Winnipeg",
      dateStyle: "short",
      timeStyle: "short",
      hour12: AYMETA.ayClientMetaData.Hour12
    }
  );
}
///////////////////////////////////////////
// Turn a utc date into a displayable
// short date
//
function utcDateToShortDateLocalized(ayValue) {
  if (!ayValue) {
    return "";
  }

  //parse the date which is identified as utc ("2020-02-06T18:18:49.148011Z")
  let parsedDate = new Date(ayValue);

  //is it a valid date?
  if (!(parsedDate instanceof Date && !isNaN(parsedDate))) {
    return "not valid";
  }

  return parsedDate.toLocaleDateString(
    AYMETA.ayClientMetaData.LanguageName || "en-US",
    {
      timeZone: AYMETA.ayClientMetaData.TimeZoneName || "America/Winnipeg",
      dateStyle: "short"
    }
  );
}
///////////////////////////////////////////
// Turn a utc date into a displayable
// short time
//
function utcDateToShortTimeLocalized(ayValue) {
  if (!ayValue) {
    return "";
  }

  //parse the date which is identified as utc ("2020-02-06T18:18:49.148011Z")
  let parsedDate = new Date(ayValue);

  //is it a valid date?
  if (!(parsedDate instanceof Date && !isNaN(parsedDate))) {
    return "not valid";
  }

  return parsedDate.toLocaleTimeString(
    AYMETA.ayClientMetaData.LanguageName || "en-US",
    {
      timeZone: AYMETA.ayClientMetaData.TimeZoneName || "America/Winnipeg",
      timeStyle: "short",
      hour12: AYMETA.ayClientMetaData.Hour12
    }
  );
}

///////////////////////////////////////////
// CURRENCY LOCALIZATION
//
//
function currencyLocalized(ayValue) {
  if (!ayValue) {
    return "";
  }
  return new Intl.NumberFormat(
    AYMETA.ayClientMetaData.LanguageName || "en-US",
    {
      style: "currency",
      currency: AYMETA.ayClientMetaData.CurrencyName || "USD"
    }
  ).format(ayValue);
}

///////////////////////////////////////////
// DECIMAL LOCALIZATION
//
//
function decimalLocalized(ayValue) {
  if (!ayValue) {
    return "";
  }
  return new Intl.NumberFormat(
    AYMETA.ayClientMetaData.LanguageName || "en-US"
  ).format(ayValue);
}

//////////////////////////////////
// cache to hold translations keys
//
var ayTranslationKeyCache = {};

///////////////////////////////////
//  GET TRANSLATIONS FROM API SERVER
//
async function ayGetTranslations(keys) {
  if (!keys || keys.length == 0) {
    return;
  }
  try {
    let transData = await ayPostToAPI("translation/subset", keys);
    transData.data.forEach(function storeFetchedTranslationItemsInCache(item) {
      ayTranslationKeyCache[item.key] = item.value;
    });
  } catch (error) {
    //fundamental error, can't proceed with this call
    // handleError("GET", error, route);
    //todo: deal with this properly
    throw error;
  }
}

///////////////////////////////////
//  GET DATA FROM API SERVER
//
async function ayGetFromAPI(route, token) {
  token = token || AYMETA.ayClientMetaData.Authorization;
  if (route && !route.startsWith("http")) {
    route = AYMETA.ayServerMetaData.ayApiUrl + route;
  }
  try {
    let r = await fetch(route, {
      method: "get",
      mode: "cors",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
        Authorization: token
      }
    });
    return await r.json();
  } catch (error) {
    //fundamental error, can't proceed with this call
    // handleError("GET", error, route);
    //todo: deal with this properly
    throw error;
  }
}

///////////////////////////////////
//  POST  DATA TO API SERVER
//
async function ayPostToAPI(route, data, token) {
  token = token || AYMETA.ayClientMetaData.Authorization;
  if (route && !route.startsWith("http")) {
    route = AYMETA.ayServerMetaData.ayApiUrl + route;
  }
  try {
    fetchOptions = {
      method: "post",
      mode: "cors",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
        Authorization: token
      },
      body: JSON.stringify(data)
    };
    let r = await fetch(route, fetchOptions);
    return await r.json();
  } catch (error) {
    //todo: better handle this
    throw error;
  }
}

//Utils
function ayPad(n, width, z) {
  z = z || "0";
  n = n + "";
  return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
}

/////////////////////////////
// attachment download URL
//
function attachmentDownloadUrl(fileId, ctype) {
  //http://localhost:7575/api/v8/attachment/download/100?t=sssss
  //Ctype is optional and is the MIME content type, used to detect image urls at client for drag and drop ops
  //in wiki but ignored by server

  let url =
    "attachment/download/" +
    fileId +
    "?t=" +
    AYMETA.ayClientMetaData.DownloadToken;

  if (ctype && ctype.includes("image")) {
    url += "&i=1";
  }

  return AYMETA.ayServerMetaData.ayApiUrl + url;
}
