import SimpleSchema from 'simpl-schema';

SimpleSchema.extendOptions([ 'canAutofillDefault' ]);

export let expectedIndexes = {};

// Returns true if the specified index has a name, and the collection has an
// existing index with the same name but different columns or options.
async function conflictingIndexExists(collection, index, options)
{
  if (!options.name)
    return false;
  
  let existingIndexes = await collection.rawCollection().indexes();
  
  for (let existingIndex of existingIndexes) {
    if (existingIndex.name === options.name) {
      if (!_.isEqual(existingIndex.key, index)
         || !_.isEqual(existingIndex.partialFilterExpression, options.partialFilterExpression))
      {
        return true;
      }
    }
  }
  
  return false;
}

export async function ensureIndex(collection, index, options)
{
  if (Meteor.isServer) {
    if (options.name && await conflictingIndexExists(collection, index, options)) {
      //eslint-disable-next-line no-console
      console.log(`Differing index exists with the same name: ${options.name}. Dropping.`);
      collection.rawCollection().dropIndex(options.name);
    }
    
    const mergedOptions = {background: true, ...options};
    collection._ensureIndex(index, mergedOptions);
    
    if (!expectedIndexes[collection.collectionName])
      expectedIndexes[collection.collectionName] = [];
    expectedIndexes[collection.collectionName].push({
      key: index,
      partialFilterExpression: options && options.partialFilterExpression,
    });
  }
}

// Given an index partial definition for a collection's default view,
// represented as an index field-list prefix and suffix, plus an index partial
// definition for a specific view on the same collection, combine them into
// a full index definition.
//
// When defining an index prefix/suffix for a default view, every field that is
// in the selector should be in either the prefix or the suffix. If the
// selector is a simple one (a regular value), it should be in the prefix; if
// it's a complex one (an operator), it should be in the suffix. If a field
// appears twice (in both the prefix and the view-specific index, or both the
// view-specific index and the suffix), it will be included only in the first
// position where it appears.
//
//   viewFields: [ordered dictionary] Collection fields from a specific view
//   prefix: [ordered dictionary] Collection fields from the default view
//   suffix: [ordered dictionary] Collection fields from the default view
//
export function combineIndexWithDefaultViewIndex({viewFields, prefix, suffix})
{
  let combinedIndex = {...prefix};
  for (let key in viewFields) {
    if (!(key in combinedIndex))
      combinedIndex[key] = viewFields[key];
  }
  for (let key in suffix) {
    if (!(key in combinedIndex))
      combinedIndex[key] = suffix[key];
  }
  return combinedIndex;
}

export function schemaDefaultValue(defaultValue) {
  // Used for both onCreate and onUpdate
  const fillIfMissing = ({newDocument, fieldName}) => {
    if (newDocument[fieldName] === undefined) {
      return defaultValue;
    } else {
      return undefined;
    }
  };
  const throwIfSetToNull = ({document, newDocument, fieldName}) => {
    const wasValid = (document[fieldName] !== undefined && document[fieldName] !== null);
    const isValid = (newDocument[fieldName] !== undefined && newDocument[fieldName] !== null);
    if (wasValid && !isValid) {
      throw new Error(`Error updating: ${fieldName} cannot be null or missing`);
    }
  };
  
  return {
    defaultValue: defaultValue,
    onCreate: fillIfMissing,
    onUpdate: throwIfSetToNull,
    canAutofillDefault: true,
  }
}
@@ -844,24 +844,36 @@
 isServer) %7B%0A
+    try %7B%0A  
     if (opti
@@ -940,24 +940,26 @@
 options)) %7B%0A
+  
       //esli
@@ -992,24 +992,26 @@
 nsole%0A      
+  
 console.log(
@@ -1080,24 +1080,26 @@
 ropping.%60);%0A
+  
       collec
@@ -1152,19 +1152,25 @@
     
+  
 %7D%0A    
-%0A
+  %0A 
     
+ 
 cons
@@ -1219,24 +1219,26 @@
 tions%7D;%0A    
+  
 collection._
@@ -1272,25 +1272,29 @@
 tions);%0A    
+ 
-%0A
+ %0A  
     if (!exp
@@ -1334,16 +1334,18 @@
 nName%5D)%0A
+  
       ex
@@ -1391,24 +1391,26 @@
 %5D = %5B%5D;%0A    
+  
 expectedInde
@@ -1447,16 +1447,18 @@
 .push(%7B%0A
+  
       ke
@@ -1473,16 +1473,18 @@
 ,%0A      
+  
 partialF
@@ -1552,12 +1552,117 @@
     
+  
 %7D);%0A
+    %7D catch(e) %7B%0A      console.error(%60Error in $%7Bcollection.collectionName%7D.ensureIndex: $%7Be%7D%60);%0A    %7D%0A
   %7D%0A

Fix exception swallowing during index creation