import $api from '@/api'
import store from '@/store'
import { app } from '@/boot-app.js'
/**
 * 校验blob授权是否过期
 * */
function checkSas(sasTs) {
	let curTimestamp = (new Date()).getTime()
	if (curTimestamp >= sasTs) {
		return true
	} else {
		return false
	}
}
export default {
	// vueScroll全局配置工具;
	vueScrollOpt: {
		mode: 'native',
		// 设置 vuescroll的大小类型， 可选的有percent, number.
		// 设置为percent会把 vuescroll 的 height 和 width 设置成100%,
		// 设置成number的话 vuescroll 会自动计算父元素的大小，并将height和width设置成对应的数值。
		// 提示:如果父元素的尺寸为百分比大小时建议设置成number,如果父元素大小为一个固定的px的值,那么设置为百分比比较合适一些。
		sizeStrategy: 'percent',
		// 是否开启监听 dom resize
		detectResize: false,
		// 下拉刷新相关(slide mode)
		pullRefresh: {
			enable: false,
			// 下拉刷新的提示
			tips: {
				deactive: 'Pull to Refresh',
				active: 'Release to Refresh',
				start: 'Refreshing...',
				beforeDeactive: 'Refresh Successfully!'
			}
		},
		// 上推加载相关
		pushLoad: {
			enable: false,
			tips: {
				deactive: 'Push to Load',
				active: 'Release to Load',
				start: 'Loading...',
				beforeDeactive: 'Load Successfully!'
			},
			auto: false,
			autoLoadDistance: 0
		},
		paging: false,
		zooming: true,
		// 快照
		snapping: {
			enable: false,
			width: 100,
			height: 100
		},
		/* shipped scroll options */
		scroller: {
			/*
			  允许滚动出边界
			  true 或者 false 或者一个数组指定哪个方向可以超出边界，可选项分别是：
			  ['top','bottom','left','right']
			*/
			bouncing: true,
			/** Enable locking to the main axis if user moves only slightly on one of them at start */
			locking: true,
			/** 最小缩放级别 */
			minZoom: 0.5,
			/** 最大缩放级别 */
			maxZoom: 3,
			/** 滚动速度的倍速 **/
			speedMultiplier: 1,
			/** 到达边界时应用于减速的改变量  **/
			penetrationDeceleration: 0.03,
			/** 到达边界时应用于加速的改变量  **/
			penetrationAcceleration: 0.08,
			/** Whether call e.preventDefault event when sliding the content or not */
			preventDefault: true,
			/** Whether call preventDefault when (mouse/touch)move */
			preventDefaultOnMove: true
		},
		scrollPanel: {
			// 组件加载完后的初始滚动量
			initialScrollY: false,
			initialScrollX: false,
			// 是否禁止x或y方向上的滚动
			scrollingX: false,
			scrollingY: true,
			speed: 300,
			// 滚动动画
			easing: undefined,
			// 是否有一个padding样式，样式的大小应该和rail/bar的大小是一样。可以用来阻止内容被滚动条遮住一部分
			padding: false,
			// 有时候原声滚动条可能在左侧,
			// 请查看 https://github.com/YvesCoding/vuescroll/issues/64
			verticalNativeBarPos: 'right'
		},
		// 滚动条滚动的地方
		rail: {
			background: '#000',
			opacity: 0,
			border: 'none',
			/** Rail's size(Height/Width) , default -> 6px */
			size: '6px',
			/** Specify rail's border-radius, or the border-radius of rail and bar will be equal to the rail's size. default -> false **/
			specifyBorderRadius: false,
			/** Rail the distance from the two ends of the X axis and Y axis. **/
			gutterOfEnds: null,
			/** Rail the distance from the side of container. **/
			gutterOfSide: '0px',
			/** Whether to keep rail show or not, default -> false, event content height is not enough */
			keepShow: false
		},
		bar: {
			/** 当不做任何操作时滚动条自动消失的时间 */
			showDelay: 1000,
			/** Specify bar's border-radius, or the border-radius of rail and bar will be equal to the rail's size. default -> false **/
			specifyBorderRadius: false,
			/** 是否只在滚动的时候现实滚动条 */
			onlyShowBarOnScroll: false,
			/** 是否保持显示 */
			keepShow: false,
			/** 滚动条颜色, default -> #00a650 */
			background: 'rgb(58,58,58)',
			/** 滚动条透明度, default -> 1  */
			opacity: 1,
			/** Styles when you hover scrollbar, it will merge into the current style */
			hoverStyle: false
		},
		scrollButton: {
			enable: false,
			background: 'rgb(3, 185, 118)',
			opacity: 1,
			step: 180,
			mousedownStep: 30
		}
	},

	// wangEditor菜单配置
	wangEditorMenu: [
		'head', // 标题
		'bold', // 粗体
		'fontSize', // 字号
		'fontName', // 字体
		'italic', // 斜体
		'underline', // 下划线
		'strikeThrough', // 删除线
		'foreColor', // 文字颜色
		'link', // 插入链接
		'video', //插入视频
		'justify', // 对齐方式
		'image', // 插入图片
		'table', // 表格
		'undo', // 撤销
	],
	wangEditorMenuSimple: [
		'head', // 标题
		'bold', // 粗体
		'fontSize', // 字号
		'fontName', // 字体
		'italic', // 斜体
		'underline', // 下划线
		'strikeThrough', // 删除线
		'foreColor', // 文字颜色
		'justify', // 对齐方式
		'table', // 表格
	],
	// 生成随机UUID工具
	randomId: function() {
		return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
	},
	// 生成随机UUID工具
	guid: function() {
		return (this.randomId() + this.randomId() + '-' + this.randomId() + '-' + this.randomId() + '-' + this
			.randomId() +
			'-' + this.randomId() + this.randomId() + this.randomId())
	},

	// 正则判断是否为标准的URL格式
	isURL(url) {
		const strRegex = '^((https|http|ftp)://)?' //(https或http或ftp):// 可有可无
			+
			'(([\\w_!~*\'()\\.&=+$%-]+: )?[\\w_!~*\'()\\.&=+$%-]+@)?' //ftp的user@ 可有可无
			+
			'(([0-9]{1,3}\\.){3}[0-9]{1,3}' // IP形式的URL- 3位数字.3位数字.3位数字.3位数字
			+
			'|' // 允许IP和DOMAIN（域名）
			+
			'(localhost)|' //匹配localhost
			+
			'([\\w_!~*\'()-]+\\.)*' // 域名- 至少一个[英文或数字_!~*\'()-]加上.
			+
			'\\w+\\.' // 一级域名 -英文或数字 加上.
			+
			'[a-zA-Z]{1,6})' // 顶级域名- 1-6位英文
			+
			'(:[0-9]{1,5})?' // 端口- :80 ,1-5位数字
			+
			'((/?)|' // url无参数结尾 - 斜杆或这没有
			+
			'(/[\\w_!~*\'()\\.;?:@&=+$,%#-]+)+/?)$'; //请求参数结尾- 英文或数字和[]内的各种字符
		const re = new RegExp(strRegex, 'i'); // 大小写不敏感
		if (re.test(encodeURI(url))) {
			return true;
		}
		return false;
	},

	// 数据结构转换工具
	jsonTransform(obj) {
		let arr = []
		console.log(obj)
		if (obj.datas.length) {
			let item = {}
			let attrLength = obj.keys.length
			for (let i = 0; i < obj.datas.length; i++) {
				for (let j = 0; j < attrLength; j++) {
					item[obj.keys[j]] = obj.datas[i][j]
				}
				arr.push(item)
				item = {}
			}
		}
		return arr || null
	},

	/**
	 *对Date的扩展，将 Date 转化为指定格式的String
	 *月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符，
	 *年(y)可以用 1-4 个占位符，毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
	 *例子：
	 *(new Date()).Format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423
	 *(new Date()).Format("yyyy-M-d h:m:s.S")      ==> 2006-7-2 8:9:4.18
	 */
	formatTime(timestamp, fmt = 'yyyy-MM-dd hh:mm:ss') {
		let d = new Date()
		d.setTime(timestamp)
		var o = {
			'M+': d.getMonth() + 1, //月份
			'd+': d.getDate(), //日
			'h+': d.getHours(), //小时
			'm+': d.getMinutes(), //分
			's+': d.getSeconds(), //秒
			'q+': Math.floor((d.getMonth() + 3) / 3), //季度
			'S': d.getMilliseconds() //毫秒
		}
		if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (d.getFullYear() + '').substr(4 - RegExp.$1.length))
		for (var k in o)
			if (new RegExp('(' + k + ')').test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : ((
				'00' + o[
					k]).substr(('' + o[k]).length)))
		return fmt
	},

	/**
	 * 字节格式转换
	 * @param {any} bytes
	 */
	bytesToSize(bytes) {
		if (bytes === 0) return '0 B';
		let k = 1024,
			sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
			i = Math.floor(Math.log(bytes) / Math.log(k));
		return (bytes / Math.pow(k, i)).toFixed(2) + ' ' + sizes[i];
	},

	/* 采用原生Xhr来发送HTTP请求 避免携带token访问blob报错 */
	getFile(url) {
		return new Promise((resolve, reject) => {
			var xhr = new XMLHttpRequest();
			var formData = new FormData();
			xhr.open('get', url); //url填写后台的接口地址，如果是post，在formData append参数（参考原文地址）
			// xhr.responseType = 'arraybuffer';
			xhr.onload = function(e) {
				resolve(e.currentTarget.response)
			};
			xhr.send(formData);
		})
	},


	/**
	 * 获取blob授权
	 * @param {type,data} param
	 *  type:'file/blobR/blobRW',
	 *  data: 对应的API参数
	 */
	getSas(param) {
		return new Promise((r, j) => {
			switch (param.type) {
				case 'file': //单文件授权
					if (!store.state.fileSas || checkSas(store.state.fileSas.timeout)) {
						$api.blob.urlSasR({
							params: param.data
						}).then(
							(res) => {
								if (res.error == null) {
									r(res.result.data)
								} else {
									j(500)
								}
							},
							(err) => {
								j(500)
							}
						)
					} else {
						r(store.state.fileSas)
					}
					break
				case 'blobR': //容器只读权限
					if (!store.state.blobR || checkSas(store.state.blobR.timeout)) {
						$api.blob.blobSasR(param.data).then(
							(res) => {
								if (res.error == null) {
									//store.commit('setBlobR')
									r(res.result.data)
								} else {
									j(500)
								}
							},
							(err) => {
								j(500)
							}
						)
					} else {
						r(store.state.blobR)
					}
					break
				case 'blobRW':
					if (!store.state.blobRW || checkSas(store.state.blobRW.timeout)) {
						$api.blob.blobSasRCW(param.data).then(
							(res) => {
								if (res.error == null) {
									store.commit('setBlobRW', res.result.data)
									r(res.result.data)
								} else {
									j(500)
								}
							},
							(err) => {
								j(500)
							}
						)
					} else {
						r(store.state.blobRW)
					}
					break
				default:
					j('getSas() 参数错误:type')
			}
		})
	},
	
	getBlobHost(){
		let s = store.state.user.userProfile.blob_uri || store.state.user.studentProfile.blob_uri || 'https://teammodelstorage.blob.core.chinacloudapi.cn/hbcn'
		return s.split(s.substring(s.lastIndexOf('/')))[0]
	},

	/**
	 * 获取个人容器授权
	 */
	getPrivateSas(code) {
		return new Promise((r, j) => {
			if (!store.state.user.schoolProfile.blob_sas) {
				$api.blob.blobSasRCW({
					name: code || store.state.userInfo.TEAMModelId,
					role: 'school'
				}).then(
					(res) => {
						if (res.error == null) {
							res.sas = '?' + res.sas
							r(res)
						} else {
							j(500)
						}
					},
					(err) => {
						j(500)
					}
				)
			} else {
				r({
					sas:'?' + store.state.user.userProfile.blob_sas,
					name:code || store.state.userInfo.TEAMModelId,
					url:this.getBlobHost()
				})
			}
		})
	},
	/**
	 * 获取学校容器授权
	 */
	getSchoolSas(code) {
		return new Promise((r, j) => {
			if (!store.state.user.schoolProfile.blob_sas) {
				$api.blob.blobSasRCW({
					name: code || store.state.userInfo.schoolCode,
					role: 'school'
				}).then(
					(res) => {
						if (res.error == null) {
							res.sas = '?' + res.sas
							r(res)
						} else {
							j(500)
						}
					},
					(err) => {
						j(500)
					}
				)
			} else {
				r({
					sas:'?' + store.state.user.schoolProfile.blob_sas,
					name:code || store.state.userInfo.schoolCode,
					url:this.getBlobHost()
				})
			}
		})
	},
	/**
	 * 获取单个文件授权
	 */
	getFileSas(param) {
		return new Promise((r, j) => {
			$api.blob.urlSasR({
				url: param
			}).then(
				(res) => {
					if (res.error == null) {
						//store.commit('setBlobRW', res.result.data)
						r(res)
					} else {
						j(500)
					}
				},
				(err) => {
					j(500)
				}
			)
		})
	},

	/* 获取视频第一帧 */
	getVideoBase64(url) {
		return new Promise(function(resolve, reject) {
			let dataURL = '';
			let video = document.createElement("video");
			video.setAttribute('crossOrigin', 'anonymous'); //处理跨域
			video.setAttribute('src', url);
			video.setAttribute('preload', 'auto');
			video.setAttribute('width', 150);
			video.setAttribute('height', 90);
			video.addEventListener('loadeddata', function() {
				let canvas = document.createElement("canvas"),
					width = video.width, //canvas的尺寸和图片一样
					height = video.height;
				canvas.width = width;
				canvas.height = height;
				canvas.getContext("2d").drawImage(video, 0, 0, width, height); //绘制canvas
				dataURL = canvas.toDataURL('image/jpeg'); //转换为base64
				// 画播放按钮
				var img = new Image()
				img.src = require('@/assets/icon/icon_play.png')
				img.setAttribute('crossOrigin', 'anonymous');
				img.onload = function() {
					//画图
					canvas.getContext("2d").drawImage(img, 55, 25, 40, 40);
					var data = canvas.toDataURL('image/jpeg');
					resolve(data);

				}
			});
		})
	},

	/* 上传视频到BLob */
	async doUploadVideo(vm, file, editor) {
		vm.$Spin.show({
			render: (h) => {
				return h('div', {
					'class': 'my-spin',
					style: {
						background: '#000',
						padding: '20px',
						borderRadius: '5px',
						color: '#fff'
					}
				}, [
					h('Icon', {
						'class': 'demo-spin-icon-load',
						props: {
							type: 'ios-loading',
							size: 18
						}
					}),
					h('div', app.$t('utils.uploadLoading'))
				])
			}
		});
		const blobTool = require('./blobTool.js')
		const isSchool = vm.$parent.exerciseScope ? vm.$parent.exerciseScope === 1 : vm.exerciseScope === 1
		const sasData = isSchool ? await this.getSchoolSas() : await this.getPrivateSas()

		const scope = isSchool ? 'school' : 'private'
		const blobToolClass = blobTool.default
		//初始化Blob
		let containerClient = new blobToolClass(sasData.url, sasData.name, sasData.sas, scope)
		try {
			let id = vm.curId || vm.$parent.curId
			// 上传文件
			let blobFile = await containerClient.upload(file, 'item/' + id)
			// 获取blob链接以及视频封面截图
			const fileSas = await this.getFileSas(blobFile.url)
			const fileBlobUrl = fileSas.url
			const posterBase64 = await this.getVideoBase64(fileBlobUrl)
			editor.selection.getSelectionStartElem().elems[0].innerHTML += '<span><span>&nbsp;</span><video src=' +
				fileBlobUrl + ' class="richText-video" width="300" preload controls="controls"></video><span>&nbsp;</span></span>'
			editor.change.emit()
			vm.$EventBus.$emit('noSave', {
				path: blobFile.blob,
				size: blobFile.size,
				scope: scope
			})
			vm.$Spin.hide();
		} catch (e) {
			vm.$Message.error(e.spaceError)
			vm.$Spin.hide();
		}
	},

	/* 上传视频到BLob */
	async doUploadAudio(vm, file, editor) {
		console.log(vm)
		vm.$Spin.show({
			render: (h) => {
				return h('div', {
					'class': 'my-spin',
					style: {
						background: '#000',
						padding: '20px',
						borderRadius: '5px',
						color: '#fff'
					}
				}, [
					h('Icon', {
						'class': 'demo-spin-icon-load',
						props: {
							type: 'ios-loading',
							size: 18
						}
					}),
					h('div', app.$t('utils.uploadLoading'))
				])
			}
		});
		const blobTool = require('./blobTool.js')
		const isSchool = vm.$parent.exerciseScope ? vm.$parent.exerciseScope === 1 : vm.exerciseScope === 1
		const sasData = isSchool ? await this.getSchoolSas() : await this.getPrivateSas()
		const scope = isSchool ? 'school' : 'private'
		const blobToolClass = blobTool.default
		//初始化Blob
		let containerClient = new blobToolClass(sasData.url, sasData.name, sasData.sas, scope)
		try {
			let id = vm.curId || vm.$parent.curId
			// 上传文件
			let blobFile = await containerClient.upload(file, 'item/' + id)
			console.log(blobFile)
			// 获取blob链接以及视频封面截图
			const fileSas = await this.getFileSas(blobFile.url)
			const fileBlobUrl = fileSas.url
			editor.selection.getSelectionStartElem().elems[0].innerHTML += `<span><span>&nbsp;&nbsp;</span><span class="richText-audio" contenteditable="false" >
					<span class="audio-info">
						<i class="ivu-icon ivu-icon-ios-musical-notes" style="font-size: 24px;margin:0 10px"></i>
						<span class="audio-name">${ file.name }</span>
					</span>
					<audio src="${ fileBlobUrl }"  id="audio" controls="controls" controlsList="nodownload"></audio>
				</span><span>&nbsp;</span></span>`
			editor.change.emit()
			vm.$EventBus.$emit('noSave', {
				path: blobFile.blob,
				size: blobFile.size,
				scope: scope
			})
			vm.$Spin.hide();
		} catch (e) {
			vm.$Message.error(e.spaceError)
			vm.$Spin.hide();
		}
	},
	/* 删除未保存的BLOB多媒体文件 */
	async deleteNoSave(noSaveArr) {
		const blobTool = require('./blobTool.js')
		const schoolSas = await this.getSchoolSas()
		const privateSas = await this.getPrivateSas()
		const blobToolClass = blobTool.default
		let schoolBlobClient = new blobToolClass(schoolSas.url, schoolSas.name, schoolSas.sas, 'school')
		let privateBlobClient = new blobToolClass(privateSas.url, privateSas.name, privateSas.sas, 'private')
		let promiseArr = []
		for (let i = 0; i < noSaveArr.length; i++) {
			let item = noSaveArr[i]
			promiseArr.push(new Promise((r, j) => {
				let myClient = item.scope === 'school' ? schoolBlobClient : privateBlobClient
				myClient.deleteBlob(item.path, item.size).then(res => {
					r(200)
				}).catch(err => {
					j(err)
				})
			}))
		}
		Promise.all(promiseArr).then(result => {
			localStorage.setItem('noSave','[]')
		}).catch(err => {
			console.log(err)
		})

	},
	isEqual: function(x, y) {
		// If both x and y are null or undefined and exactly the same 
		if (x === y) {
			return true;
		}
		// If they are not strictly equal, they both need to be Objects 
		if (!(x instanceof Object) || !(y instanceof Object)) {
			return false;
		}
		//They must have the exact same prototype chain,the closest we can do is
		//test the constructor. 
		if (x.constructor !== y.constructor) {
			return false;
		}
		for (var p in x) {
			//Inherited properties were tested using x.constructor === y.constructor
			if (x.hasOwnProperty(p)) {
				// Allows comparing x[ p ] and y[ p ] when set to undefined 
				if (!y.hasOwnProperty(p)) {
					return false;
				}
				// If they have the same strict value or identity then they are equal 
				if (x[p] === y[p]) {
					continue;
				}
				// Numbers, Strings, Functions, Booleans must be strictly equal 
				if (typeof(x[p]) !== "object") {
					return false;
				}
				// Objects and Arrays must be tested recursively 
				if (!Object.equals(x[p], y[p])) {
					return false;
				}
			}
		}
		for (p in y) {
			// allows x[ p ] to be set to undefined 
			if (y.hasOwnProperty(p) && !x.hasOwnProperty(p)) {
				return false;
			}
		}
		return true;
	},
	/* 学情认知层次模块数据转换 */
	getLevelStuPercent(val, subjectIndex, index) {
		let result = []
		val.students.forEach(stu => {
			result.push([
				stu.name,
				stu.className,
				stu.no || '-',
				val.fScores[subjectIndex].value[index],
				stu.subjects[subjectIndex].fieldPoint[index],
				val.fScores[subjectIndex].value[index] == 0 ? 0 : (stu.subjects[subjectIndex].fieldPoint[index] / val.fScores[subjectIndex].value[index])
				.toFixed(2)
			])
		})
		return result
	},
	/* 学情认知层次年级班级得分率数据转换 */
	getLevelClassPercent(val, subjectIndex, index) {
		let result = []
		val.classes.forEach(classItem => {
			result.push(classItem.subjects[subjectIndex].field.map((score,index) => val.fieldwrong[subjectIndex].value[index][1] == 0 ? 0 : Number(score / val.fieldwrong[subjectIndex].value[index][1]) * 100)[index])
		})
		return result
	},
	/* 学情认知层次年级班级得分率数据转换 */
	getLevelPercent(val, subjectIndex) {
		let stuResult = {}
		let classResult = {}
		val.fieldName[subjectIndex].value.forEach((item, index) => {
			stuResult[item] = this.getLevelStuPercent(val, subjectIndex, index)
			classResult[item] = this.getLevelClassPercent(val, subjectIndex, index)
		})
		stuResult.grade = val.fieldAllPer[subjectIndex].value.map((score,index) => (val.fieldwrong[subjectIndex].value[index][1] == 0 ? 0 : Number(score / val.fieldwrong[subjectIndex].value[index][1]).toFixed(2)) * 100)
		stuResult.keys = val.knowKey
		classResult.keys = val.knowkey
		classResult.className = val.classes.map(i => i.className)
		let obj = {
			stuResult: stuResult,
			classResult: classResult
		}
		return obj
	},

	/* 学情知识点模块数据转换 */
	getKnowStuPercent(val, subjectIndex, index) {
		let result = []
		val.students.forEach(stu => {
			result.push([
				stu.name,
				stu.className,
				stu.no || '-',
				val.kScores[subjectIndex].value[index],
				stu.subjects[subjectIndex].point[index],
				val.kScores[subjectIndex].value[index] == 0 ? 0 : (stu.subjects[subjectIndex].point[index] / val.kScores[subjectIndex].value[index])
				.toFixed(2)
			])
		})
		return result
	},
	/* 学情知识点班级得分率数据转换 */
	getKnowClassPercent(val, subjectIndex, index) {
		let result = []
		val.classes.forEach(classItem => {
			// 取当前班级在每个知识点的得分 除以知识点的总分 得到每个班在该知识点的得分率 index=>知识点下标
			result.push(classItem.subjects[subjectIndex].point.map((score,pointIndex) => val.wrong[subjectIndex].value[pointIndex][1] == 0 ? 0 : Number(score / val.wrong[subjectIndex].value[pointIndex][1]) * 100)[index])
		})
		return result
	},
	/* 学情知识点年级班级得分率数据转换 */
	getKnowPercent(val, subjectIndex) {
		let stuResult = {}
		let classResult = {}
		val.knowName[subjectIndex].value.forEach((item, index) => {
			stuResult[item] = this.getKnowStuPercent(val, subjectIndex, index)
			classResult[item] = this.getKnowClassPercent(val, subjectIndex, index)
		})
		// 取当前年级在每个知识点的得分 除以知识点的总分 得到年级在该知识点的得分率
		stuResult.grade = val.knowAllper[subjectIndex].value.map((score,index) => val.wrong[subjectIndex].value[index][1] == 0 ? 0 : Number(score / val.wrong[subjectIndex].value[index][1]) * 100)
		stuResult.keys = val.knowKey
		classResult.keys = val.knowkey
		classResult.className = val.classes.map(i => i.className)
		let obj = {
			stuResult: stuResult,
			classResult: classResult
		}
		return obj
	},

}
