export const cast = function (
  typeP,
  valP,
  report_conversion_error_callback,
  report_conversion_warn_callback
) {
  if (typeof _ === "undefined") {
    console.error("error: _ library not defined in cast");
    return valP;
  }

  var ret = valP;

  const report_conversion_error = function (res) {
    if (report_conversion_error_callback) {
      report_conversion_error_callback(res, typeP, valP);
    }
  };
  const report_conversion_warn = function (res) {
    if (report_conversion_warn_callback) {
      report_conversion_warn_callback(res, typeP, valP);
    }
  };
  switch (typeP) {
    case "boolean":
    case "bool":
      const true_bool_opt = ["Y", 1, true, "TRUE", "ON", "YES", "1"];
      const false_bool_opt = ["N", 0, false, "FALSE", "OFF", "NO", "0"];
      if (true_bool_opt.includes(_.toUpper(valP))) {
        ret = true;
        break;
      }

      if (false_bool_opt.includes(_.toUpper(valP)) || !valP) {
        ret = false;
      }

      break;

    case "number":
      if (
        typeof valP === "undefined" ||
        typeof valP === "NaN" ||
        valP === null
      ) {
        ret = 0;
      } else {
        if (typeof valP !== "number") {
          try {
            if (typeof valP === "boolean") {
              ret = valP ? 1 : 0;
            } else {
              ret = _.toNumber(valP);
            }
            // normal behavior studio always store values as string
            // report_conversion_warn();
          } catch (e) {
            ret = 0;
            report_conversion_error(0);
          }
        }
      }
      break;
    case "string":
      if (
        typeof valP === "undefined" ||
        typeof valP === "NaN" ||
        valP === null
      ) {
        ret = "";
      } else {
        if (typeof valP !== "string") {
          try {
            ret = _.toString(valP);
            report_conversion_warn();
          } catch (e) {
            ret = "";
            report_conversion_error("blanc");
          }
        }
      }
      break;
    case "object":
      if (
        typeof valP === "undefined" ||
        typeof valP === "NaN" ||
        valP === null
      ) {
        ret = {};
      } else {
        if (typeof valP !== "object") {
          try {
            if (valP) {
              ret = JSON5.parse(valP);
            } else {
              ret = {};
            }
          } catch (e) {
            try {
              ret = JSON5.parse(valP);
            } catch (error) {
              ret = {};
              report_conversion_error("{}");
            }
          }
        }
      }
      break;
    case "array":
      if (
        typeof valP === "undefined" ||
        typeof valP === "NaN" ||
        valP === null ||
        valP === ""
      ) {
        ret = [];
      } else {
        if (!Array.isArray(valP)) {
          try {
            ret = _.toArray(eval(valP));
          } catch (e) {
            ret = [];
            report_conversion_error("[]");
          }
        }
      }
      break;
    default:
      if (
        typeof valP === "undefined" ||
        typeof valP === "NaN" ||
        valP === null
      ) {
        ret = "";
      } else {
        if (typeof valP !== "string") {
          try {
            ret = valP.toString();
            report_conversion_warn();
          } catch (e) {
            ret = "";
            report_conversion_error("blanc");
          }
        }
      }
      break;
  }
  return ret;
};
