/**
 * Created by rockyl on 2019-11-20.
 */

export default class ZoomScroll extends engine.ScriptBase {
	static id = 'zoom-scroll';

	autoInit: boolean = true;
	duration: number = 1000;
	@engine.dirtyFieldTrigger
	index: number = 0;
	@engine.dirtyFieldTrigger
	itemWidth: number = 0;
	@engine.dirtyFieldTrigger
	itemHeight: number = 0;
	@engine.dirtyFieldTrigger
	scaleMin: number = 0.7;
	@engine.dirtyFieldTrigger
	scaleMax: number = 1;
	@engine.dirtyFieldTrigger
	alphaOut: number = 0.5;
	@engine.dirtyFieldTrigger
	alphaIn: number = 1;

	private _centerOffset;
	private _startDragPos;
	private _startDragOffset = {x: 0, y: 0};
	private _dragOffset = {x: 0, y: 0};

	mounted() {
		this._centerOffset = this.host.width / 2;

		if(this.autoInit){
			this.init();
		}
	}

	sleep(): void {

	}

	update(t) {

	}

	init() {
		for (let i = 0, li = this.host.children.length; i < li; i++) {
			const child = this.host.children[i];
			child.anchorX = child.width / 2;
			child.anchorY = child.height / 2;
			child.x = child.ix = i * this.itemWidth + this._centerOffset - this.itemWidth / 2;
		}

		this.scrollTo(0, false);
		this.host.addEventListener(engine.MouseEvent.MOUSE_DOWN, this.onDragStart, this);
	}

	updateOffset(offset) {

		this._dragOffset.x = this._startDragOffset.x + offset.x;

		for (let i = 0, li = this.host.children.length; i < li; i++) {
			const child = this.host.children[i];
			let x = child.x = child.ix + this._dragOffset.x;

			let s = 40 / Math.abs(x - this._centerOffset + this.itemWidth / 2);
			child.scaleX = child.scaleY = x === 0 ? 1 : Math.min(s + this.scaleMin, this.scaleMax);
			child.alpha = x === 0 ? 1 : Math.min(s + this.alphaOut, this.alphaIn);
		}
	}

	private onDragStart(event) {
		this.host.stage.addEventListener(engine.MouseEvent.MOUSE_MOVE, this.onDraging, this);
		this.host.stage.addEventListener(engine.MouseEvent.MOUSE_UP, this.onDragEnd, this);

		this._startDragPos = {
			x: event.stageX,
			y: event.stageY,
		};

		this._startDragOffset.x = this._dragOffset.x;
		this._startDragOffset.y = this._dragOffset.y;
	}

	private onDraging(event) {
		if (!this._startDragPos) {
			return;
		}

		const {x, y} = this._startDragPos;
		const {stageX, stageY} = event;
		const offset = {
			x: stageX - x,
			y: stageY - y,
		};

		this.updateOffset(offset);
	}

	private onDragEnd(event) {
		this.host.stage.removeEventListener(engine.MouseEvent.MOUSE_MOVE, this.onDraging, this);
		this.host.stage.removeEventListener(engine.MouseEvent.MOUSE_UP, this.onDragEnd, this);

		if (!this._startDragPos) {
			return;
		}

		this._startDragOffset.x = 0;
		this._startDragOffset.y = 0;

		let index = Math.round(this._dragOffset.x / this.itemWidth);
		index = -Math.min(0, Math.max(1 - this.host.children.length, index));

		this['_index'] = index;

		this.scrollTo(index);

		this._startDragPos = null;
	}

	private get t() {
		return this._dragOffset.x;
	}

	private set t(v) {
		this.updateOffset({x: v, y: 0});
	}

	private scrollTo(index, animation = true) {
		let indexPos = -index * this.itemWidth;
		if (animation) {
			engine.Tween.get(this, null, null, true)
				.to({t: indexPos}, 100, engine.Ease.cubicOut);
		} else {
			this.t = indexPos;
		}
	}

	protected onModify(value, key, oldValue) {
		switch (key) {
			case 'index':
				let index = value;
				if(oldValue!==undefined){
					index = Math.max(0, Math.min(this.host.children.length - 1, value));
					this['_index'] = index;
				}

				setTimeout(()=>{
					this.scrollTo(index, oldValue!==undefined);
				});
				break;
		}
	}
}

