export default function mergeSchemas(schemas: any[]) {
  return schemas.reduce((prev, next) => {
    if (typeof next !== 'object' || next === null) {
      return prev;
    }

    Object.keys(next).forEach((key) => {
      const prevItem = prev[key];
      const nextItme = next[key];
      if (Array.isArray(prevItem) && Array.isArray(nextItme)) {
        // делаем мапу, чтоб каждый раз не перебирать массив
        // eslint-disable-next-line no-case-declarations
        const map = getMapByKey(prevItem);

        switch (key) {
          case 'groupList':
            prev[key] = nextItme.reduce((o, nextGroup) => {
              if (nextGroup.name in map) {
                // если группа с такм именем уже есть - выполняем слияние
                const prevGroup = o[map[nextGroup.name]];
                const res = Object.assign({}, prevGroup, nextGroup);
                if (
                  Array.isArray(prevGroup.attrList) &&
                  Array.isArray(nextGroup.attrList)
                )
                  // @ts-ignore
                  res.attrList = nextGroup.attrList.reduce((arr, attrName) => {
                    if (!prevGroup.attrList.includes(attrName))
                      arr.push(attrName);
                    return arr;
                  }, prevGroup.attrList.slice());
                o[map[nextGroup.name]] = res;
              } else {
                // иначе просто добавляем в массив
                o.push(nextGroup);
              }
              return o;
            }, prevItem.slice());
            break;
          case 'attrList':
            prev[key] = nextItme.reduce((o, attr) => {
              if (attr.name in map) {
                // если аттрибут с такм именем уже есть - выполняем слияние
                o[map[attr.name]] = Object.assign({}, o[map[attr.name]], attr);
              } else {
                // иначе просто добавляем в массив
                o.push(attr);
              }
              return o;
            }, prevItem.slice());
            break;
          default:
            prev[key] = prev[key].concat(next[key]);
            break;
        }
      } else {
        prev[key] = next[key];
      }
    });
    return prev;
  }, {});
}

function getMapByKey(arr: any, key?: string) {
  // @ts-ignore
  return arr.reduce((o, attr, i) => {
    o[attr[key || 'name']] = i;
    return o;
  }, {});
}
