import {
	Col,
	Form,
	Input,
	Select,
	DatePicker,
	TimePicker,
	Checkbox,
	Button,
	Radio,
	Switch,
	Upload,
	Icon,
	InputNumber,
	Cascader,
	TreeSelect,
	message,
} from 'antd';
import React, { Component, Fragment } from 'react';
import styles from './index.less';
import PropTypes from 'prop-types';
import moment from 'moment';
import { countSpecialField } from '@/baseComponent/utils';
import TableSelect from './TableSelect';
import ChildForm from './ChildForm';
import ReactQuill from 'react-quill';
import baseConfig from '@/config/config';
import 'react-quill/dist/quill.snow.css';
import ButtonUpload from './ButtonUpload';
import { getToken } from '@/webPublic/one_stop_public/utils/token';
import {
  getSassApiHeader,
  getSysCode
} from '@/webPublic/one_stop_public/2023yunshangguizhou/utils';

const RadioGroup = Radio.Group;
const Option = Select.Option;
const { TextArea } = Input;
const FormItem = Form.Item;

const CheckboxGroup = Checkbox.Group;
const { MonthPicker, RangePicker } = DatePicker;

const quillConfig = {
	toolbar: [
		[{ size: [] }],
		['bold', 'italic', 'underline', 'strike', 'blockquote'],
		[{ list: 'ordered' }, { list: 'bullet' }, { indent: '-1' }, { indent: '+1' }],
		['link', 'image', 'video'],
		['clean'],
	],
};

const ColDom = ({ children, filedSpan }) => {
	const bigSpan = Math.ceil(24 / filedSpan.big);
	const smallSpan = Math.ceil(24 / filedSpan.small);
	return (
		<Col
			xl={smallSpan}
			xxl={bigSpan}
			className={styles.colDom}
			style={countSpecialField(filedSpan.big)}>
			{children}
		</Col>
	);
};

const FormItemDom = ({ info, children, nameSpan }) => {
	return (
		<FormItem
			label={info.name}
			required={info.required || false}
			labelCol={{
				xl: nameSpan.small,
				xxl: nameSpan.big,
			}}
			wrapperCol={{
				xl: 24 - nameSpan.small,
				xxl: 24 - nameSpan.big,
			}}
			colon={false}>
			{children}
		</FormItem>
	);
};

export default class FormArray extends Component {
	constructor(props) {
		super(props);
		this.state = {};
	}

	formatTime = (time, formatTimeConfig = 'YYYY-MM-DD HH:mm') => {
		return moment(time);
	};

	datePickerOnchange = (dateString, key) => {
		const { changeValue } = this.props;
		changeValue(dateString, key);
	};

	defaultPropsCount = (info, value) => {
		const itemDisabled = typeof info.disabled !== 'undefined' ? info.disabled : false;
		const readOnly = typeof info.readOnly !== 'undefined' ? info.readOnly : false;
		const placeholder = typeof info.placeholder !== 'undefined' ? info.placeholder : '';
		const options = typeof info.options !== 'undefined' ? info.options : [];
		let itemValue = typeof value[info.key] === 'undefined' ? '' : value[info.key];
		if (['select', 'radioGroup'].indexOf(info.type) > -1) {
			itemValue = typeof itemValue === 'number' ? itemValue.toString() : itemValue;
			itemValue = typeof itemValue === 'boolean' ? itemValue + '' : itemValue;
		} else if (['selectMultiple', 'checkBoxMutiple', 'cascader'].indexOf(info.type) > -1) {
			itemValue = typeof itemValue === 'number' ? itemValue.toString() : itemValue;
			// 数字变成 字符串

			itemValue = typeof itemValue === 'string' && itemValue ? itemValue.split(',') : itemValue;
			// 有值且值是字符串则 变成数组

			itemValue = !itemValue ? [] : itemValue;
			// 没有值则变成空数组

			for (let i = 0; i < itemValue.length; i++) {
				itemValue[i] = typeof itemValue[i] === 'number' ? itemValue[i].toString() : itemValue[i];
				// 每一个值数字变成字符串
			}
		} else if (['datePicker', 'monthPicker', 'timePicker'].indexOf(info.type) > -1) {
			if (typeof itemValue !== 'object') {
				if (itemValue) {
					if (!isNaN(parseInt(itemValue)) && parseInt(itemValue) > 10000000) {
						itemValue = parseInt(itemValue);
						itemValue = moment(itemValue);
					} else {
						if (info.format) {
							itemValue = moment(itemValue, info.format);
						} else {
							itemValue = moment(itemValue);
						}
					}
				} else {
					itemValue = null;
				} /*格式化时间*/
			}
		} else if (['rangePicker'].indexOf(info.type) > -1) {
			if (typeof itemValue !== 'object') {
				let endValue = typeof value[info.endKey] === 'undefined' ? null : value[info.endKey];
				if (itemValue) {
					if (!isNaN(parseInt(itemValue)) && parseInt(itemValue) > 10000000) {
						itemValue = parseInt(itemValue);
					}
					if (!isNaN(parseInt(endValue)) && parseInt(endValue) > 10000000) {
						endValue = parseInt(endValue);
					}
					itemValue = [moment(itemValue), moment(endValue)];
				} else {
					itemValue = undefined;
				}
			}
		} else if (info.type === 'checkBox') {
			itemValue = !!itemValue;
		} else if (info.type === 'switch') {
			itemValue = !!value[info.key];
		}
		/*if(info.type === 'selectPeople'){
      itemValue = typeof itemValue !== 'object' ? {key:itemValue,label: ''} : itemValue;
    }*/

		const defaultProps = {
			readOnly: this.props.readOnly ? true : readOnly,
			disabled: this.props.disabled ? true : itemDisabled,
			value: itemValue,
			placeholder: placeholder,
			options: options,
			className: styles[info.className] || '',
		};
		if (typeof info.precision !== 'undefined') {
			defaultProps.precision = info.precision;
		}
		return defaultProps;
	};

	rangeOnChange = (dateStrings = [], key, endKey) => {
		const { changeValue } = this.props;
		changeValue(dateStrings[0], key);
		changeValue(dateStrings[1], endKey);
	};

	changeInputNumber = (value, config) => {
		if (typeof value === 'number') {
			if (typeof config.min !== 'undefined' && value < config.min) {
				message.warning(`${config.name}不能小于${config.min}`);
			} else if (typeof config.max !== 'undefined' && value > config.max) {
				message.warning(`${config.name}不能大于${config.max}`);
			}
		}
	};

	domAssembly = () => {
		const { changeValue, value, config, fileSpan, nameSpan } = this.props;
		return config.map((info, i) => {
			let fieldDom = null;
			const defaultProps = this.defaultPropsCount(info, value);
			switch (info.type) {
				case 'input': // 普通文本
					fieldDom = (
						<Input
							{...defaultProps}
							style={info.style || {}}
							onChange={(e) => {
								changeValue(e.target.value, info.key);
							}}
						/>
					);
					break;
				case 'inputNumber': // 数字文本
					fieldDom = (
						<Fragment>
							<InputNumber
								{...defaultProps}
								style={info.style || { width: '100%' }}
								min={info.min ? info.min : 0}
								max={info.max ? info.max : Infinity}
								onChange={(value) => {
									this.changeInputNumber(value, info);
									changeValue(value, info.key);
								}}
							/>
							{info.formatter ? <span>{info.formatter}</span> : ''}
						</Fragment>
					);
					break;
				case 'idCard':
					fieldDom = (
						<Fragment>
							<Input
								{...defaultProps}
								style={info.style || {}}
								onChange={(e) => {
									changeValue(e.target.value, info.key);
								}}
							/>
						</Fragment>
					);
					break;
				case 'phone':
					fieldDom = (
						<Fragment>
							<InputNumber
								{...defaultProps}
								style={info.style || { width: '100%' }}
								min={0}
								max={info.max ? info.max : Infinity}
								onChange={(value) => {
									changeValue(value, info.key);
								}}
							/>
						</Fragment>
					);
					break;
				case 'checkBoxMutiple': // 多选 checkbox
					fieldDom = (
						<CheckboxGroup
							{...defaultProps}
							onChange={(value) => {
								changeValue(value, info.key);
							}}
						/>
					);
					break;
				case 'cascader': // 级联选择
					fieldDom = (
						<Cascader
							value={defaultProps.value}
							options={defaultProps.options}
							style={{ width: '100%' }}
							onChange={(value, selectedOptions) => {
								changeValue(value, info.key);
							}}
						/>
					); // 返回数组 [parent,child]
					break;
				case 'selectMultiple': // 下拉多选
					fieldDom = (
						<Select
							{...defaultProps}
							mode="multiple"
							allowClear
							style={{ width: '100%' }}
							onChange={(value) => {
								changeValue(value, info.key);
							}}>
							{defaultProps.options.map((optionItem) => {
								return (
									<Option
										key={
											typeof optionItem.key !== 'boolean' ? optionItem.key + '' : optionItem.key
										}>
										{optionItem.name}
									</Option>
								);
							})}
						</Select>
					);
					break;
				case 'select': // 下拉单选
					fieldDom = (
						<Select
							{...defaultProps}
							style={{ width: '100%' }}
							allowClear={typeof info.allowClear !== 'undefined' ? info.allowClear : true}
							onChange={(value) => {
								changeValue(value, info.key);
							}}>
							{defaultProps.options.map((optionItem) => {
								return (
									<Option
										key={typeof optionItem.key !== 'boolean' ? optionItem.key + '' : optionItem.key}
										disabled={optionItem.disabled}>
										{optionItem.name}
									</Option>
								);
							})}
						</Select>
					);
					break;
				case 'tableSelect':
					fieldDom = (
						<TableSelect
							config={info}
							value={defaultProps.value}
							onChange={changeValue}
							disabled={defaultProps.disabled}
						/>
					);
					break;
				case 'childForm':
					fieldDom = (
						<ChildForm
							config={info}
							value={defaultProps.value}
							onChange={changeValue}
							disabled={defaultProps.disabled}
						/>
					);
					break;
				case 'checkBox': // 布尔值选择
					fieldDom = (
						<Checkbox
							checked={defaultProps.value}
							disabled={defaultProps.disabled}
							onChange={(e) => {
								changeValue(e.target.checked, info.key);
							}}>
							{info.text}
						</Checkbox>
					);
					break;
				/*  case 'editable': // 可编辑的富文本
            fieldDom = <div className={styles.Editable}>
              <Editable onChange={changeValue}
                        filedKey={info.key}
                        disabled={defaultProps.disabled}
                        value={defaultProps.value}
              />
            </div>;
            break;*/

				case 'datePicker': // 日期选择
					fieldDom = (
						<DatePicker
							showTime={info.showTime}
							{...defaultProps}
							style={{ width: '100%' }}
							format={info.format}
							onChange={(date, dateString) => {
								this.datePickerOnchange(dateString, info.key);
							}}
						/>
					);
					break;
				case 'timePicker': // 日期选择
					fieldDom = (
						<TimePicker
							{...defaultProps}
							style={{ width: '100%' }}
							format={info.format || 'HH:mm'}
							onChange={(date, dateString) => {
								this.datePickerOnchange(dateString, info.key);
							}}
						/>
					);
					break;
				case 'rangePicker': // 时间段选择
					if (info.disabledDate && info.disabledDate === 'afterYesterday') {
						// 禁用今天之前的时间
						defaultProps.disabledDate = (current) => {
							// Can not select days before today and today
							return current < moment().add(-1, 'days');
						};
					}
					fieldDom = (
						<RangePicker
							showTime={info.showTime}
							{...defaultProps}
							style={{ width: '100%' }}
							format={info.format}
							placeholder={info.placeholder || ['开始日期', '结束日期']}
							onChange={(dates, dateStrings) => {
								this.rangeOnChange(dateStrings, info.key, info.endKey);
							}}
						/>
					);
					break;

				case 'monthPicker': // 年月 选择
					fieldDom = (
						<MonthPicker
							{...defaultProps}
							style={{ width: '100%' }}
							format={info.format}
							onChange={(date, dateString) => {
								this.datePickerOnchange(dateString, info.key);
							}}
						/>
					);
					break;

				case 'textarea': // 文本框
					fieldDom = (
						<TextArea
							{...defaultProps}
							autoSize={{ minRows: 4, maxRows: 6 }}
							onChange={(e) => {
								changeValue(e.target.value, info.key);
							}}
						/>
					);
					break;
				case 'radioGroup': // 圆形 选择框
					fieldDom = (
						<RadioGroup
							value={defaultProps.value}
							disabled={defaultProps.disabled}
							style={{ width: '100%' }}
							onChange={(e) => {
								changeValue(e.target.value, info.key);
							}}>
							{defaultProps.options.map((optionItem) => {
								const radioValue =
									typeof optionItem.key !== 'boolean' ? optionItem.key + '' : optionItem.key;
								return (
									<Radio key={radioValue} value={radioValue}>
										{optionItem.name}
									</Radio>
								);
							})}
						</RadioGroup>
					);
					break;
				case 'switch': // 开关
					fieldDom = (
						<Switch
							{...defaultProps}
							checked={defaultProps.value}
							checkedChildren={info.checkedChildren || ''}
							unCheckedChildren={info.unCheckedChildren || ''}
							onChange={(e) => {
								changeValue(e, info.key);
							}}
						/>
					);
					break;
				case 'editor':
					let thisClassName = styles.editorLayout;
					if (info.className) {
						thisClassName = styles[info.className];
					}
					fieldDom = (
						<ReactQuill
							{...defaultProps}
							className={thisClassName}
							modules={quillConfig}
							onChange={(e) => {
								changeValue(e, info.key);
							}}
						/>
					);
					break;
				case 'upload':
					fieldDom = (
						<Upload
							action={baseConfig.uploadUrl + `&isConvert=${info.isConvert || false}`}
							accept={info.accept}
							multiple={info.multiple}
							{...defaultProps}
              headers={getSassApiHeader()}
              data={{
                token: getToken(),
              }}
							defaultFileList={value[info.key]}
							name="file"
							onChange={({ fileList }) => {
								changeValue(fileList, info.key);
							}}>
							<Button>
								<Icon type="upload" /> 上传
							</Button>
						</Upload>
					);

					break;
				case 'buttonUpload':
					fieldDom = (
						<ButtonUpload
							onChange={(url) => {
								changeValue(url, info.key);
							}}
							{...info}
							{...defaultProps}
						/>
					);
					break;
				case 'text':
					fieldDom = <div>{defaultProps.value || info.value}</div>;
					break;
				case 'TreeSelect':
					fieldDom = (
						<TreeSelect
							{...defaultProps}
							{...info.props}
							onChange={(v) => changeValue(v, info.key)}
						/>
					);
					break;
				case 'personalRender':
					fieldDom = info.render({ value, onChange: (v, key) => changeValue(v, key) });
					break;
				default:
					fieldDom = null;
					break;
			}
			return (
				<ColDom filedSpan={info.fileSpan || fileSpan} key={info.key + i}>
					<FormItemDom info={info} nameSpan={info.nameSpan || nameSpan}>
						{fieldDom}
					</FormItemDom>
				</ColDom>
			);
		});
	};

	render() {
		const { style } = this.props;
		return (
			<div className={styles.FormArray} style={style}>
				{this.domAssembly()}
			</div>
		);
	}
}
/**
 * 最主要的 props 就是config.
 * config: 表单填写的每一个字段,根据type的不同渲染不同的组件,
 * 包含 [inputNumber(数字input),input,
 *      selectMultiple(多选下拉),select(单选下拉)
 *      checkBox(单选checkbox),
 *      checkBoxMutiple (多选checkbox)
 *      datePicker日期选择  value 传入 时间戳格式 等等
 *
 * 具体请查看下面的demo
 *
 * changeValue: 表单的值改变后的回调
 * value : 表单的值应该是一个对象state {name:'',phone:''....}
 * fileSpan : { big:5, small:4}
 *         small: 设置1366*768的屏幕 每一行显示几个字段  如 只显示3个 则 = 3
 *         big: 设置1920*1080的屏幕  每一行显示几个字段 同上
 * nameSpan { big:5, small:4}   同上设置 一个字段的 字段名和填写的值所占的比例
 * */

/**
 * 2019年3月7日
 * 钟是志
 * 增加对 时间段rangePicker选择的支持 具体使用见下面的 demo
 * */
FormArray.propTypes = {
	config: PropTypes.array,
	readOnly: PropTypes.bool,
	disabled: PropTypes.bool,
	changeValue: PropTypes.func,
	value: PropTypes.object,
	fileSpan: PropTypes.object,
	nameSpan: PropTypes.object,
	style: PropTypes.object,
};
FormArray.defaultProps = {
	config: [
		{
			name: '数字选择',
			type: 'inputNumber',
			placeholder: '',
			key: 'scoreRank',
		},
		{
			name: '文本框',
			type: 'input',
			placeholder: '',
			key: 'scoreRank2',
		},
		{
			key: 'startDate',
			endKey: 'endDate',
			name: '时间段选择',
			type: 'rangePicker',
			format: 'YYYY-MM-DD',
			placeholder: ['开始时间', '结束时间'],
			required: true,
		},
		{
			name: '日期选择',
			type: 'datePicker',
			placeholder: '',
			key: 'scoreRank5',
		},
		{
			name: '下拉框选择',
			type: 'select',
			placeholder: '',
			key: 'scoreRank6',
		},
		{
			name: '下拉框多选',
			type: 'selectMultiple',
			placeholder: '',
			key: 'scoreRank7',
		},
		{
			key: 'studentType',
			name: 'checkBox多选',
			type: 'checkBoxMutiple',
			options: [
				{ label: '本科', value: '本科' },
				{ label: '专科', value: '专科' },
				{ label: '研究生', value: '研究生' },
			],
			required: true,
		},
	],
	changeValue: (value, key) => {},
	value: {},
	fileSpan: {
		big: 5,
		small: 4,
	},
	nameSpan: {
		big: 10,
		small: 12,
	},
	disabled: false,
	style: {},
};
