export default class JsonHelper {
  public static findDataByKey(
    source: any,
    key: string,
    value: any,
    childkey = "children",
    isExactMatch = true
  ): any {
    let result = null;
    this.filter(
      source,
      key,
      value,
      childkey,
      function (v: any) {
        result = v;
      },
      isExactMatch
    );
    return result;
  }
  public static appendData(
    source: any,
    data: any,
    parentKey: string,
    parentValue: string,
    childkey = "children"
  ) {
    this.filter(source, parentKey, parentValue, childkey, function (v: any) {
      if (v[childkey]) {
        v[childkey].push(data);
      } else {
        v[childkey] = [data];
      }
    });
    return source;
  }
  public static removeDataByKey(
    source: any,
    key: string,
    value: string,
    childkey = "children"
  ) {
    let data: any;
    this.filter(source, key, value, childkey, function (v: any) {
      data = v;
    });
    this.removeDataByObject(source, data, key, value, childkey);
  }
  public static removeDataByObject(
    source: any,
    object: any,
    key: string,
    value: string,
    childkey = "children"
  ) {
    this.parentFilter(source, key, value, childkey, function (v: any) {
      v[childkey].remove(object);
    });
  }
  public static findDataParentByKey(
    source: any,
    key: string,
    value: any,
    childkey = "children"
  ): any {
    let result = null;
    this.parentFilter(source, key, value, childkey, function (v: any) {
      result = v;
    });
    return result;
  }
  private static parentFilter(
    source: any,
    key: string,
    value: any,
    childkey = "children",
    callback: Function,
    index = -1
  ): boolean {
    let current: any;
    let childSplit = childkey.split("|");
    for (let i = 0; i < childSplit.length; i++) {
      if (
        source[childSplit[i]] !== undefined &&
        source[childSplit[i]] !== null
      ) {
        current = index > -1 ? source[childSplit[i]][index] : source;
        break;
      }
    }
    let keySplit = key.split(".");
    let _current = current;
    for (let i = 0; i < keySplit.length; i++) {
      if (
        _current[keySplit[i]] !== undefined &&
        _current[keySplit[i]] !== null
      ) {
        _current = _current[keySplit[i]];
        if (i < keySplit.length - 1) {
          current = current[keySplit[i]];
        }
      }
      
    }
    let filter: any = _current as any;
    if (filter == value) {
      callback(source, index);
      return true;
    }
    let status = false;
    let childSource: any;
    for (let i = 0; i < childSplit.length; i++) {
      if (
        current[childSplit[i]] &&
        current[childSplit[i]].length !== undefined &&
        current[childSplit[i]].length !== null
      ) {
        childSource = current[childSplit[i]];
        break;
      }
    }
    if (childSource && childSource.length && childSource.length > 0) {
      for (let i = 0; i < childSource.length; i++) {
        status = this.parentFilter(current, key, value, childkey, callback, i);
        if (status) {
          return status;
        }
      }
    }

    return status;
  }
  private static filter(
    source: any,
    key: string,
    value: any,
    childkey = "children",
    callback: Function,
    isExactMatch = true,
    index = -1
  ): boolean {
    let current = source;
    let childSplit = childkey.split("|");
    for (let i = 0; i < childSplit.length; i++) {
      if (
        source[childSplit[i]] !== undefined &&
        source[childSplit[i]] !== null
      ) {
        current = index > -1 ? source[childSplit[i]][index] : source;

        break;
      }
    }
    let keySplit = key.split(".");
    let _current = current;
    for (let i = 0; i < keySplit.length; i++) {
      if (
        _current[keySplit[i]] !== undefined &&
        _current[keySplit[i]] !== null
      ) {
        _current = _current[keySplit[i]];
        if (i < keySplit.length - 1) {
          current = current[keySplit[i]];
        }
      }
      
    }
    let filter: any = _current as any;
    if (
      (isExactMatch && filter == value) ||
      (!isExactMatch && value.substr(0, value.length) == value)
    ) {
      callback(current, index, source);
      return true;
    }
    let status = false;
    let childSource: any;
    for (let i = 0; i < childSplit.length; i++) {
      if (
        current[childSplit[i]] &&
        current[childSplit[i]].length !== undefined &&
        current[childSplit[i]].length !== null
      ) {
        childSource = current[childSplit[i]];
        break;
      }
    }
    if (childSource && childSource.length && childSource.length > 0) {
      for (let i = 0; i < childSource.length; i++) {
        status = this.filter(
          current,
          key,
          value,
          childkey,
          callback,
          isExactMatch,
          i
        );
        if (status) {
          return status;
        }
      }
    }
    return status;
  }
}
