import SimpleSchema from 'simpl-schema';


/*

Convert a nested SimpleSchema schema into a JSON object
If flatten = true, will create a flat object instead of nested tree

*/
export const convertSchema = (schema, flatten = false) => {
  if (schema._schema) {
    let jsonSchema = {};
    
    Object.keys(schema._schema).forEach(fieldName => {
      // exclude array fields
      if (fieldName.includes('$')) {
        return;
      }

      // extract schema
      jsonSchema[fieldName] = getFieldSchema(fieldName, schema);

      // check for existence of nested schema on corresponding array field
      const arraySubSchema = getArraySubSchema(fieldName, schema);
      // if nested schema exists, call convertSchema recursively
      if (arraySubSchema) {
        const convertedArraySubSchema = convertSchema(arraySubSchema);
        if (flatten) {
          jsonSchema = { ...jsonSchema, ...convertedArraySubSchema };
        } else {
          jsonSchema[fieldName].schema = convertedArraySubSchema;
        }
      }

      // check if the type of this field is a nested schema
      const objectSubSchema = getObjectSubSchema(fieldName, schema);
      if (objectSubSchema) {
        let convertedObjectSubSchema = convertSchema(objectSubSchema);
        const mergedSubSchema = mergeSubSchemaWithParent(convertedObjectSubSchema, jsonSchema, fieldName);
        jsonSchema = { ...jsonSchema, ...mergedSubSchema };
        delete jsonSchema[fieldName];
      }
    });
    return jsonSchema;
  } else {
    return null;
  }
};

/*

Get a JSON object representing a field's schema

*/
export const getFieldSchema = (fieldName, schema) => {
  let fieldSchema = {};
  schemaProperties.forEach(property => {
    const propertyValue = schema.get(fieldName, property);
    if (propertyValue) {
      fieldSchema[property] = propertyValue;
    }
  });
  return fieldSchema;
};

/*

Given an array field, get its nested schema

*/
export const getArraySubSchema = (fieldName, schema) => {
  const arrayItemSchema = schema._schema[`${fieldName}.$`];
  return arrayItemSchema && arrayItemSchema.type.definitions[0].type;
};

/*

Given an object field, get its sub schema

*/
export const getObjectSubSchema = (fieldName, schema) => {
  const objectItemSchema = schema._schema[fieldName].type.definitions[0].type;
  if (SimpleSchema.isSimpleSchema(objectItemSchema)) {
    return objectItemSchema;
  }
};

/*

Given a subschema, prefixes the field names with the parent's, and merges the parent's values
into each child (this way field properties like 'editableBy' and 'group' can be set on the parent
for all children, and can still be overridden by children.

*/
export const mergeSubSchemaWithParent = (schema, jsonSchema, parentName) => {
  const merged = {};
  for (const key in schema) {
    merged[`${parentName}.${key}`] = Object.assign({}, jsonSchema[parentName], schema[key]);
  }
  return merged;
};

export const schemaProperties = [
  'type',
  'label',
  'optional',
  'required',
  'min',
  'max',
  'exclusiveMin',
  'exclusiveMax',
  'minCount',
  'maxCount',
  'allowedValues',
  'regEx',
  'blackbox',
  'trim',
  'custom',
  'defaultValue',
  'autoValue',
  'hidden', // hidden: true means the field is never shown in a form no matter what
  'mustComplete', // mustComplete: true means the field is required to have a complete profile
  'profile', // profile: true means the field is shown on user profiles
  'form', // form placeholder
  'inputProperties', // form placeholder
  'control', // SmartForm control (String or React component)
  'input', // SmartForm control (String or React component)
  'autoform', // legacy form placeholder; backward compatibility (not used anymore)
  'order', // position in the form
  'group', // form fieldset group
  'onInsert', // field insert callback
  'onEdit', // field edit callback
  'onRemove', // field remove callback
  'viewableBy',
  'insertableBy',
  'editableBy',
  'resolveAs',
  'searchable',
  'description',
  'beforeComponent',
  'afterComponent',
  'placeholder',
  'options',
  'query',
  'fieldProperties',
];

export const formProperties = [
  'optional',
  'required',
  'min',
  'max',
  'exclusiveMin',
  'exclusiveMax',
  'minCount',
  'maxCount',
  'allowedValues',
  'regEx',
  'blackbox',
  'trim',
  'custom',
  'defaultValue',
  'autoValue',
  'mustComplete', // mustComplete: true means the field is required to have a complete profile
  'form', // form placeholder
  'inputProperties', // form placeholder
  'control', // SmartForm control (String or React component)
  'input', // SmartForm control (String or React component)
  'order', // position in the form
  'group', // form fieldset group
  'description',
  'beforeComponent',
  'afterComponent',
  'placeholder',
  'options',
  'query',
  'fieldProperties',
];

@@ -1,47 +1,4 @@
-import SimpleSchema from 'simpl-schema';%0A%0A%0A
 /*%0A%0A
@@ -563,22 +563,17 @@
   const 
-arrayS
+s
 ubSchema
@@ -574,32 +574,30 @@
 Schema = get
-ArraySub
+Nested
 Schema(field
@@ -686,22 +686,17 @@
     if (
-arrayS
+s
 ubSchema
@@ -714,37 +714,32 @@
  const converted
-Array
 SubSchema = conv
@@ -752,14 +752,9 @@
 ema(
-arrayS
+s
 ubSc
@@ -827,37 +827,32 @@
 ma, ...converted
-Array
 SubSchema %7D;%0A   
@@ -915,21 +915,16 @@
 onverted
-Array
 SubSchem
@@ -947,451 +947,8 @@
    %7D
-%0A%0A      // check if the type of this field is a nested schema%0A      const objectSubSchema = getObjectSubSchema(fieldName, schema);%0A      if (objectSubSchema) %7B%0A        let convertedObjectSubSchema = convertSchema(objectSubSchema);%0A        const mergedSubSchema = mergeSubSchemaWithParent(convertedObjectSubSchema, jsonSchema, fieldName);%0A        jsonSchema = %7B ...jsonSchema, ...mergedSubSchema %7D;%0A        delete jsonSchema%5BfieldName%5D;%0A      %7D
 %0A   
@@ -1426,16 +1426,14 @@
  get
-ArraySub
+Nested
 Sche
@@ -1528,33 +1528,28 @@
 ;%0A  
-return arrayItem
+const nested
 Schema 
-&&
+=
  arr
@@ -1564,819 +1564,75 @@
 hema
-.type.definitions%5B0%5D.type;%0A%7D;%0A%0A/*%0A%0AGiven an object field, get its sub schema%0A%0A*/%0Aexport const getObjectSubSchema = (fieldName, schema) =%3E %7B%0A  const objectItemSchema = schema._schema%5BfieldName%5D.type.definitions%5B0%5D.type;%0A  if (SimpleSchema.isSimpleSchema(objectItemSchema)) %7B%0A    return objectItemSchema;%0A  %7D%0A%7D;%0A%0A/*%0A%0AGiven a subschema, prefixes the field names with the parent's, and merges the parent's values%0Ainto each child (this way field properties like 'editableBy' and 'group' can be set on the parent%0Afor all children, and can still be overridden by children.%0A%0A*/%0Aexport const mergeSubSchemaWithParent = (schema, jsonSchema, parentName) =%3E %7B%0A  const merged = %7B%7D;%0A  for (const key in schema) %7B%0A    merged%5B%60$%7BparentName%7D.$%7Bkey%7D%60%5D = Object.assign(%7B%7D, jsonSchema%5BparentName%5D, schema%5Bkey%5D);%0A  %7D%0A  return merged
+ && arrayItemSchema.type.definitions%5B0%5D.type;%0A  return nestedSchema
 ;%0A%7D;

Revert changes to schema_utils for now because they break FormIntl