
import { PlayGame } from './PlayGame';
import { Background } from "./Background";
import {Road} from './Road'
import {Player} from "./player/Player";
import {getStage,getfactor} from "./utils";

import {Block} from "./Block";
import ObjectPool = engine.ObjectPool;

export const PoolName: string = 'block';

ObjectPool.registerPool(PoolName, function () {
	return new Block();
}, function (item: Block, data) {
	item.reset(data);
});



export default class GameView extends engine.Container {

	private static _instance: GameView;
	public static get instance(): GameView {
		if (this._instance == undefined) {
			this._instance = new GameView();
		}
		return this._instance;
	}

	offset = {x: -100, y: 320};

	background: Background;
	road: Road;
	playGame:PlayGame;
	world: p2.World;
	player: Player;

	revivePos;
	playing;
	lock;
	worldFPS = 60;

	private _block:Block;
	_touchEnabled;

	_viewport: any = {
		x: 0,
		y: 0,
	};

	constructor() {
		super();

	}

	hasPreSetup;

	eventStart() {
		if(this.hasPreSetup){
			return;
		}
		this.hasPreSetup = true;

		let background = this.background = new Background();
		background.setup();
		this.addChild(background);

		let road = this.road = new Road();
		road.y = getStage().height / 2 + 310;
		this.addChild(road);
		this.road.preSetup();
		
		this.setupWorld();
		this.player.fade(0, false);

		this.viewport = 0;

		this.startWorld();

		this.reset();
		this.setup();

		const playHint = new engine.Label();
		playHint.fillColor = 'block';
		playHint.size = 30;
		playHint.text = '注意不要踩到线和陷阱哦，后果很严重哦~';
		playHint.x = (getStage().width-playHint.width)/2;
		playHint.y = getStage().height / 2 + 500;
		this.addChild(playHint);

		this.playGame = new PlayGame();
		setTimeout(() => {
			this.playGame.GameView = this;
			this.addChild(this.playGame);
			this.start();
		}, 500);
	}
	hasSetup;
	setup() {
		if(this.hasSetup){
			return;
		}
		this.hasSetup = true;

		this.road.setup();
	}

	setupWorld() {
		let OTHER = Math.pow(2, 1),
			BODYPARTS = Math.pow(2, 2),
			GROUND = Math.pow(2, 3);

		const world = this.world = new p2.World({
			//gravity: [0, 0],
		});
		world.sleepMode = p2.World.BODY_SLEEPING;

		let planeShape = new p2.Plane();
		let ground = new p2.Body({
			position: [0, 0],
		});
		ground.addShape(planeShape);
		planeShape.collisionGroup = GROUND;
		planeShape.collisionMask = BODYPARTS | OTHER;
		world.addBody(ground);

		let player = this.player = new Player();
		player.setup({
			collisionGroup: BODYPARTS,
			collisionMask: GROUND | OTHER,
			world,
			ground,
		});
		player.addEventListener('move', this.onMove, this);
		player.addEventListener('foot_down', this.onFootDown, this);
	}

	onTicker(dt: number): boolean {
		const world = this.world;
		this.world.step(this.worldFPS / 1000);

		let l = world.bodies.length;
		for (let i: number = 0; i < l; i++) {
			let body: p2.Body = world.bodies[i];
			let display: any = body.displays ? body.displays[0] : null;
			if (display) {
				if (!this.contains(display)) {
					this.addChild(display);
				}

				display.localUpdate(
					body.position[0] * getfactor() + getStage().width / 2 + this.offset.x - this.viewport,
					getStage().height / 2 - body.position[1] * getfactor() + this.offset.y,
					360 - (body.angle + body.shapes[0].angle) * 180 / Math.PI,
					body.sleepState == p2.Body.SLEEPING
				)
			}
		}

		return false;
	}

	reset(revive = false) {
		this.background.reset(revive);
		this.road.reset(revive);
		this.player.reset(revive);
		this.player.fade(0);

		// if(!revive){
		// 	this.score = 0;
		// }
		this.viewport = revive ? this.revivePos : 0;
	}

	start(revive = false){
		this.road.start(revive);
		this.player.fade(1);
		this.playGame.start(revive);
		
	}

	startWorld() {
		if(this.playing){
			return;
		}
		this.playing = true;
		//engine.startTick(this.onTicker, this);
		engine.gameStage.addEventListener(engine.Event.ENTER_FRAME,this.onTicker,this)
	}

	stopWorld() {
		if(!this.playing){
			return;
		}
		this.playing = false;
		//egret.stopTick(this.onTicker, this);
		engine.gameStage.removeEventListener(engine.Event.ENTER_FRAME,this.onTicker,this)
	}

	get viewport() {
		return this._viewport.x;
	}

	set viewport(v) {
		this._viewport.x = v;
		this.updateViewport();
	}

	updateViewport() {
		const {x, y} = this._viewport;
		const pos = Math.max(0, x);
		this.background.setViewport(pos);
		this.road.setViewport(pos);
	}

	private onMove(event) {
		const {pos, bodyPos} = event.data;

		this.viewport = pos;

		if(this.road.hitReward(bodyPos)){
			this.dispatchEvent('scoreChange', {
				rewardScore: 100,
				passType: 10,
			}, true);
		}
	}

	down() {
		if(this.lock){
			return;
		}
		this.player.down();
	}

	up() {
		if(this.lock){
			return;
		}
		this.player.up();
	}

	private  onFootDown(event){
		const {mileage, pos} = event.data;
		this.revivePos = pos;
		const {target, lastTarget} = this.road.hitBlock(pos);

		this.road.playDust(pos);

		if(target){
			this.lock = true;
			this.stopWorld();

			this.dispatchEvent(engine.Event.COMPLETE,null,true);
			target.playFadeOut();
			target.playEffect();
			if(target.type == 4){  //explosion
				this.player.setSkin('gray');
			}
			this.road.removeBlock(target);
			this.player.switchFace(target.type);
			if(target.type == 0){
				this.player.fall();
			}

			this.lock = false;
			this.startWorld();
		}else{
			this.player.switchFace('normal');
			const score = Math.floor(mileage / 50 * 5);
			this.dispatchEvent('scoreChange', {
				score,
				passType: lastTarget ? lastTarget.type : -1,
			}, true);
		}
	}
	setWitchFace(type){
		this.player.switchFace(type);
		// setTimeout(() => {
			
		// }, );
	}
}
