/**
 * Created by rockyl on 2018-12-13.
 *
 * 滚动视图组件
 */

import {Entity, Size, createTween, createVector2D, Vector2D, ease} from "scilla";
import InteractComponent from "../base/InteractComponent";
import Transform from "../base/Transform";

export enum LockingType {
	NOSET,
	HORIZON,
	VERTICAL,
}

export default class ScrollView extends InteractComponent {
	viewport: Entity;
	content: Entity;
	lockingType: LockingType = LockingType.NOSET;

	private _beginPos: any;
	private _lastPos: Vector2D = createVector2D();
	private _viewportTransform: Transform;
	private _contentTransform: Transform;
	private _posOffset: any;
	private _posRange: Size;

	private _speed: Vector2D = createVector2D();

	onAwake() {
		super.onAwake();

		this._contentTransform = this.content.getComponent(Transform);
		this._viewportTransform = this.viewport.getComponent(Transform);

		this.callOnNextTick(this.updatePosOffset);
	}

	updatePosOffset = ()=>{
		const {position: {x: x, y: y}} = this._contentTransform;
		this._posOffset = {x, y};
		//console.log(this._posOffset);
	}

	updatePosRange = () => {
		const {width: pWidth, height: pHeight} = this._viewportTransform;
		const {width, height} = this._contentTransform;

		this._posRange = new Size(pWidth - width, pHeight - height);
		//console.log(this._posRange);
	};

	onTouchBegin(e) {
		super.onTouchBegin(e);

		this.updatePosRange();

		const {x: tx, y: ty} = e;
		const {_contentTransform: {position: {x: cx, y: cy}}} = this;

		this._beginPos = {
			tx,
			ty,
			cx,
			cy,
		};
		this._lastPos.setXY(tx, ty);
	}

	onGlobalTouchMove(e): boolean {
		super.onGlobalTouchMove(e);

		if (!this._beginPos) {
			return;
		}

		const {
			_beginPos: {tx, ty, cx, cy},
			_posOffset: {x: offX, y: offY},
			_contentTransform: {position},
			lockingType,
		} = this;
		const {x, y} = e;

		let px = x - tx + cx;
		let py = y - ty + cy;

		const {width: rWidth, height: rHeight} = this._posRange;

		const halfWidth = Math.abs( rWidth / 2);
		const paddingX = halfWidth - Math.abs(offX - halfWidth - px);
		if(paddingX < 0){
			px += paddingX * 0.8 * (x - tx > 0 ? 1 : -1);
		}

		const halfHeight = Math.abs( rHeight / 2);
		const paddingY = halfHeight - Math.abs(offY - halfHeight - py);
		if(paddingY < 0){
			py += paddingY * 0.8 * (y - ty > 0 ? 1 : -1);
		}

		switch (lockingType) {
			case LockingType.HORIZON:
				position.y = py;
				break;
			case LockingType.VERTICAL:
				position.x = px;
				break;
			default:
				position.setXY(px, py);
		}

		this._speed.copyFrom(this._lastPos.subtract({x, y}));
		this._lastPos.setXY(x, y);
	}

	onGlobalTouchEnd(e): boolean {
		super.onGlobalTouchEnd(e);

		if (!this._beginPos) {
			return;
		}
		this._beginPos = null;

		const {x: offX, y: offY} = this._posOffset;
		const {width: rWidth, height: rHeight} = this._posRange;
		const {position, position: {x, y}} = this._contentTransform;

		const tx = Math.min(Math.max(offX + rWidth, x), offX);
		const ty = Math.min(Math.max(offY + rHeight, y), offY);

		const targetPos = createVector2D(tx, ty);
		const duration = Math.min(500, Math.max(targetPos.distance(position), 200));
		createTween(this, this._contentTransform, true, {fields: ['x', 'y']})
			.to({position: targetPos}, duration, ease.cubicOut);
	}
}
