/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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
 *
 *   http://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.
 */
import { nanoid } from 'nanoid';
import { compose } from 'redux';
import persistState, { StorageAdapter } from 'redux-localstorage';
import { isEqual, omitBy, omit, isEqualWith } from 'lodash';
import { ensureIsArray } from '@superset-ui/core';

export function addToObject(
  state: Record<string, any>,
  arrKey: string,
  obj: Record<string, any>,
) {
  const newObject = { ...state[arrKey] };
  const copiedObject = { ...obj };

  if (!copiedObject.id) {
    copiedObject.id = nanoid();
  }
  newObject[copiedObject.id] = copiedObject;
  return { ...state, [arrKey]: newObject };
}

export function alterInObject(
  state: Record<string, any>,
  arrKey: string,
  obj: Record<string, any>,
  alterations: Record<string, any>,
) {
  const newObject = { ...state[arrKey] };
  newObject[obj.id] = { ...newObject[obj.id], ...alterations };
  return { ...state, [arrKey]: newObject };
}

export function alterInArr(
  state: Record<string, any>,
  arrKey: string,
  obj: Record<string, any>,
  alterations: Record<string, any>,
  idKey = 'id',
) {
  // Finds an item in an array in the state and replaces it with a
  // new object with an altered property
  const newArr: unknown[] = [];
  state[arrKey].forEach((arrItem: Record<string, any>) => {
    if (obj[idKey] === arrItem[idKey]) {
      newArr.push({ ...arrItem, ...alterations });
    } else {
      newArr.push(arrItem);
    }
  });
  return { ...state, [arrKey]: newArr };
}

export function removeFromArr(
  state: Record<string, any>,
  arrKey: string,
  obj: Record<string, any>,
  idKey = 'id',
) {
  const newArr: unknown[] = [];
  state[arrKey].forEach((arrItem: Record<string, any>) => {
    if (!(obj[idKey] === arrItem[idKey])) {
      newArr.push(arrItem);
    }
  });
  return { ...state, [arrKey]: newArr };
}

export function getFromArr(
  arr: Record<string, any>[],
  id: string,
  idKey = 'id',
) {
  let obj;
  arr.forEach(o => {
    if (o[idKey] === id) {
      obj = o;
    }
  });
  return obj;
}

export function addToArr(
  state: Record<string, any>,
  arrKey: string,
  obj: Record<string, any>,
  prepend = false,
) {
  const newObj = { ...obj };
  if (!newObj.id) {
    newObj.id = nanoid();
  }
  const newState: Record<string, any[]> = {};
  if (prepend) {
    newState[arrKey] = [newObj, ...state[arrKey]];
  } else {
    newState[arrKey] = [...state[arrKey], newObj];
  }
  return { ...state, ...newState };
}

export function extendArr(
  state: Record<string, any>,
  arrKey: string,
  arr: Record<string, any>[],
  prepend = false,
) {
  const newArr = [...arr];
  newArr.forEach(el => {
    if (!el.id) {
      /* eslint-disable no-param-reassign */
      el.id = nanoid();
    }
  });
  const newState: Record<string, any[]> = {};
  if (prepend) {
    newState[arrKey] = [...newArr, ...state[arrKey]];
  } else {
    newState[arrKey] = [...state[arrKey], ...newArr];
  }
  return { ...state, ...newState };
}

export function initEnhancer(
  persist = true,
  persistConfig: { paths?: StorageAdapter<unknown>; config?: string } = {},
  disableDebugger = false,
) {
  const { paths, config } = persistConfig;
  const composeEnhancers =
    process.env.WEBPACK_MODE === 'development' && disableDebugger !== true
      ? /* eslint-disable-next-line no-underscore-dangle, dot-notation */
        window['__REDUX_DEVTOOLS_EXTENSION_COMPOSE__' as keyof typeof window]
        ? /* eslint-disable-next-line no-underscore-dangle, dot-notation */
          window['__REDUX_DEVTOOLS_EXTENSION_COMPOSE__' as keyof typeof window](
            {
              trace: true,
            },
          )
        : compose
      : compose;

  return persist
    ? composeEnhancers(persistState(paths, config))
    : composeEnhancers();
}

export function areArraysShallowEqual(arr1: unknown[], arr2: unknown[]) {
  // returns whether 2 arrays are shallow equal
  // used in shouldComponentUpdate when denormalizing arrays
  // where the array object is different every time, but the content might
  // be the same
  if (!arr1 || !arr2) {
    return false;
  }
  if (arr1.length !== arr2.length) {
    return false;
  }
  const { length } = arr1;
  for (let i = 0; i < length; i += 1) {
    if (arr1[i] !== arr2[i]) {
      return false;
    }
  }
  return true;
}

export function areObjectsEqual(
  obj1: any,
  obj2: any,
  opts: {
    ignoreUndefined?: boolean;
    ignoreNull?: boolean;
    ignoreFields?: string[];
  } = { ignoreUndefined: false, ignoreNull: false, ignoreFields: [] },
) {
  let comp1 = obj1;
  let comp2 = obj2;
  if (opts.ignoreUndefined) {
    comp1 = omitBy(comp1, i => i === undefined);
    comp2 = omitBy(comp2, i => i === undefined);
  }
  if (opts.ignoreNull) {
    comp1 = omitBy(comp1, i => i === null);
    comp2 = omitBy(comp2, i => i === null);
  }
  if (opts.ignoreFields?.length) {
    const ignoreFields = ensureIsArray(opts.ignoreFields);
    return isEqualWith(comp1, comp2, (val1, val2) =>
      isEqual(
        ensureIsArray(val1).map(value => omit(value, ignoreFields)),
        ensureIsArray(val2).map(value => omit(value, ignoreFields)),
      ),
    );
  }
  return isEqual(comp1, comp2);
}
