/**
 * Created by rockyl on 2020-01-09.
 */

function getTexture(uuid) {
	return engine.Texture.from(getAssetByUUID(uuid).uuid);
}

export class ScratchCard extends engine.Container {
	private _bg: engine.Sprite;
	private _img: engine.Image;
	private _mask: engine.Graphics;

	private _status = 0;
	private _points = [];
	private _tempPoints;
	private _startPos: any = {};
	private _endPos: any = {};
	private _moveLength = 0;
	private _scratchable = false;

	constructor() {
		super();

		let bg = this._bg = new engine.Sprite(getTexture('b76f6524-3a6e-4586-9ab9-b78f41f39ed8'));
		this.addChild(bg);

		let img = this._img = new engine.Image();
		img.mouseEnabled = false;
		img.horizonCenter = img.verticalCenter = 0;
		this.addChild(img);

		let mask = this._mask = new engine.Graphics();
		mask.mouseEnabled = false;
		this.addChild(mask);

		img.mask = mask;

		bg.addEventListener(engine.MouseEvent.MOUSE_DOWN, this.onMouseDown, this);

		engine.globalEvent.addEventListener('scratch-card-reset', this.reset, this);
	}

	reset(event: engine.Event) {
		let img = this._img;
		if (event.data && event.data.image) {
			img.source = event.data.image;
			this._scratchable = true;
		} else {
			this._scratchable = false;
			img.source = null;
		}

		this._mask.clear();

		this._points.splice(0);
		this._moveLength = 0;
	}

	private draw() {
		let brushSize = getProps().brushSize;
		let mask = this._mask;
		let points = this._points;
		if (!points.length) return;
		mask.clear();
		for (let i = 0; i < points.length; i++) {
			let tempPoints = points[i];
			if (tempPoints.length < 2) continue;
			mask.beginFill(0xff0000);
			mask.drawCircle(tempPoints[0].x, tempPoints[0].y, 1);
			mask.endFill();
			mask.lineStyle(brushSize, 0xff0000, 1);
			mask.moveTo(tempPoints[0].x, tempPoints[0].y);
			for (let j = 1; j < tempPoints.length - 1; j++) {
				mask.lineTo(tempPoints[j].x, tempPoints[j].y);
			}
			mask.endFill();
			mask.beginFill(0xff0000);
			mask.drawCircle(tempPoints[tempPoints.length - 1].x, tempPoints[tempPoints.length - 1].y, 2);
			mask.endFill();
		}
	}

	private onMouseDown(event: engine.MouseEvent) {
		if (!this._scratchable) {
			return;
		}

		this._bg.addEventListener(engine.MouseEvent.MOUSE_MOVE, this.onMouseMove, this);
		this._bg.addEventListener(engine.MouseEvent.MOUSE_OUT, this.onMouseOut, this);
		this.stage.addEventListener(engine.MouseEvent.MOUSE_UP, this.onMouseUp, this);

		const {localX: x, localY: y} = event;

		this._points.push(this._tempPoints = []);
		this._tempPoints.push({x, y});

		this._startPos.x = x;
		this._startPos.y = y;

		this._status = 1;
	}

	private onMouseMove(event: engine.MouseEvent) {
		if (this._status === 1) {
			const {localX: x, localY: y} = event;

			this._tempPoints.push({x, y});
			this.draw();

			this._endPos.x = x;
			this._endPos.y = y;

			let distance = engine.Point.distance(this._startPos, this._endPos);
			this._moveLength += distance;

			this._startPos.x = x;
			this._startPos.y = y;

			if (this._moveLength > getProps().openThreshold) {
				this._status = 0;

				this._mask.beginFill(0xff0000);
				this._mask.drawRect(0, 0, this._bg.width, this._bg.height);
				this._mask.endFill();
				engine.globalEvent.dispatchEvent('scratch-card-open');
			}
		}
	}

	private onMouseOut(event: engine.MouseEvent) {
		if (this._status === 1) {
			this._status = 0;
		}
	}

	private onMouseUp(event: engine.MouseEvent) {
		this._bg.removeEventListener(engine.MouseEvent.MOUSE_MOVE, this.onMouseMove, this);
		this._bg.removeEventListener(engine.MouseEvent.MOUSE_OUT, this.onMouseOut, this);
		this.stage.removeEventListener(engine.MouseEvent.MOUSE_UP, this.onMouseUp, this);

		this._status = 0;
	}
}
