function isObject(value) {
  return value !== null && (typeof value === 'object' || typeof value === 'function');
}

const partternField = /^\{{2}(.*)\}{2}$/;
function replaceField(globalData, field) {
  if (field && partternField.test(field)) { return globalData[field.replace(partternField, '$1')]; }
  return field;
}

/**
 * 根据数据源解析模板变量
 * @param {*} globalData
 * @param {*} source
 * @param {*} hash
 * @returns
 */
export async function parseDeep(globalData, source, hash = new WeakMap()) {
  if (!isObject(source)) return replaceField(globalData, source);
  if (hash.has(source)) return hash.get(source);

  var target = Array.isArray(source) ? [] : {};
  hash.set(source, target);

  for (var key in source) {
    if (Object.prototype.hasOwnProperty.call(source, key)) {
      if (isObject(source[key])) {
        target[key] = await parseDeep(globalData, source[key], hash);
      } else {
        target[key] = replaceField(globalData, source[key]);
      }
    }
  }
  return target;
}

/**
 * 递归遍历字段
 * @param {*} obj
 * @param {*} targetPath
 * @returns
 */
export function findDeepValue(obj, targetPath) {
  const keys = targetPath.split('.');
  let current = obj;
  for (const key of keys) {
    if (current.hasOwnProperty(key)) {
      current = current[key];
    } else {
      return undefined;
    }
  }
  return current;
}
