 import {Schema} from './types';
 import {addSchemaFilter} from './factory';
 import {CheckboxControlRenderer} from './renderers/Form/Checkbox';
 import {FormRenderer} from './renderers/Form/index';
 import {ButtonGroupControlRenderer} from './renderers/Form/ButtonGroupSelect';
 import {getLevelFromClassName} from './utils/helper';
 import {FileControlRenderer} from './renderers/Form/InputFile';
 import {ImageControlRenderer} from './renderers/Form/InputImage';
 import {RichTextControlRenderer} from './renderers/Form/InputRichText';
 import {HBoxRenderer} from './renderers/HBox';


 // 兼容老的用法，老用法 label 用在 checkbox 的右侧内容，新用法用 option 来代替。
 addSchemaFilter(function CheckboxPropsFilter(schema: Schema, renderer) {
   if (renderer.component !== CheckboxControlRenderer) {
     return schema;
   }
 
   if (schema.label && typeof schema.option === 'undefined') {
     schema = {
       ...schema
     };
     schema.option = schema.label;
     delete schema.label;
   }
 
   return schema;
 });
 
 function convertFieldSetTabs2Controls(schema: any) {
   const toUpdate: any = {};
   let flag = false;
 
   toUpdate.controls = Array.isArray(schema.controls)
     ? schema.controls.concat()
     : [];
   toUpdate.controls = toUpdate.controls.map((control: any) => {
     if (Array.isArray(control)) {
       let converted = convertFieldSetTabs2Controls({
         type: 'group',
         controls: control
       });
 
       if (converted !== control) {
         flag = true;
       }
 
       return converted;
     }
     return control;
   });
 
   schema.fieldSet &&
     (Array.isArray(schema.fieldSet)
       ? schema.fieldSet
       : [schema.fieldSet]
     ).forEach((fieldSet: any) => {
       flag = true;
       toUpdate.controls.push({
         ...convertFieldSetTabs2Controls(fieldSet),
         type: 'fieldSet',
         collapsable: schema.collapsable
       });
     });
 
   schema.tabs &&
     (flag = true) &&
     toUpdate.controls.push({
       type: 'tabs',
       tabs: schema.tabs.map((tab: any) => convertFieldSetTabs2Controls(tab))
     });
 
   if (flag) {
     schema = {
       ...schema,
       ...toUpdate
     };
     delete schema.fieldSet;
     delete schema.tabs;
   }
   return schema;
 }
 
 // Form 中，把 fieldSet 和 tabs 转成 {type: 'fieldSet', controls: []}
 // 同时把数组用法转成 {type: 'group', controls: []}
 addSchemaFilter(function FormPropsFilter(schema: Schema, renderer) {
   if (renderer.component !== FormRenderer) {
     return schema;
   }
 
   if (schema.fieldSet || schema.tabs) {
     // console.warn('Form 下面直接用 fieldSet 或者 tabs 将不支持，请改成在 controls 数组中添加。');
     schema = convertFieldSetTabs2Controls(schema);
   } else if (Array.isArray(schema.controls)) {
     let flag = false;
     let converted = schema.controls.map((control: any) => {
       if (Array.isArray(control)) {
         let converted = convertFieldSetTabs2Controls({
           type: 'group',
           controls: control
         });
 
         if (converted !== control) {
           flag = true;
         }
         return converted;
       }
       return control;
     });
 
     if (flag) {
       schema = {
         ...schema,
         controls: converted
       };
     }
   }
 
   return schema;
 });
 
 // FieldSet 中把 controls 里面的数组用法转成 {type: 'group', controls: []}
 addSchemaFilter(function FormPropsFilter(schema: Schema, renderer) {
 
   if (Array.isArray(schema.controls)) {
     let flag = false;
     let converted = schema.controls.map((control: any) => {
       if (Array.isArray(control)) {
         let converted = convertFieldSetTabs2Controls({
           type: 'group',
           controls: control
         });
 
         if (converted !== control) {
           flag = true;
         }
         return converted;
       }
       return control;
     });
 
     if (flag) {
       schema = {
         ...schema,
         controls: converted
       };
     }
   }
 
   return schema;
 });
 
 
 // CRUD/List  和 CRUD/Card 的 body 中的数组用法转成 hbox
 addSchemaFilter(function (schema: Schema, renderer) {
  return schema;
 });
 
 // button group 的 btnClassName 和 btnActiveClassName 改成 btnLevel 和 btnActiveLevel 了
 addSchemaFilter(function (scheam: Schema, renderer) {
   if (renderer.component !== ButtonGroupControlRenderer) {
     return scheam;
   }
 
   if (scheam.btnClassName || scheam.btnActiveClassName) {
     scheam = {
       ...scheam,
       btnLevel: getLevelFromClassName(scheam.btnClassName),
       btnActiveLevel: getLevelFromClassName(scheam.btnActiveClassName)
     };
 
     delete scheam.btnClassName;
     delete scheam.btnActiveClassName;
   }
 
   return scheam;
 });
 
 // FieldSet  className 定制样式方式改成 size 来配置
 addSchemaFilter(function (scheam: Schema, renderer) {
 
   if (
     scheam.className &&
     !scheam.size &&
     /\bfieldset(?:\-(xs|sm|md|lg))?\b/.test(scheam.className)
   ) {
     scheam = {
       ...scheam,
       size: RegExp.$1 || 'base',
       className: scheam.className.replace(
         /\bfieldset(?:\-(xs|sm|md|lg))?\b/,
         ''
       )
     };
 
     delete scheam.btnClassName;
     delete scheam.btnActiveClassName;
   }
 
   return scheam;
 });
 
 // 原 reciever 错别字改为 receiver
 addSchemaFilter(function (scheam: Schema, renderer) {
   if (
     renderer.component !== FileControlRenderer &&
     renderer.component !== ImageControlRenderer &&
     renderer.component !== RichTextControlRenderer
   ) {
     return scheam;
   }
 
   if (scheam.reciever) {
     scheam = {
       ...scheam,
       receiver: scheam.reciever
     };
     delete scheam.reciever;
   }
 
   if (scheam.videoReciever) {
     scheam = {
       ...scheam,
       videoReceiver: scheam.reciever
     };
     delete scheam.reciever;
   }
 
   return scheam;
 });
 
  
  // Hbox 一些旧格式的兼容
  addSchemaFilter(function (scheam: Schema, renderer) {
    if (renderer.component !== HBoxRenderer) {
      return scheam;
    }
  
    if (Array.isArray(scheam.columns) && scheam.columns.some(item => item.type)) {
      scheam = {
        ...scheam,
        columns: scheam.columns.map(item => {
          let {
            width,
            height,
            style,
            columnClassName,
            mode,
            horizontal,
            visible,
            visibleOn,
            body,
            ...rest
          } = item;
          if (item.type) {
            body = Array.isArray(body) ? body.concat() : body ? [body] : [];
            body.push(rest);
            item = {
              width,
              height,
              style,
              columnClassName,
              mode,
              horizontal,
              visible,
              visibleOn,
              body
            };
          }

          return item;
        })
      };
    }

    return scheam;
  });

 const controlMapping: any = {
   'array': 'input-array',
   'button-group': 'button-group-select',
   'city': 'input-city',
   'color': 'input-color',
   'date': 'input-date',
   'datetime': 'input-datetime',
   'time': 'input-time',
   'quarter': 'input-quarter',
   'month': 'input-month',
   'year': 'input-year',
   'date-range': 'input-date-range',
   'datetime-range': 'input-datetime-range',
   'diff': 'diff-editor',
   'file': 'input-file',
   'image': 'input-image',
   'list': 'list-select',
   'location': 'location-picker',
   'matrix': 'matrix-checkboxes',
   'month-range': 'input-month-range',
   'quarter-range': 'input-quarter-range',
   'number': 'input-number',
   'range': 'input-range',
   'rating': 'input-rating',
   'repeat': 'input-repeat',
   'rich-text': 'input-rich-text',
   'form': 'input-sub-form',
   'table': 'input-table',
   'tag': 'input-tag',
   'text': 'input-text',
   'url': 'input-url',
   'password': 'input-password',
   'email': 'input-email',
   'tree': 'input-tree',
   'progress': 'static-progress',
   'mapping': 'static-mapping'
 };
 
 const maybeFormItem = [
   'button',
   'submit',
   'reset',
   'button-group',
   'button-toolbar',
   'container',
   'grid',
   'hbox',
   'panel',
   'anchor-nav',
   'qr-code'
 ];
 
 function wrapControl(item: any) {
   if (!item || !item.type) {
     return item;
   }
 
   let {
     label,
     description,
     name,
     required,
     remark,
     inputOnly,
     labelClassName,
     caption,
     labelRemark,
     descriptionClassName,
     captionClassName,
     hint,
     showErrorMsg,
     mode,
     horizontal,
     className,
     inputClassName,
     columnClassName,
     visibleOn,
     visible,
     ...rest
   } = item;
 
   rest.name = name;
   rest.className = inputClassName;
 
   // 如果是按钮
   if (~['button', 'submit', 'reset'].indexOf(rest.type)) {
     rest.label = label;
     label = '';
   }
 
   return {
     type: 'control',
     label,
     description,
     name,
     required,
     remark,
     inputOnly,
     labelClassName,
     caption,
     labelRemark,
     descriptionClassName,
     captionClassName,
     hint,
     showErrorMsg,
     mode,
     horizontal,
     className,
     columnClassName,
     visibleOn,
     visible,
     body: rest
   };
 }
 
 const maybeStatic = [
   'tpl',
   'mapping',
   'progress',
   'status',
   'json',
   'video',
   'qrcode',
   'plain',
   'each',
   'link'
 ];
 
 function wrapStatic(item: any) {
   if (!item || !item.type) {
     return item;
   }
 
   return {
     ...item,
     type: `static-${item.type}`
   };
 }
 
 addSchemaFilter(function (schema: Schema, renderer: any, props: any) {
   const type = typeof schema?.type === 'string' ? schema.type.toLowerCase() : '';
   // controls 转成 body
   if (type === 'combo' && Array.isArray(schema.conditions)) {
     schema = {
       ...schema,
       conditions: schema.conditions.map(condition => {
         if (Array.isArray(condition.controls)) {
           condition = {
             ...condition,
             items: condition.controls.map(controlToNormalRenderer)
           };
           delete condition.controls;
         }
 
         return condition;
       })
     };
   }
 
   if (schema?.controls && schema.type !== 'audio') {
     schema = {
       ...schema,
       [schema.type === 'combo' ? `items` : 'body']: (Array.isArray(
         schema.controls
       )
         ? schema.controls
         : [schema.controls]
       ).map(controlToNormalRenderer)
     };
     delete schema.controls;
   } else if (
     schema?.quickEdit?.controls &&
     (!schema.quickEdit.type ||
       !~['combo', 'group', 'panel', 'fieldSet', 'fieldset'].indexOf(
         schema.quickEdit.type
       ))
   ) {
     schema = {
       ...schema,
       quickEdit: {
         ...schema.quickEdit,
         body: (Array.isArray(schema.quickEdit.controls)
           ? schema.quickEdit.controls
           : [schema.quickEdit.controls]
         ).map(controlToNormalRenderer)
       }
     };
     delete schema.quickEdit.controls;
   } else if (schema?.quickEdit?.type) {
     schema = {
       ...schema,
       quickEdit: controlToNormalRenderer(schema.quickEdit)
     };
   } else if (type === 'tabs' && Array.isArray(schema.tabs)) {
     schema = {
       ...schema,
       tabs: schema.tabs.map(tab => {
         if (Array.isArray(tab.controls) && !Array.isArray(tab.body)) {
           tab = {
             ...tab,
             body: tab.controls.map(controlToNormalRenderer)
           };
           delete tab.controls;
         }
 
         return tab;
       })
     };
   } else if (type === 'anchor-nav' && Array.isArray(schema.links)) {
     schema = {
       ...schema,
       links: schema.links.map(link => {
         if (Array.isArray(link.controls)) {
           link = {
             ...link,
             body: link?.controls.map(controlToNormalRenderer)
           };
 
           delete link.controls;
         }
 
         return link;
       })
     };
   } else if (type === 'input-array' && schema.items) {
     schema = {
       ...schema,
       items: Array.isArray(schema.items)
         ? schema.items.map(controlToNormalRenderer)
         : controlToNormalRenderer(schema.items)
     };
   } else if (
     (type === 'grid' || type === 'hbox') &&
     Array.isArray(schema.columns)
   ) {
     schema = {
       ...schema,
       columns: schema.columns.map(column => {
         if (Array.isArray(column.controls)) {
           column = {
             ...column,
 
             body: column?.controls.map(controlToNormalRenderer)
           };
 
           // 有可能直接外面的grid 或者 bhox 列里面用 form 的。
           if (column.type !== 'form') {
             delete column.type;
           }
 
           delete column.controls;
         }
 
         return column;
       })
     };
   } else if (type === 'service' && schema?.body?.controls) {
     schema = {
       ...schema,
       body: (Array.isArray(schema.body.controls)
         ? schema.body.controls
         : [schema.body.controls]
       ).map(controlToNormalRenderer)
     };
   }
 
   return schema;
 
   function controlToNormalRenderer(item: any) {
     if (item?.$ref && props.resolveDefinitions) {
       item = {
         ...props.resolveDefinitions(item.$ref),
         ...item
       };
       delete item.$ref;
     }
 
     return item && controlMapping[item.type]
       ? {
           ...item,
           type: controlMapping[item.type]
         }
       : ~maybeFormItem.indexOf(item?.type)
       ? wrapControl(item)
       : ~maybeStatic.indexOf(item?.type)
       ? wrapStatic(item)
       : item;
   }
 });
 