// Copyright 2023 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

type ObjectType = {
  [index: number | string]: any;
};

function hasOwnProperty(obj: ObjectType, prop: number | string) {
  if (obj == null) {
    return false;
  }
  //to handle objects with null prototypes (too edge case?)
  return Object.prototype.hasOwnProperty.call(obj, prop);
}
function hasShallowProperty(obj: ObjectType, prop: number | string) {
  return (
    (typeof prop === 'number' && Array.isArray(obj)) ||
    hasOwnProperty(obj, prop)
  );
}

function getShallowProperty(obj: ObjectType, prop: number | string) {
  if (hasShallowProperty(obj, prop)) {
    return obj[prop];
  }
}
function getKey(key: string) {
  const intKey = parseInt(key);
  if (intKey.toString() === key) {
    return intKey;
  }
  return key;
}

export function setPathOnObject(
  obj: ObjectType,
  path: number | string | Array<number | string>,
  value: any,
  doNotReplace: boolean = false,
) {
  if (typeof path === 'number') {
    path = [path];
  }
  if (!path || path.length === 0) {
    return obj;
  }
  if (typeof path === 'string') {
    return setPathOnObject(
      obj,
      path.split('.').map(getKey),
      value,
      doNotReplace,
    );
  }
  const currentPath = path[0];
  const currentValue = getShallowProperty(obj, currentPath);
  if (path.length === 1) {
    if (currentValue === void 0 || !doNotReplace) {
      obj[currentPath] = value;
    }
    return currentValue;
  }

  if (currentValue === void 0) {
    //check if we assume an array
    if (typeof path[1] === 'number') {
      obj[currentPath] = [];
    } else {
      obj[currentPath] = {};
    }
  }

  return setPathOnObject(obj[currentPath], path.slice(1), value, doNotReplace);
}
