<!--
 * @Description: 用户画像渲染之标签组件
 * @Author: wenjing
 * @Date: 2023-06-15 11:31:00
-->
<template>
  <div ref="uprofilePanel" class="tag-info-body">
		<div ref="exportPanel" class="export-panel">
			<div :style="panelSize">
				<div v-for="(tag, tagIndex) in tagSet.tagList" :key="tagIndex"
					@mouseenter="handleShowIcon(tagIndex, true)" @mouseleave="handleShowIcon(tagIndex, false)">
					<div class="tag-name" :style="tagNameStyle(tag)"
					  @mouseenter="handleSetTarget('text', true)" @mouseleave="handleSetTarget('text', false)">
						{{ filterTagText(tag) }}
					</div>
					<img class="tag-icon" :style="iconStyle(tag)" :src="tagIconPath(tag)" 
						@mouseenter="handleSetTarget('icon', true)" @mouseleave="handleSetTarget('icon', false)"/>
					<!-- 标签单项的编辑和删除按钮 -->
					<div v-if="mode === 'edit' && tagIndex === curTagIndex" class="tag-icon-btn" :style="tagBtnStyle(tag)">
            <el-popover v-model="editPopupVisible" plaement="bottom-start" width="600" trigger="manual">
							<render-tag-form mode="edit" :visible="editPopupVisible" :tag-set-index="tagSetIndex" :tag-set="tagSet" 
								:tag-index="curTagIndex" @close="handleEditTagCancel" @confirm="handleEditTagConfirm" />
              <i class="el-icon-edit mouse-pointer" @click="handleEditTag" slot="reference"
								style="color:#397AFA; font-weight: bold;"></i>
            </el-popover>
            <mask-layer v-if="editPopupVisible"/>
            <delete-confirm-popup style="margin-left:5px; color:#FF4D4F; font-weight: bold" 
							:visible="delConfirmPopupVisible" @update:visible="handleDelTagConfirmPopupVisible"
							@confirm="handleDeleteTag(tagIndex)" />
					</div>
				</div>
				<img class="mouse-pointer" :style="imageStyle" :src="imagePath" @click="handleClickImage">
			</div>
			<!--图例-->
			<div class="legend" :style="legendStyle">
				<div v-for="(status, sIndex) in tagSet.statusList" :key="sIndex" class="legend-item mouse-pointer" 
				  :style="{marginRight:'20px'}" @click="handleToggleStatus(sIndex)">
					<div v-show="status.selected" :style="legendBulletStyle(status)" class="legend-bullet"></div>
					<div v-show="status.selected" :style="legendTextStyle">&ensp;{{ status.name }}</div>
				</div>
			</div>
		</div>
		<!--导出按钮-->
		<div v-show="mode === 'dynamic'" class="export-btn" :style="'right:' + offsetX + 'px;'">
			<el-tooltip class="item" effect="dark" :content="exportBtn.btnName" placement="top">
				<el-button v-if="exportBtn && exportBtn.selected" icon="el-icon-download" circle
					size="mini" @click="handleExportImg"></el-button>
			</el-tooltip>
		</div>
	</div>
</template>

<script>
import html2canvas from "html2canvas";
import MaskLayer from '../../utilcomp/masklayer/MaskLayer.vue';
import RenderTagForm from './RenderTagForm.vue';
import DeleteConfirmPopup from './DeleteConfirmPopup.vue';

export default {
	name: 'UserProfile',
	props: {
		// 当前展现的标签集补全
		tagSet: {
			type: Object,
			default: {}
		},

		tagSetIndex: {
			type: Number,
			default: -1
		},
		
    //画像显示模式
		mode: {
			type: String,			//'edit'-编辑模式，'dynamic'-显示动态画像（根据展现数据的status值显示不同图标）
		}
	},

	components: {
    'mask-layer': MaskLayer,
		'render-tag-form': RenderTagForm,
    'delete-confirm-popup': DeleteConfirmPopup,
  },
	
  data() {
		return {
			wRatio: 1.0,				//元素显示的宽度比例
			hRatio: 1.0,				//元素显示的宽度比例
			offsetX: 0,					//元素显示的X偏移量
			offsetY: 0,					//元素显示的Y偏移量

			curStatus: 0,				//编辑模式下使用，保存当前显示的TagStatusList的索引
      imgExportUrl: '',		//导出画像图像时使用

			editPopupVisible: false,        //是否显示编辑标签表单弹窗
      delConfirmPopupVisible: false,  //是否显示编辑标签表单弹窗
			curTagIndex: -1,
			curTarget: ''
    }
  },

	computed: {
    panelSize() {
			let width = Math.floor(this.tagSet.width * this.wRatio);
			let height = Math.floor(this.tagSet.height * this.hRatio);
			return { width: width + 'px',	height: height + 'px'};
    },

		imageStyle() {
			let width = Math.floor(this.tagSet.width * this.wRatio);
			let height = Math.floor(this.tagSet.height * this.hRatio);
			let style = "object-fit:fill; width:" + width + "px; height:" + height + "px;" +
				"margin-left:" + this.offsetX + "px; margin-top:" + this.offsetY + "px;"
			return (this.mode === 'edit') ? style + "border: dashed 1px lightgrey;" : style;
		},

		imagePath() {
			return this.commonUtil.fillUrlArgments(
				this.commonUrl.URL_DOWNLOAD_AUP_IMAGE, this.tagSet.key, this.tagSet.imageFile);
		},

		tagNameStyle() {
			return function(tag) {
				let left = tag.pos[2] * this.wRatio;
				let top = tag.pos[3] * this.hRatio;
				let color = this.calcTagNameColor(tag);
				let fontSize = 16 * this.wRatio;
				return { 
					'left': (this.offsetX + left) + 'px', 
					'top': (this.offsetY + top) + 'px', 
					'color': color,
					'font-size': fontSize + 'px'
				};
			}
		},

		iconStyle() {
			return function(tag) {
				let left = tag.pos[0] * this.wRatio;
				let top = tag.pos[1] * this.hRatio;
				return { 
					width: tag.iconWidth * this.wRatio + 'px', 
					height: tag.iconHeight * this.hRatio + 'px', 
					left: (this.offsetX + left) + 'px', 
					top: (this.offsetY + top) + 'px' 
				};
			}
		},

		tagIconPath() {
			return function(tag) {
				let iconFile = this.calcTagIconFile(tag);
				let url = this.commonUtil.fillUrlArgments(
					this.commonUrl.URL_DOWNLOAD_AUP_IMAGE, this.tagSet.key, iconFile);
				return url;
			}
		},
		
		tagBtnStyle() {
			return function(tag) {
				let left = tag.pos[(this.curTarget === 'text') ? 2 : 0] * this.wRatio;
				let top = tag.pos[(this.curTarget === 'text') ? 3 : 1] * this.hRatio;
				let width = ((this.curTarget === 'text') ? 50 : tag.iconWidth) * this.wRatio ;
				let height = ((this.curTarget === 'text') ? 22 : tag.iconHeight) * this.hRatio ;
				
				return { 
					width: width + 'px', 
					height: height + 'px', 
					left: (this.offsetX + left) + 'px', 
					top: (this.offsetY + top) + 'px' 
				};
			}
		},

		legendStyle() {
			return "marginTop:" + (20 * this.hRatio) +"px; marginLeft:" + this.offsetX + "px";
		},

    legendBulletStyle() {
      return function(status) {
				return {
					width: (8 * this.wRatio) + "px",
					height: (8 * this.hRatio) + "px",
					backgroundColor: status.color
				};
			}
    },
		
		legendTextStyle() {
			return "font-size:" + (16 * this.wRatio) + 'px'
		},
    
		exportBtn() {
			for (let btn of this.tagSet.btnList) {
				if (btn.action === 'EXPORT') {
					return btn;
				}
			}
			return null;
		}
	},

	methods: {
		initDisplayParams() {
			const rect = this.$refs.uprofilePanel.getBoundingClientRect();
			let upWidth = (rect.width > 0)	? rect.width : this.tagSet.width;
			let upHeight = (rect.height > 0) ? rect.height : this.tagSet.height;
			
			if (this.tagSet.width >= upWidth) {
				this.wRatio = upWidth / this.tagSet.width;
				this.offsetX = 0;
			} else {
				this.wRatio = 1.0;
				this.offsetX = Math.floor((upWidth - this.tagSet.width) / 2);
			}

			this.hRatio = (this.tagSet.height >= upHeight) 
				? upHeight / this.tagSet.height :	this.hRatio = 1.0;
			this.offsetY = 0;
		},

		calcTagNameColor(tag) {
			if (this.mode === 'edit') {
				return this.tagSet.statusList[this.curStatus].color;
			} else {
				switch (tag.status) {
					case '_NORMAL_':
						return this.tagSet.statusList[0].color;
					case '_LEVEL2_':
						return this.tagSet.statusList[1].color;
					case '_LEVEL3_':
						return this.tagSet.statusList[2].color;
					case '_LEVEL4_':
						return this.tagSet.statusList[3].color;
					default:
						return "";
				}
			}
		},

		filterTagText(tag) {
			let name = tag.tag;
			if (this.mode === 'edit') {
				return (name && name.charAt(0) != '_') ? name : '';
			}

			if (name && name.charAt(0) === '_') {
				return '';
			}
			let value = tag.value.split('\|')[0];
			return (value) ? value : name;
		},

		calcTagIconFile(tag) {
			if (this.mode === 'edit') {
				return tag.statusIconList[this.curStatus];
			} else {
				let status = tag.value.split('\|')[1];
				switch (status) {
					case '_NORMAL_':
						return tag.statusIconList[0];
					case '_LEVEL2_':
						return tag.statusIconList[1];
					case '_LEVEL3_':
						return tag.statusIconList[2];
					case '_LEVEL4_':
						return tag.statusIconList[3];
					default:
						return '';
				}
			}
		},

    //生成导出用图片连接
    async generateExportUrl() {
      let name = this.$refs.exportPanel;
      await html2canvas(name).then(canvas => {
        // 转成图片，生成图片地址
        this.imgExportUrl = canvas.toDataURL("image/png");
      });
    },

		clearCurrentData() {
      this.curTagIndex = -1;
			this.curTarget = '';
    },

		handleClickImage() {
			if (this.mode !== 'edit') return;
			this.$emit("click-image", this.tagSet);
		},

		/* 以下为‘编辑、删除标签’处理的事件方法 */
		handleShowIcon(curTagIndex, flag) {
      if (this.delConfirmPopupVisible || this.editPopupVisible) return;
			
      if (flag) {
				this.curTagIndex = curTagIndex;
      } else {
        this.clearCurrentData();
      }
    },

		handleSetTarget(target, flag) {
      if (this.delConfirmPopupVisible || this.editPopupVisible) return;
			
      if (flag) {
				this.curTarget = target;
      }
    },

		handleEditTag() {
			if (this.mode !== 'edit') return;
			this.editPopupVisible = true;
		},

		handleEditTagCancel() {
      this.editPopupVisible = false;
      this.clearCurrentData();
    },

    handleEditTagConfirm(tagSet, tagSetIndex) {
			this.editPopupVisible = false;
			this.clearCurrentData();
			this.$emit("refresh", tagSet, tagSetIndex);
    },

    handleDelTagConfirmPopupVisible(val) {
      this.delConfirmPopupVisible = val;
      if (!this.delConfirmPopupVisible) {
        this.clearCurrentData();
      }
    },

		handleDeleteTag(tagIndex) {
			let requestData = {
				url: this.commonUrl.URL_REMOVE_RENDER_TAG,
        method: 'DELETE',
				contentType: this.commonConst.CNTYPE_URLENCODED,
        param: {tagSetKey: this.tagSet.key, tagIndex: tagIndex}
      };
      this.vueRequest(requestData).then(result => {
        if (result == null) return;
				this.$emit("refresh", result.data, this.tagSetIndex);
      })
    },

		handleToggleStatus(index) {
			this.curStatus = index;
		},

		handleExportImg() {
      html2canvas(this.$refs.exportPanel).then(canvas => {
        // 转成图片，生成图片地址
        this.imgExportUrl = canvas.toDataURL("image/png");

				let eleLink = document.createElement("a");
				eleLink.href = this.imgExportUrl;
				eleLink.download = this.tagSet.subjectName;
				document.body.appendChild(eleLink);
				eleLink.click();
				document.body.removeChild(eleLink);
      });
    },
	},
	
	watch: {
		tagSet(_newVal) {
      this.initDisplayParams();
    }
  },

  mounted() {
		this.initDisplayParams();
	}
}
</script>

<style scoped>
.tag-info-body {
	padding-bottom: 10px;
	position: relative;
	width: 100%;
}
.export-panel {
	padding-bottom: 0px;
	border: 0px solid red;
}

.tag-name {
	position: absolute;
	z-index: 40;
	text-align: left;
}
.tag-icon {
	position: absolute;
	z-index: 30;
	left: 0;
	top: 0;
}
.tag-icon-btn {
	position: absolute;
	z-index: 50;
	left: 0;
	top: 0;
  display: flex;
  text-align: center;
	align-items: center;
	justify-content: center;
	background: whitesmoke;
	opacity: 1;
  border: solid lightgray 1px;
	border-radius: 4px;
}

.legend {
	display: flex;
}
.legend-item {
	display: flex;
	align-items: center
}
.legend-bullet {
	border-radius: 100%;
	margin-right: 5px;
}

.export-btn {
	position: absolute;
	z-index: 40;
	right: 0px;
	bottom: 8px;
}
</style>
