import {
	Component,
	ElementRef,
	EventEmitter,
	HostListener,
	Input,
	OnChanges,
	OnDestroy,
	OnInit,
	Output,
	ViewChild
} from '@angular/core';
import { Subject } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
import { EditorItem, HotZoneImg, HotZoneItem, HotZoneLabel, Label, MySprite, removeItemFromArr } from './Unit';
import TWEEN from '@tweenjs/tween.js';
import { getMinScale } from "../../play/Unit";
import { tar } from "compressing";


@Component({
	selector: 'app-custom-hot-zone',
	templateUrl: './custom-hot-zone.component.html',
	styleUrls: ['./custom-hot-zone.component.scss']
})
export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {


	@Input()
	imgItemArr = null;
	@Input()
	hotZoneItemArr = null;
	@Input()
	hotZoneArr = null;
	@Output()
	save = new EventEmitter();
	@ViewChild('canvas', { static: true }) canvas: ElementRef;
	@ViewChild('wrap', { static: true }) wrap: ElementRef;

	@Input()
	isHasRect = true;
	@Input()
	isHasPic = true;
	@Input()
	isHasText = true;
	@Input()
	hotZoneFontObj = {
		size: 50,
		name: 'BRLNSR_1',
		color: '#8f3758'
	}
	@Input()
	defaultItemType = 'rect';

	@Input()
	hotZoneImgSize = 190;

	saveDisabled = true;

	canvasWidth = 1280;
	canvasHeight = 720;
	canvasBaseW = 1280;
	// @HostListener('window:resize', ['$event'])
	canvasBaseH = 720;
	mapScale = 1;
	ctx;
	mx;
	my; // 点击坐标
	// 声音
	bgAudio = new Audio();
	images = new Map();
	animationId: any;


	// 资源
	// rawImages = new Map(res);
	winResizeEventStream = new Subject();
	canvasLeft;
	canvasTop;
	renderArr;
	imgArr = [];
	oldPos;
	radioValue;
	curItem;
	bg: MySprite;
	changeSizeFlag = false;
	changeTopSizeFlag = false;
	changeRightSizeFlag = false;

	constructor() {
	}

	_bgItem = null;

	get bgItem() {
		return this._bgItem;
	}

	@Input()
	set bgItem(v) {
		this._bgItem = v;

		this.init();
	}

	onResize(event) {
		this.winResizeEventStream.next();
	}


	ngOnInit() {

		this.initListener();

		// this.init();
		this.update();

	}

	ngOnDestroy() {
		window.cancelAnimationFrame(this.animationId);
	}


	ngOnChanges() {

	}


	onBackgroundUploadSuccess(e) {
		console.log('e: ', e);
		this.bgItem.url = e.url;
		this.refreshBackground();
	}

	onItemImgUploadSuccess(e, item) {
		item.pic_url = e.url;
		this.loadHotZonePic(item.pic, e.url);
	}

	onItemAudioUploadSuccess(e, item) {
		item.audio_url = e.url;
	}


	refreshBackground(callBack = null) {

		if (!this.bg) {
			this.bg = new MySprite(this.ctx);
			this.renderArr.push(this.bg);
		}

		const bg = this.bg;
		if (this.bgItem.url) {

			bg.load(this.bgItem.url).then(() => {
				const rate1 = this.canvasWidth / bg.width;
				const rate2 = this.canvasHeight / bg.height;

				const rate = Math.min(rate1, rate2);
				bg.setScaleXY(rate);


				bg.x = this.canvasWidth / 2;
				bg.y = this.canvasHeight / 2;

				if (callBack) {
					callBack();
				}
			});
		}

	}


	addBtnClick() {
		// this.imgArr.push({});
		// this.hotZoneArr.push({});

		const item = this.getHotZoneItem();
		this.hotZoneArr.push(item);

		this.refreshItem(item);

		this.refreshHotZoneId();

	}

	deleteBtnClick(index) {

		const item = this.hotZoneArr.splice(index, 1)[0];
		removeItemFromArr(this.renderArr, item.pic);
		removeItemFromArr(this.renderArr, item.textLabel);

		this.refreshHotZoneId();

	}

	onImgUploadSuccessByImg(e, img) {
		img.pic_url = e.url;
		this.refreshImage(img);
	}

	refreshImage(img) {

		this.hideAllLineDash();

		img.picItem = this.getPicItem(img);

		this.refreshImageId();

	}


	refreshHotZoneId() {
		for (let i = 0; i < this.hotZoneArr.length; i++) {
			this.hotZoneArr[i].index = i;

			if (this.hotZoneArr[i]) {
				this.hotZoneArr[i].title = 'item-' + (i + 1);

			}
		}
	}


	refreshImageId() {
		for (let i = 0; i < this.imgArr.length; i++) {
			this.imgArr[i].id = i;

			if (this.imgArr[i].picItem) {
				this.imgArr[i].picItem.text = 'Image-' + (i + 1);
			}
		}

	}

	getHotZoneItem(saveData = null) {


		const itemW = 200;
		const itemH = 200;
		const item = new HotZoneItem(this.ctx);
		item.setSize(itemW, itemH);
		item.anchorX = 0.5;
		item.anchorY = 0.5;

		item.x = this.canvasWidth / 2;
		item.y = this.canvasHeight / 2;

		item.itemType = this.defaultItemType;

		if (saveData) {

			const saveRect = saveData.rect;
			item.scaleX = saveRect.width / item.width;
			item.scaleY = saveRect.height / item.height;
			item.x = saveRect.x + saveRect.width / 2;
			item.y = saveRect.y + saveRect.height / 2;

		}

		item.showLineDash();

		const pic = new HotZoneImg(this.ctx);
		pic.visible = false;
		item['pic'] = pic;
		if (saveData && saveData.pic_url) {
			this.loadHotZonePic(pic, saveData.pic_url);
		}
		pic.x = item.x;
		pic.y = item.y;
		this.renderArr.push(pic);

		const textLabel = new HotZoneLabel(this.ctx);
		textLabel.fontSize = this.hotZoneFontObj.size;
		textLabel.fontName = this.hotZoneFontObj.name;
		textLabel.fontColor = this.hotZoneFontObj.color;
		textLabel.textAlign = 'center';
		// textLabel.setOutline();
		// console.log('saveData:', saveData);
		item['textLabel'] = textLabel;
		textLabel.setScaleXY(this.mapScale);
		if (saveData && saveData.text) {
			textLabel.text = saveData.text;
			textLabel.refreshSize();
		}
		textLabel.x = item.x;
		textLabel.y = item.y;
		this.renderArr.push(textLabel);

		return item;
	}


	getPicItem(img, saveData = null) {


		const item = new EditorItem(this.ctx);
		item.load(img.pic_url).then(img => {

			let maxW, maxH;
			if (this.bg) {
				maxW = this.bg.width * this.bg.scaleX;
				maxH = this.bg.height * this.bg.scaleY;
			} else {
				maxW = this.canvasWidth;
				maxH = this.canvasHeight;
			}

			let scaleX = maxW / 3 / item.width;
			let scaleY = maxH / 3 / item.height;

			if (item.height * scaleX < this.canvasHeight) {
				item.setScaleXY(scaleX);
			} else {
				item.setScaleXY(scaleY);
			}
			item.x = this.canvasWidth / 2;
			item.y = this.canvasHeight / 2;

			if (saveData) {

				const saveRect = saveData.rect;
				item.setScaleXY(saveRect.width / item.width);
				item.x = saveRect.x + saveRect.width / 2;
				item.y = saveRect.y + saveRect.height / 2;

			} else {
				item.showLineDash();
			}

		});
		return item;
	}


	onAudioUploadSuccessByImg(e, img) {
		img.audio_url = e.url;
	}

	deleteItem(e, i) {
		// this.imgArr.splice(i , 1);
		// this.refreshImageId();

		this.hotZoneArr.splice(i, 1);
		this.refreshHotZoneId();
	}


	radioChange(e, item) {
		item.itemType = e;

		this.refreshItem(item);

		// console.log(' in radioChange e: ', e);
	}

	refreshItem(item) {
		switch (item.itemType) {
			case 'rect':
				this.setRectState(item);
				break;
			case 'pic':
				this.setPicState(item);
				break;
			case 'text':
				this.setTextState(item);
				break;
			default:

		}
	}


	init() {

		this.initData();
		this.initCtx();

		this.initItem();
	}

	initItem() {
		if (!this.bgItem) {
			this.bgItem = {};
		} else {
			this.refreshBackground(() => {

				// if (!this.imgItemArr) {
				//   this.imgItemArr = [];
				// } else {
				//   this.initImgArr();
				// }

				// console.log('aaaaa');

				if (!this.hotZoneItemArr) {
					this.hotZoneItemArr = [];
				} else {
					this.initHotZoneArr();
				}

			});
		}

	}

	initHotZoneArr() {

		// console.log('this.hotZoneArr: ', this.hotZoneArr);
		let curBgRect;
		if (this.bg) {
			curBgRect = this.bg.getBoundingBox();
		} else {
			curBgRect = { x: 0, y: 0, width: this.canvasWidth, height: this.canvasHeight };
		}

		let oldBgRect = this.bgItem.rect;
		if (!oldBgRect) {
			oldBgRect = curBgRect;
		}

		const rate = curBgRect.width / oldBgRect.width;

		console.log('rate: ', rate);

		this.hotZoneArr = [];
		const arr = this.hotZoneItemArr.concat();
		for (let i = 0; i < arr.length; i++) {

			const data = JSON.parse(JSON.stringify(arr[i]));
			// const img = {pic_url: data.pic_url};

			data.rect.x *= rate;
			data.rect.y *= rate;
			data.rect.width *= rate;
			data.rect.height *= rate;

			data.rect.x += curBgRect.x;
			data.rect.y += curBgRect.y;

			// img['picItem'] = this.getPicItem(img, data);
			// img['audio_url'] = arr[i].audio_url;
			// this.imgArr.push(img);

			const item = this.getHotZoneItem(data);
			item.audio_url = data.audio_url;
			item.pic_url = data.pic_url;
			item.text = data.text;
			item.itemType = data.itemType;
			this.refreshItem(item);

			console.log('item: ', item);
			this.hotZoneArr.push(item);

		}

		this.refreshHotZoneId();

		// this.refreshImageId();

	}


	initImgArr() {

		console.log('this.imgItemArr: ', this.imgItemArr);
		let curBgRect;
		if (this.bg) {
			curBgRect = this.bg.getBoundingBox();
		} else {
			curBgRect = { x: 0, y: 0, width: this.canvasWidth, height: this.canvasHeight };
		}

		let oldBgRect = this.bgItem.rect;
		if (!oldBgRect) {
			oldBgRect = curBgRect;
		}

		const rate = curBgRect.width / oldBgRect.width;

		console.log('rate: ', rate);

		this.imgArr = [];
		const arr = this.imgItemArr.concat();
		for (let i = 0; i < arr.length; i++) {

			const data = JSON.parse(JSON.stringify(arr[i]));
			const img = { pic_url: data.pic_url };

			data.rect.x *= rate;
			data.rect.y *= rate;
			data.rect.width *= rate;
			data.rect.height *= rate;

			data.rect.x += curBgRect.x;
			data.rect.y += curBgRect.y;

			img['picItem'] = this.getPicItem(img, data);
			img['audio_url'] = arr[i].audio_url;
			this.imgArr.push(img);
		}
		this.refreshImageId();
	}


	initData() {

		this.canvasWidth = this.wrap.nativeElement.clientWidth;
		this.canvasHeight = this.wrap.nativeElement.clientHeight;
		this.mapScale = this.canvasWidth / this.canvasBaseW;
		this.renderArr = [];
		this.bg = null;

		this.imgArr = [];
		this.hotZoneArr = [];
	}

	initCtx() {
		this.ctx = this.canvas.nativeElement.getContext('2d');
		this.canvas.nativeElement.width = this.canvasWidth;
		this.canvas.nativeElement.height = this.canvasHeight;
	}


	mapDown(event) {

		this.oldPos = { x: this.mx, y: this.my };

		for (let i = 0; i < this.hotZoneArr.length; i++) {

			const item = this.hotZoneArr[i];
			let callback;
			let target;
			switch (item.itemType) {
				case 'rect':
					target = item;
					callback = this.clickedHotZoneRect.bind(this);
					break;
				case 'pic':
					target = item.pic;
					callback = this.clickedHotZonePic.bind(this);
					break;
				case 'text':
					target = item.textLabel;
					callback = this.clickedHotZoneText.bind(this);
					break;
			}

			if (this.checkClickTarget(target)) {
				callback(target);
				return;
			}
		}


	}


	mapMove(event) {
		if (!this.curItem) {
			return;
		}

		if (this.changeSizeFlag) {
			this.changeSize();

		} else if (this.changeTopSizeFlag) {
			this.changeTopSize();

		} else if (this.changeRightSizeFlag) {
			this.changeRightSize();

		} else {

			const addX = this.mx - this.oldPos.x;
			const addY = this.my - this.oldPos.y;
			this.curItem.x += addX;
			this.curItem.y += addY;
		}

		this.oldPos = { x: this.mx, y: this.my };

		this.saveDisabled = true;

	}

	mapUp(event) {
		this.curItem = null;
		this.changeSizeFlag = false;
		this.changeTopSizeFlag = false;
		this.changeRightSizeFlag = false;
	}


	changeSize() {
		const rect = this.curItem.getBoundingBox();

		let lenW = (this.mx - (rect.x + rect.width / 2)) * 2;
		let lenH = ((rect.y + rect.height / 2) - this.my) * 2;


		let minLen = 20;
		let s;
		if (lenW < lenH) {
			if (lenW < minLen) {
				lenW = minLen;
			}
			s = lenW / this.curItem.width;

		} else {
			if (lenH < minLen) {
				lenH = minLen;
			}
			s = lenH / this.curItem.height;
		}


		// console.log('s: ', s);
		this.curItem.setScaleXY(s);
		this.curItem.refreshLabelScale();
	}


	changeTopSize() {
		const rect = this.curItem.getBoundingBox();

		// let lenW = ( this.mx - (rect.x + rect.width / 2) ) * 2;
		let lenH = ((rect.y + rect.height / 2) - this.my) * 2;


		let minLen = 20;
		let s;
		// if (lenW < lenH) {
		//   if (lenW < minLen) {
		//     lenW = minLen;
		//   }
		//   s = lenW / this.curItem.width;
		//
		// } else {
		if (lenH < minLen) {
			lenH = minLen;
		}
		s = lenH / this.curItem.height;
		// }


		// console.log('s: ', s);
		this.curItem.scaleY = s;
		this.curItem.refreshLabelScale();
	}

	changeRightSize() {
		const rect = this.curItem.getBoundingBox();

		let lenW = (this.mx - (rect.x + rect.width / 2)) * 2;
		// let lenH = ( (rect.y + rect.height / 2) - this.my ) * 2;

		let minLen = 20;
		let s;
		if (lenW < minLen) {
			lenW = minLen;
		}
		s = lenW / this.curItem.width;

		this.curItem.scaleX = s;
		this.curItem.refreshLabelScale();
	}

	changeItemSize(item) {
		this.curItem = item;
		this.changeSizeFlag = true;
	}

	changeItemTopSize(item) {
		this.curItem = item;
		this.changeTopSizeFlag = true;
	}

	changeItemRightSize(item) {
		this.curItem = item;
		this.changeRightSizeFlag = true;
	}

	changeCurItem(item) {

		this.hideAllLineDash();

		this.curItem = item;
		this.curItem.showLineDash();
	}

	hideAllLineDash() {

		for (let i = 0; i < this.imgArr.length; i++) {
			if (this.imgArr[i].picItem) {
				this.imgArr[i].picItem.hideLineDash();
			}
		}
	}


	update() {
		if (!this.ctx) {
			return;
		}


		this.animationId = window.requestAnimationFrame(this.update.bind(this));
		// 清除画布内容
		this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);

		for (let i = 0; i < this.renderArr.length; i++) {
			this.renderArr[i].update(this);
		}

		// for (let i = 0; i < this.imgArr.length; i++) {
		//   const picItem = this.imgArr[i].picItem;
		//   if (picItem) {
		//     picItem.update(this);
		//   }
		// }

		this.updateArr(this.hotZoneArr);
		this.updatePos()


		TWEEN.update();
	}

	updateArr(arr) {
		if (arr) {
			for (let i = 0; i < arr.length; i++) {
				arr[i].update();
			}
		}
	}


	renderAfterResize() {
		this.canvasWidth = this.wrap.nativeElement.clientWidth;
		this.canvasHeight = this.wrap.nativeElement.clientHeight;
		this.init();
	}

	initListener() {

		this.winResizeEventStream
			.pipe(debounceTime(500))
			.subscribe(data => {
				this.renderAfterResize();
			});

		if (this.IsPC()) {

			this.canvas.nativeElement.addEventListener('mousedown', (event) => {
				setMxMyByMouse(event);
				this.mapDown(event);
			});

			this.canvas.nativeElement.addEventListener('mousemove', (event) => {
				setMxMyByMouse(event);
				this.mapMove(event);
			});

			this.canvas.nativeElement.addEventListener('mouseup', (event) => {
				setMxMyByMouse(event);
				this.mapUp(event);
			});

			const setMxMyByMouse = (event) => {
				this.mx = event.offsetX;
				this.my = event.offsetY;
			};

		} else {

			this.canvas.nativeElement.addEventListener('touchstart', (event) => {
				setMxMyByTouch(event);
				this.mapDown(event);
			});

			this.canvas.nativeElement.addEventListener('touchmove', (event) => {
				setMxMyByTouch(event);
				this.mapMove(event);
			});

			this.canvas.nativeElement.addEventListener('touchend', (event) => {
				setMxMyByTouch(event);
				this.mapUp(event);
			});

			this.canvas.nativeElement.addEventListener('touchcancel', (event) => {
				setMxMyByTouch(event);
				this.mapUp(event);
			});


			const setMxMyByTouch = (event) => {
				if (event.touches.length <= 0) {
					return;
				}

				if (this.canvasLeft == null) {
					setParentOffset();
				}

				this.mx = event.touches[0].pageX - this.canvasLeft;
				this.my = event.touches[0].pageY - this.canvasTop;
			};


			const setParentOffset = () => {

				const rect = this.canvas.nativeElement.getBoundingClientRect();
				this.canvasLeft = rect.left;
				this.canvasTop = rect.top;
			};
		}
	}

	IsPC() {
		if (window['ELECTRON']) {
			return false; // 封装客户端标记
		}
		if (document.body.ontouchstart !== undefined) {
			return false;
		} else {
			return true;
		}
	}


	checkClickTarget(target) {

		const rect = target.getBoundingBox();
		if (this.checkPointInRect(this.mx, this.my, rect)) {
			return true;
		}
		return false;
	}

	checkPointInRect(x, y, rect) {
		if (x >= rect.x && x <= rect.x + rect.width) {
			if (y >= rect.y && y <= rect.y + rect.height) {
				return true;
			}
		}
		return false;
	}


	saveClick() {
		const bgItem = this.bgItem;
		if (this.bg) {
			bgItem['rect'] = this.bg.getBoundingBox();
		} else {
			bgItem['rect'] = {
				x: 0,
				y: 0,
				width: Math.round(this.canvasWidth * 100) / 100,
				height: Math.round(this.canvasHeight * 100) / 100
			};
		}


		const hotZoneItemArr = [];
		const hotZoneArr = this.hotZoneArr;
		for (let i = 0; i < hotZoneArr.length; i++) {

			const hotZoneItem = {
				index: hotZoneArr[i].index,
				pic_url: hotZoneArr[i].pic_url,
				text: hotZoneArr[i].text,
				audio_url: hotZoneArr[i].audio_url,
				itemType: hotZoneArr[i].itemType,
				fontSize: this.hotZoneFontObj.size,
				fontName: this.hotZoneFontObj.name,
				fontColor: this.hotZoneFontObj.color,
				fontScale: hotZoneArr[i].textLabel ? hotZoneArr[i].textLabel.scaleX : 1,
				imgScale: hotZoneArr[i].pic ? hotZoneArr[i].pic.scaleX : 1,
				mapScale: this.mapScale
			};
			hotZoneItem['rect'] = hotZoneArr[i].getBoundingBox();
			hotZoneItem['rect'].x = Math.round((hotZoneItem['rect'].x - bgItem['rect'].x) * 100) / 100;
			hotZoneItem['rect'].y = Math.round((hotZoneItem['rect'].y - bgItem['rect'].y) * 100) / 100;
			hotZoneItem['rect'].width = Math.round((hotZoneItem['rect'].width) * 100) / 100;
			hotZoneItem['rect'].height = Math.round((hotZoneItem['rect'].height) * 100) / 100;


			hotZoneItemArr.push(hotZoneItem);
		}

		console.log('hotZoneItemArr: ', hotZoneItemArr);

		this.save.emit({ bgItem, hotZoneItemArr });
	}

	private updatePos() {
		this.hotZoneArr.forEach((item) => {
			let x, y;
			switch (item.itemType) {
				case 'rect':
					x = item.x;
					y = item.y;
					break;

				case 'pic':
					x = item.pic.x;
					y = item.pic.y;
					break;

				case 'text':
					x = item.textLabel.x;
					y = item.textLabel.y;
					break;
			}

			item.x = x;
			item.y = y;
			item.pic.x = x;
			item.pic.y = y;
			item.textLabel.x = x;
			item.textLabel.y = y;
		});
	}

	private setPicState(item: any) {
		item.visible = false;
		item.textLabel.visible = false;
		item.pic.visible = true;
	}

	private setRectState(item: any) {
		item.visible = true;
		item.textLabel.visible = false;
		item.pic.visible = false;
	}

	private setTextState(item: any) {
		item.visible = false;
		item.pic.visible = false;
		item.textLabel.visible = true;
	}

	private clickedHotZoneRect(item: any) {
		if (this.checkClickTarget(item)) {

			if (item.lineDashFlag && this.checkClickTarget(item.arrow)) {
				this.changeItemSize(item);
			} else if (item.lineDashFlag && this.checkClickTarget(item.arrowTop)) {
				this.changeItemTopSize(item);
			} else if (item.lineDashFlag && this.checkClickTarget(item.arrowRight)) {
				this.changeItemRightSize(item);
			} else {
				this.changeCurItem(item);
			}
			return;
		}
	}

	private clickedHotZonePic(item: any) {
		if (this.checkClickTarget(item)) {
			this.curItem = item;
		}
	}

	private clickedHotZoneText(item: any) {
		if (this.checkClickTarget(item)) {
			this.curItem = item;
		}
	}

	saveText(item) {
		item.textLabel.text = item.text;
	}

	private loadHotZonePic(pic: HotZoneImg, url) {
		const baseLen = this.hotZoneImgSize * this.mapScale;
		pic.load(url).then(() => {
			const s = getMinScale(pic, baseLen);
			pic.setScaleXY(s);
		});
	}
}