{"size": 2910, "ext": "js", "max_stars_repo_path": "js/src/formNewObj.js", "max_stars_repo_name": "IvanOmelchenkoIP/Course-Work-OP", "max_stars_repo_stars_event_min_datetime": null, "max_stars_repo_stars_event_max_datetime": null, "max_issues_repo_path": "js/src/formNewObj.js", "max_issues_repo_name": "IvanOmelchenkoIP/Course-Work-OP", "max_issues_repo_issues_event_min_datetime": "2021-05-04T18:02:25.000Z", "max_issues_repo_issues_event_max_datetime": "2021-06-03T19:35:36.000Z", "max_forks_repo_path": "js/src/formNewObj.js", "max_forks_repo_name": "IvanOmelchenkoIP/Course-Work-OP", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": null, "max_issues_count": 4, "max_forks_count": null, "avg_line_length": 26.2162162162, "max_line_length": 86, "alphanum_fraction": 0.5924398625}
"use strict";

const formNewObj = (struct, fns) => {
  if (!canStartSelect(struct, fns)) {
    console.log('Cannot do selection correctly with given data!');
    return null;
  }

  let iter = 0;
  console.log(
    `Starting selection of a new object (${fns.length} iterations):`
  );
  let newObj = null;
  for (const fn of fns) {
    newObj = newObj ? selectByFns(newObj, ...fn) : selectByFns(struct, ...fn);

    console.log("\n");
    console.log(`New object after iteration #${iter}:`);
    console.dir(newObj);
    iter++;
  }
  console.log('Selection has been finished.');
  return newObj;
};

const canStartSelect = (struct, fnArr) => {
  if (!struct || typeof struct !== "object") return false;
  if (!fnArr || !Array.isArray(fnArr)) return false;
  return true;
};

const selectByFns = (origin, fn, pos) => {
  if (!isSelectable(origin, fn, pos)) {
    console.log(
      `Can not start selecting data on current stage!
Processing to the next stage with originally given object...`
    );
    return origin;
  }

  const selection = new Object(null);
  const keys = Object.keys(origin);
  if (!keys) return null;
  for (const key of keys) {
    if (pos > 0) {
      selection[key] =
        origin[key] &&
        typeof origin[key] === "object" &&
        Object.keys(origin[key]).length
          ? selectByFns(origin[key], fn, pos - 1)
          : null;

      !selection[key] || !Object.keys(selection[key]).length
        ? delete selection[key]
        : console.log(
            `Key ${key} with value ${selection[key]} has been added to the new object`
          );
    } else {
      if (isAdded(origin, key, ...fn)) selection[key] = origin[key];
    }
  }
  return selection;
};

const isSelectable = (origin, fn, pos) => {
  if (!origin || typeof origin !== "object") return false;
  if (!fn || !Array.isArray(fn)) return false;
  if (typeof pos !== "number" || pos < 0) return false;
  return true;
};

const isAdded = (obj, key, fnKey, fnVal, argsKey, argsVal) => {
  if (!fnVal && !fnKey) {
    console.log("No parameters to verify your keys for selection by!");
    return false;
  }

  let flagKey = true;
  let flagVal = true;
  try {
    if (fnKey) {
      checkCorrect(key, fnKey, argsKey) ? (flagKey = true) : (flagKey = false);
    }
    if (fnVal) {
      checkCorrect(obj[key], fnVal, argsVal)
        ? (flagVal = true)
        : (flagVal = false);
    }
  } catch (err) {
    console.log("There was an error launching verification of your data!");
    console.error(err);
    return false;
  }
  return flagKey && flagVal ? true : false;
};

const checkCorrect = (obj, fn, args) => {
  try {
    if (fn.length > 1) {
      return fn(obj, ...args) ? true : false;
    } else {
      return fn(obj) ? true : false;
    }
  } catch (err) {
    console.log("There was an error verifying your data!");
    console.error(err);
    return false;
  }
};

module.exports = formNewObj;