import { collect } from 'collect.js';
import * as Yup from 'yup';
import { IObject } from '../interfaces';

/**
 * Retorna todos os itens do objeto, exceto aqueles com as chaves especificadas
 *
 * @param object
 * @param excepts
 */
export function objectExcept(object: IObject, excepts: any[]): any {
   return collect(object).sortKeys().except(excepts).all();
}
/**
 * numberFormat
 * @param number
 * @param {number} decimals
 * @param {string} decPoint
 * @param {string} thousandsSep
 * @returns {string}
 */
export function NumberFormat(number, decimals = 2, decPoint = ',', thousandsSep = '.'): string {
   number = `${number}`.replace(/[^0-9+\-Ee.]/g, '');
   const n = !Number.isFinite(+number) ? 0 : +number;
   const prec = !Number.isFinite(+decimals) ? 2 : Math.abs(decimals);
   const sep = typeof thousandsSep === 'undefined' ? '.' : thousandsSep;
   const dec = typeof decPoint === 'undefined' ? ',' : decPoint;

   const toFixedFix = (_n, _prec): string => {
      const k = 10 ** _prec;
      return `${(Math.round(_n * k) / k).toFixed(_prec)}`;
   };

   const s = (prec ? toFixedFix(n, prec) : `${Math.round(n)}`).split('.');

   if (s[0].length > 3) {
      s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
   }

   if ((s[1] || '').length < prec) {
      s[1] = s[1] || '';
      s[1] += new Array(prec - s[1].length + 1).join('0');
   }

   return s.join(dec);
}

/**
 *
 * @param string
 */
export function OnlyNumbers(string: string): string {
   if (!string) {
      return '';
   }
   string = string.toString();
   return string.replace(/[^0-9]/g, '');
}

/**
 *
 * @param end
 * @param start
 */
export function CreateRange(end: number, start = 0): number[] {
   const array = [];
   for (let i = start; i < end; i += 1) {
      array.push(i);
   }
   return array;
}

/**
 *
 * @param object
 */
export function deleteEmpty(object: object): any {
   const newObject = { ...object };

   return Object.fromEntries(
      Object.entries(newObject)
         .filter(
            ([key, value]) =>
               value !== '' &&
               value !== undefined &&
               value !== null &&
               (value instanceof Array ? value.length !== 0 : true),
         )
         .map(([key, value]) => [key, value]),
   );
}

export async function setErrorUnFormWithYup(
   formRef: any,
   data: any,
   schema: Yup.ObjectSchema<any, any, any>,
): Promise<boolean> {
   try {
      // Remove all previous errors
      formRef.current.setErrors({});

      /**
       * Validate
       */
      await schema.validate(data, {
         abortEarly: false,
      });
   } catch (err) {
      const validationErrors = {};
      if (err instanceof Yup.ValidationError) {
         err.inner.forEach((yupError) => {
            // console.log(yupError.message);
            validationErrors[yupError.path] = yupError.message;
         });
         formRef.current.setErrors(validationErrors);
      } else {
         // console.log(err);
      }

      return false;
   }

   return true;
}

/**
 *
 * @param mixedVar
 */
export function isEmpty(mixedVar: any): boolean {
   //  discuss at: http://locutus.io/php/empty/
   // original by: Philippe Baumann
   //    input by: Onno Marsman (https://twitter.com/onnomarsman)
   //    input by: LH
   //    input by: Stoyan Kyosev (http://www.svest.org/)
   // bugfixed by: Kevin van Zonneveld (http://kvz.io)
   // improved by: Onno Marsman (https://twitter.com/onnomarsman)
   // improved by: Francesco
   // improved by: Marc Jansen
   // improved by: Rafał Kukawski (http://blog.kukawski.pl)
   //   example 1: empty(null)
   //   returns 1: true
   //   example 2: empty(undefined)
   //   returns 2: true
   //   example 3: empty([])
   //   returns 3: true
   //   example 4: empty({})
   //   returns 4: true
   //   example 5: empty({'aFunc' : function () { alert('humpty'); } })
   //   returns 5: false

   let undef;
   let key;
   let i;
   let len;
   const emptyValues = [undef, null, false, 0, '', '0'];

   for (i = 0, len = emptyValues.length; i < len; i += 1) {
      if (mixedVar === emptyValues[i]) {
         return true;
      }
   }

   if (typeof mixedVar === 'object') {
      // eslint-disable-next-line no-restricted-syntax
      for (key in mixedVar) {
         // eslint-disable-next-line no-prototype-builtins
         if (mixedVar.hasOwnProperty(key)) {
            return false;
         }
      }
      return true;
   }

   return false;
}

export function setValueInResults(array: any[], key: string | number, value: any, putValue: any): any[] {
   return array.map((el) => {
      if (el[key] === value) {
         el = { ...el, ...putValue };
      }

      return el;
   });
}
