// In this document we will define all the different filters
// that the user can apply to its documents.

/**
 * Keep only the column that are in the array
 * @param {string[]} name
 */
export function columnMatchFilter(jsonObj: object[], columns: string[]) {
  return jsonObj.map((obj: any) => {
    return columns.reduce((acc: any, cur) => {
      acc[cur] = obj[cur];
      return acc;
    }, {});
  });
}


/**
 * Filter the document based on the condition. Only the rows that match the condition will be kept.
 * @param {object[]} jsonObj
 * @param {string} condition
 * @returns {object[]}
*/
export function whereFilter(jsonObj: object[], condition: string) {
  const { key, operator, value } = parseCondition(condition);
  const _value = setValueType(value);

  return jsonObj.filter((obj: any) => {
    const _objValue = setValueType(obj[key]);
    return compare(_objValue, operator, _value);
  });
}


function parseCondition(condition: string) {
  const decomposedCondition = condition.split(' ');

  // If the user didn't specify the operator, we return an error
  if (decomposedCondition.length !== 3) {
    throw new Error('Invalid condition');
  }

  const [key, operator, value] = decomposedCondition;

  // Check if the operator is valid
  if (!['=', '==', '===', '>', '<', '>=', '<=', '!='].includes(operator)) {
    throw new Error('Invalid operator');
  }

  return { key, operator, value };
}


function setValueType(value: string) {
  if (Number(value)) {
    return Number(value);
  }
  return value;
}


function compare(a: any, operator: string, b: any) {
  switch (operator) {
    case '=':
    case '==':
    case '===':
      return a === b;
    case '>':
      return a > b;
    case '<':
      return a < b;
    case '>=':
      return a >= b;
    case '<=':
      return a <= b;
    case '!=':
      return a !== b;
    default:
      return false;
  }
}