<template>
  <div
		style="position:relative;"
		:class="difFontSize ? 'is-show-wordSize-limit' : 'is-show-word-limit'"	
	>
		<el-input
			ref="rootDiv" 
			v-model="model"
			:id="id" 
			type="textarea"
			:style="{'border-bottom': isShowRed ? `1px solid ${isShowRed}` : ''}"
			class="show-word-limit show-scroll"
			:cols="cols"
			:rows="rows"
			v-bind="attrs"
			v-on="$listeners"
			v-bind:disabled="isDisable"
			:autosize="autosize"
      :placeholder="placeholderEnable || placeholder || $t('components.请输入')"
			:show-word-limit="!isLimitChar && !isIgnoreLine"
			:maxlength="rows * cols"
			@blur="onBlur"
			@change="handleChange"
			@focus="onFocus"
		>
		<!-- :class="isRequired? 'input-required' : null" -->
			<template v-slot:suffix>
				<slot name="suffix"></slot>
			</template>
		</el-input>
		<span v-if="isLimitChar || isIgnoreLine" class="cus-input-count">{{curLength}}/{{rows * cols}}</span>

		<div class="viewMulRow el-textarea el-input--small viewMulRowScroll"
			@click="viewClick" 
			v-show="model && charmod && showTipX && !focused"
			v-html="colorText"
			:style="{'background-color': isDisable ? 'rgb(235, 235, 235)' : '#ffffff'}"
		></div>
		<!-- <el-dialog
				ref="dialog"
				v-dialogDrag
				:visible.sync="modalVisible"
				center class="preview"
				:show-close="true"
				destroy-on-close title="文本清理提示"
				width="70%"
				:append-to-body="true"
				v-if="modalVisible"
			>
				<div>
					<el-col :offset="1" :span="10">
						<label>清理后的内容({{`${rows} x ${cols}`}})</label>
						<div style="border:1px solid #555;height:30em;padding:1em;overflow:auto">
							<pre>{{model}}</pre>
						</div>
					</el-col>
					<el-col :offset="2" :span="10">
						<label>红色、划线字符已被自动清除</label>
						<div style="border:1px solid #555;height:30em;padding:1em;overflow:auto">
							<p v-for="(line,index) in lineRows" :key="index" :style="{color:index>=rows?'red':'','text-decoration-line': index>=rows?'line-through':''}" v-html="line">
							</p>
						</div>
					</el-col>
				</div>
				<div slot="footer" class="dialog-footer">
						<el-button type="primary" @click="modalVisible=false">确定</el-button>
				</div>
		</el-dialog> -->
  </div>
</template>

<script>
import commonDepend from '~/mixin/commonDepend.js'
import markSetShowRed from '~/components/business/componentMixins/markSetShowRed.js'
import lodash from "lodash";
const SP_STR = "✌";
const SP_CHAR = SP_STR.charCodeAt(0);
const LINE_CHAR = "\n"
const SWIFT_CHARS =
  " \r\n'()+,-./01234567890:?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const SWIFTZ_CHARS =
	" \r\n!\"#%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz{";
const JNWB_CHARS = 
	" .,-_()/=+?!&*;@#:%[]\n\r\t01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
	//境内外币,行内划转中文模式不能输入改字符集
const JNWB_CNCHARS = 
	"!!#$%^[]{}><'‘’“”\/??=+¥/、【】|"
const CHARSET = ["", "", SWIFT_CHARS, SWIFTZ_CHARS,JNWB_CHARS,JNWB_CNCHARS];
/**
 * 使用antd input是因为jup-input加了debounce,延迟不利于控制字符
 * 支持swift x、支持swiftx字符集
 * 中文默认按两个字符算,默认为任意模式,支持中英混杂
 */

export default {
  inject: {
		root: {
			default: () => null
		}
	},
	mixins: [commonDepend, markSetShowRed],
  props: {
    value: { type: [String, Number], default: undefined },
    disabled: { type: Boolean, default: false },
    id: { type: String, default: undefined },
    // 此对象为markset或者modifySet所在的对象,如果传了此对象可以标记当前对象下的字段为红色下划线
    markSetData: {
      type: Object,
      default: () => null
    },
		customModifykey: {
			type: String,
      default: null
    },
    cols: { type: Number, default: 65 },
    rows: { type: Number, default: 100 },
		chsbit: { type: Number, default: 2 },
		//0任意模式,1英文模式,2 swift模式 3 swiftz模式
		charmod: { type: Number, default: 0 },
		autosize: {
			type: Object,
			default: () => ({
				minRows: 1,
				maxRows: 4
			})
		},
		isCheckInCompontent: {
			type: Boolean,
			default: true
		},
		// 是否必填
		isRequired: {
			type: Boolean,
			default: false
		},
		// 根据中英文判断必填的提示词
		isEn: {
			type: Boolean,
			default: false
    },
    //是否提示文字
    showTip: {
      type: Boolean,
			default: true
    },
    placeholder:{
      type: String,
      default: null
		},
		isShowFontNoSameWidth: {
			type: Boolean,
			default: false
		},
		maxlength: {
			type: [Number, String],
			default: 1000
		},
		isCheckMaxRows: {
			type: Boolean,
			default: true
		},
		difFontSize: {
			type: Boolean,
			default: false
		},
		isLimitChar: {
			type: Boolean,
			default: false
		},
		isIgnoreLine: {
			type: Boolean,
			default: true
		}
  },
  data(){
    return {
      lineRows:[],
      modalVisible:false,
      focused:false,
      colorText:''
    }
  },
  computed: {
    model: {
      get() {
        return this.value;
      },
      set(newVal) {
				this.$emitNewValue = newVal;
				this.$emit("input", newVal)
			}
    },
    mode () {
      return this.$store.state.Status.mode
    },
    isDisable() {
			return this.mode === 'display' || this.disabled
		},
    placeholderEnable(){
      let label = this.$parent.label
      let curLabel = ''
      if (label) {
        curLabel = this.$i18n.locale === 'en' ? this.$t('components.请输入') + ' ' +  this.$t('components.' + label) : this.$t('components.请输入') + this.$t('components.' + label)
      }
      return curLabel
    },
    highlight () {
      return this.$store.state.Status.highlights.indexOf(this.id) !== -1
    },
    highlightChanges () {
      return this.$store.state.Status.highlightChanges.indexOf(this.id) !== -1
    },
    attrs(){
      if(this.mode === 'display' || this.disabled)
      {
        let {placeholder,...rest} = this.$attrs
        return rest
      }
      return this.$attrs
    },
    showTipX(){
      if(!this.showTip){
        return false
      }
      if(this.rows>1 && this.charmod){
        return true
      }
      return false
		},
		getCheckMaxRow() {
			let code = [
				'Gitadd','Hitupd','Netadd','Nitdla','Nitpdl','Gitame','Gitpam','Gitdla','Gitpdl','Nitcan',
				'Nitcrq','Netcan','Gitplb','Gctadd','Nctcan','Gitppl','Netcrq','Netpcr','Gitpop','Nitpcj',
				'Nitpcr','Hitcan','Hitdla','Hitpdl','Netset','Netopn','Gftcan','Gftadd','Nitset','Nitpse',
				'Getcan','Gitopn','Nitopn','Hitopn','Hitpop','Nitame','Nitpam','Hitame','Hitpam','Nitplb',
				'Hitpca','Nitppl','Gitset','Gitpse','Getset','Gitcrq','Gitpcr','Gitcan','Gitcrj','Gitpcj',
				'Gctcan','Getopn','Netame','Getcrq','Getpcr','Nitcom','Nitadd','Nitmjm','Getadd','Niteng',
				'Giteng','Nitenc','Nitfre','Nitpfr','Gitpfr','Gitfre','Conres','Gitatt','Nctfre','Nctadd',
				'Nitcrj','Netfre','Nctpfr','Netpfr','Nftcan','Nftadd','Gctpfr','Getpfr','Gctfre','Getfre',
				'Nitatt','Fctopn','Fctcan','Getame','Nitfee','Gctfee','Netfee','Gitzsq','Nitzsq','Nitpop',
				'Getfee','Gitfee','Gitcom','Gitenc','Nctfee','Netfee'
			]
			let formatCode = code.map((item) => {
				return item.toLowerCase()
			})
			if (this.root && this.root.trnName && formatCode.includes(this.root.trnName.toLowerCase())) {
				return false
			}
			return this.isCheckMaxRows
		},
		curLength() {
			let len = 0
			if (this.isLimitChar && this.model && typeof(this.model) == 'string') {
				len = this.model.replace(/[^x00-xff]/g, 'xx').length
			} else {
				len = this.model != undefined ? this.model.length || 0 : 0
			}
			if (this.isIgnoreLine && this.model && typeof(this.model) == 'string') {
				len = this.model.replace(/\r?\n/g, '').length
			}
			return len
		}
  },
	mounted () {
    this.initValidCallback()
		this.colorText = this.filterChar(this.model)
	},
  methods: {
		onBlur(e) {
      this.colorText = this.filterChar(this.model)
      this.focused = false
    },
    onFocus(){
      this.focused = true
    },
		handleChange () {
			if (!this.customModifykey) {
				// 添加isModify属性
				this.changeModify()
			}
		},

    filterChar(valStr){
      if(!valStr){
        return ""
      }

      if(!this.charmod){
        return valStr
      }
      if(!this.showTipX){
        return valStr
      }

      let newVal = "";
      let begPos = -2;
      for(let i = 0;i<valStr.length;i++){
        let cStr = valStr.charAt(i)
        let c = valStr.charCodeAt(i);
        
        if(this.isCharFit(c,cStr)){
          if(begPos >= 0){
            newVal = newVal+"</span>";
            begPos = -1
          }
          newVal = newVal + cStr
        }else{
          if(begPos < 0){
            newVal = newVal + "<span class=\"mul_row_text_error_tip\">"
            begPos = i
          }
          newVal = newVal + cStr
        }
      }
      if(begPos >= 0){
        newVal = newVal+"</span>";
      }
      newVal = newVal.replace(/\r?\n/g,"<br/>")
      return newVal;
    },
    isCharFit(c,cStr){
      if ((c >= 0x0001 && c <= 0x007e) || (c >= 0xff60 && c <= 0xff9f)) {
            //判断字符集
          if([2,3].includes(this.charmod) && CHARSET[this.charmod].indexOf(cStr)<0){
            return false
          }
      }else{
        if(this.charmod != 0){
          return false
        }
      }
      return true
		},
		// 校验多行输入框
		isCheckMulRowInput (_this, charmod, totalLen, checkParams) {
			let prop = this.customModifykey || this.$parent.prop
			if (!prop || !this.root) {
				return false;
			}
			// 校验字符
			let checkCode = [
				{required: checkParams.isRequired, message: checkParams.isEn ? 'Required Field' : '必输项', source:"mulrow"},
				{
					validator: (rule, value, callback) => {
						if (!_this.isLimitChar && value && _this.curLength > totalLen) {
							callback(new Error('长度不能超过' + totalLen))
						} else {
							let res = {
								status: true,
								msg: ''
							}
							if (charmod === 0) {
								callback()
								_this.$emit('checkFalse', true)
							} else if (charmod === 1) {
								console.log('=========存在中文字符', prop)
								let valStr = value || '';
								for(let i = 0; i < valStr.length; i++){
									let cStr = valStr.charAt(i)
									let c = valStr.charCodeAt(i);
									if (!((c >= 0x0001 && c <= 0x007e) || (c >= 0xff60 && c <= 0xff9f))) {
										res = {
											status: false,
											msg: '存在中文字符,请核查'
										}
										break;
									}
								}
								if (res.status) {
									callback()
									_this.$emit('checkFalse', true)
								} else {
									callback(new Error(res.msg))
									_this.$emit('checkFalse', false)
								}
							} else if (charmod > 1 && charmod < 5) {
								console.log('=========存在非法字符', prop)
								let valStr = value || '';
								for(let i = 0; i < valStr.length; i++){
									let cStr = valStr.charAt(i)
									let c = valStr.charCodeAt(i);
									if (CHARSET[charmod].indexOf(cStr) < 0) {
										res = {
											status: false,
											msg: '存在非法字符,请核查'
										}
										break;
									}
								}
								if (res.status) {
									_this.$emit('checkFalse', true)
									callback()
								} else {
									_this.$emit('checkFalse', false)
									callback(new Error(res.msg))
								}
							} else if(charmod == 5) {
								let valStr = value || '';
								for(let i = 0; i < valStr.length; i++){
									let cStr = valStr.charAt(i)
									let c = valStr.charCodeAt(i);
									if (CHARSET[charmod].indexOf(cStr) >= 0) {
										res = {
											status: false,
											msg: '存在特殊字符'+ CHARSET[charmod]
										}
										break;
									}
								}
								if(valStr.indexOf('..') > -1){
									res = {
											status: false,
											msg: '存在特殊字符..'
										}
								}
								if (res.status) {
									_this.$emit('checkFalse', true)
									callback()
								} else {
									_this.$emit('checkFalse', false)
									callback(new Error(res.msg))
								}
							}
						}
					},
					trigger: ['change', 'blur'],
          source:"mulrow"
				},
			]
			// 校验最大行
			let checkMaxRow = _this.getCheckMaxRow ? [
				{
					validator: (rule, value, callback) => {
						let scrollHeight = _this.$refs.rootDiv.$el.getElementsByClassName('el-textarea__inner')[0].scrollHeight;
						let lineHeight = _this.difFontSize ? 21*1.5 : 13*1.5;
						let curRows = Math.round((scrollHeight - 10) / lineHeight)
						console.log('最大行数校验:', curRows)
						if (curRows > _this.rows) {
							callback(new Error('输入内容不能超过' + _this.rows + '行'))
						} else {
							callback()
						}
					},
					trigger: ['change', 'blur'],
          source:"mulrow"
				},
			] : []
			// 校验字节
			let checkLimitChar = _this.isLimitChar ? [
				{
					validator: (rule, value, callback) => {
						if (_this.curLength > _this.rows * _this.cols) {
							callback(new Error('输入内容不能超过' + _this.rows * _this.cols + '个字节(一个中文字符占两个字节)'))
						} else {
							callback()
						}
					},
					trigger: ['change', 'blur'],
          source:"mulrow"
				}
			] : []
      // 清除上次校验的问题
			this.root.$refs['modelForm'].clearValidate([prop]);
			//合并交易下必填校验
			let curProp = [...checkCode, ...checkMaxRow, ...checkLimitChar]
      if(this.root.rules[prop] && this.root.rules[prop].length){
        let oldProp = this.root.rules[prop].filter(item=>!item.source && (item.hasOwnProperty("required") || item.hasOwnProperty("extends")))
        curProp = [...oldProp,...curProp];
        this.$set(this.root.rules, prop, curProp)
      }else{
        this.$set(this.root.rules, prop, curProp)
      }
			console.log('校验规则rules:', this.root.rules, prop)
		},
		initValidCallback () {
			this.$nextTick(() => {
				if (this.isCheckInCompontent) {
					let totalLen = this.cols * this.rows
					this.isCheckMulRowInput(this, this.charmod, totalLen, {
						isRequired: this.isRequired,
						isEn: this.isEn
					})
				}
        this.setWangEditor()
			})
    },
    viewClick(){
      this.onFocus()
      this.$refs.rootDiv.focus()
    },
    getCharWidth() {
      // if (window['COU_FONT' + (this.cols)]) {
      //   let textAreaWidth = window['COU_FONT' + (this.cols)]
      //   return textAreaWidth
      // }
			let div = document.createElement('span')
			div.innerHTML = this.difFontSize ? `<div class="viewFitText viewPureText" style="padding: 0!important;font-size: 21px!important;">${'M'.repeat(this.cols)}</div>` : `<div class="viewFitText viewPureText" style="padding: 0!important;font-size: 13px!important;">${'M'.repeat(this.cols)}</div>`
      document.body.appendChild(div)
      let rect = div.children[0].getBoundingClientRect()
      let width = rect.width
      let textAreaWidth = width
      document.body.removeChild(div)
      window['COU_FONT' + (this.cols)] = textAreaWidth
      return textAreaWidth
		},
		// 处理简式修改页面显示宋体
		getCharWidthCn () {
			return 170 * 13 / 18.6
		},
    setWangEditor() {
			this.$nextTick(() => {
				let charWidth = this.isShowFontNoSameWidth ? this.getCharWidthCn() + 'mm' : this.getCharWidth() + 'px'
				let element = this.$refs.rootDiv.$el.getElementsByClassName('el-textarea__inner')
				let viewBox = this.$el.querySelector('.viewMulRow')
				if (element && element.length) {
					element = element[0]
					element.style.padding = `5px calc(100% - 18px - ${charWidth}) 5px 10px`
					viewBox.style.padding = `5px calc(100% - 18px - ${charWidth}) 5px 10px`
				}
			})
    }
	},
  beforeUpdate() {
		this.setWangEditor()
  },
  watch: {
		isRequired () {
			console.log('监听isRequired')
			this.initValidCallback()
		},
		charmod () {
			console.log('监听charmod')
			this.initValidCallback()
    },
    isEn () {
			console.log('监听isEn')
			this.initValidCallback()
    },
    model(newVal,oldVal){
      if(!this.focused){
        this.colorText = this.filterChar(newVal)
      }
    },
    disabled(newVal) {
      if (newVal) {
        this.resetValidate()
      }
    }
  },
}
</script>

<style>
.viewFitText {
  width: fit-content!important;
  position: absolute;
  visibility: hidden;
}
.viewPureText {
  padding: 5px 15px 5px 10px;
  line-height: 1.5em;
  font-family: 'Courier New';
  overflow-wrap: break-word;
  overflow-y: scroll;
  height: 100%;
  font-size: 13px;
}
</style>
<style lang="less" scoped>
.viewMulRow{
	position: absolute;
	top: 1px;
	left: 1px;
	width: calc(100% - 2px);
	height: calc(100% - 2px);
	padding: 5px 15px 5px 10px;
	line-height: 1.5em;
	font-family: '宋体';
	overflow-wrap: break-word;
	overflow-y: auto;
}
span.mul_row_text_error_tip{
	color:red !important;
	font-size: 13px;
	font-weight: bolder;
	font-family: 'Courier New'!important;
	text-decoration: underline;
}
.is-show-word-limit {
	.viewMulRowScroll {
		overflow-y: scroll;
		font-family: 'Courier New'!important;
		font-size: 13px!important;
		white-space: break-spaces;
	}
	/deep/ .el-textarea__inner {
    font-size: 13px!important;
    font-family: 'Courier New';
		overflow-y: scroll;
		white-space: break-spaces;
    &::placeholder {
      font-size: 13px!important;
    }
  }
  /deep/ .el-input__count {
    position: absolute;
    right: 14px;
    bottom: 4px;
    z-index: 10;
	}
}
.is-show-wordSize-limit{
	.viewMulRowScroll {
		overflow-y: scroll;
		font-family: 'Courier New'!important;
		font-size: 21px!important;
		white-space: break-spaces;
	}
	/deep/ .el-textarea__inner {
    font-size: 21px!important;
    font-family: 'Courier New';
		overflow-y: scroll;
		white-space: break-spaces;
    &::placeholder {
      font-size: 21px!important;
    }
  }
  /deep/ .el-input__count {
    position: absolute;
    right: 14px;
    bottom: 4px;
    z-index: 10;
	}
}
.no-view-font-same-width {
	.viewMulRowScroll {
		font-family: '宋体'!important;
	}
	/deep/ .el-textarea__inner {
    font-family: '宋体'!important;
  }
}
.cus-input-count {
	position: absolute;
	right: 10px;
	bottom: 5px;
	z-index: 10;
	height: 16px;
	line-height: 16px;
	color: #939099;
}
</style>