package;

import flixel.addons.editors.ogmo.FlxOgmoLoader;
import flixel.FlxG;
import flixel.FlxGame;
import flixel.FlxSprite;
import flixel.FlxState;
import flixel.FlxObject;
import flixel.group.FlxGroup;
import flixel.group.FlxGroup.FlxTypedGroup;
import flixel.input.keyboard.FlxKey;
import flixel.text.FlxText;
import flixel.tile.FlxTilemap;
import flixel.ui.FlxButton;
import flixel.util.FlxColor;
using flixel.util.FlxSpriteUtil;
import flixel.util.FlxCollision;
import flixel.math.FlxVelocity;
import flixel.math.FlxAngle;
import flixel.math.FlxVector;
import flixel.math.FlxMath;
import flixel.math.FlxPoint;
import flixel.system.FlxAssets;
import Enemy;



class Level01 extends FlxState
{
	private var _player:Player;
	private var _grpEnemies:FlxTypedGroup<Enemy>;
	private var _grpClips:FlxTypedGroup<Clip>;
	private var _grpBoxes:FlxTypedGroup<Box>;
	private var _grpEnd:FlxTypedGroup<EndGame>;
	private var _hud:HUD;
	public var debugText:FlxText;
	public var debugSprite:FlxSprite;
	var angle1:Float;
	var angle2:Float;
	var cansee:Bool;
	public var disabledEnemies:Int = 0;
	private var _launchedSubstate:Bool=false;
	
	private var _map:FlxOgmoLoader;
	private var _mWalls:FlxTilemap;
	private var _mObj:FlxTilemap;
	override public function create():Void
	{
		_map = new FlxOgmoLoader(AssetPaths.level01__oel);//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
		_mWalls = _map.loadTilemap(AssetPaths.tileset__png, 16, 16, "walls");//загрузка тайлов
		_mObj = _map.loadTilemap(AssetPaths.tileset__png, 16, 16, "objects");
		_mWalls.follow();
		_mWalls.setTileProperties(143, FlxObject.ANY);
		_mWalls.setTileProperties(110, FlxObject.NONE);
		_mWalls.setTileProperties(109, FlxObject.NONE);
		_mWalls.setTileProperties(108, FlxObject.NONE);
		_mWalls.setTileProperties(140, FlxObject.NONE);
		_mWalls.setTileProperties(139, FlxObject.NONE);
		_mWalls.setTileProperties(138, FlxObject.NONE);
		_mWalls.setTileProperties(170, FlxObject.NONE);
		_mWalls.setTileProperties(169, FlxObject.NONE);
		_mWalls.setTileProperties(168, FlxObject.NONE);
		_mWalls.setTileProperties(480, FlxObject.NONE);
		_mWalls.setTileProperties(480, FlxObject.NONE);
		_mWalls.setTileProperties(279, FlxObject.NONE);
		_mWalls.setTileProperties(280, FlxObject.NONE);
		_mWalls.setTileProperties(281, FlxObject.NONE);
		_mWalls.setTileProperties(309, FlxObject.NONE);
		_mWalls.setTileProperties(310, FlxObject.NONE);
		_mWalls.setTileProperties(311, FlxObject.NONE);
		_mWalls.setTileProperties(339, FlxObject.NONE);
		_mWalls.setTileProperties(340, FlxObject.NONE);
		_mWalls.setTileProperties(341, FlxObject.NONE);
		_mWalls.setTileProperties(490, FlxObject.NONE);
		_mWalls.setTileProperties(72, FlxObject.NONE);
		_mObj.setTileProperties(381, FlxObject.NONE);
		_mObj.setTileProperties(382, FlxObject.NONE);
		_mObj.setTileProperties(383, FlxObject.NONE);
		_mObj.setTileProperties(411, FlxObject.NONE);
		_mObj.setTileProperties(412, FlxObject.NONE);
		_mObj.setTileProperties(413, FlxObject.NONE);
		_mObj.setTileProperties(441, FlxObject.NONE);
		_mObj.setTileProperties(442, FlxObject.NONE);
		_mObj.setTileProperties(443, FlxObject.NONE);
		add(_mWalls);
		add(_mObj);
		
		debugText = new FlxText(10, 20, 0, "");
		debugText.scrollFactor.set(0, 0);
		debugText.cameras = [FlxG.camera];
		add(debugText);
		
		debugSprite = new FlxSprite(0, 0);
		debugSprite.makeGraphic(500, 500, FlxColor.TRANSPARENT);
		add(debugSprite);
		
		_player = new Player();
		_grpEnemies = new FlxTypedGroup<Enemy>();
		_grpClips = new FlxTypedGroup<Clip>();
		_grpBoxes = new FlxTypedGroup<Box>();
		_grpEnd = new FlxTypedGroup<EndGame>();
		_hud = new HUD();
		
		_map.loadEntities(placeEntities, "entities");//загрузка сущностей
		
		add(_grpClips);
		
		add(_player);
		add(_grpEnemies);
		add(_grpBoxes);
		add(_grpEnd);
		add(_hud);
		FlxG.camera.follow(_player, TOPDOWN, 1);
		this.cameras = [FlxG.camera];
		
		/*var sprite = new FlxSprite();
		sprite.makeGraphic(10, 10, FlxColor.TRANSPARENT);
		sprite.drawCircle();
		FlxG.mouse.load(sprite.pixels);*/
		
		
		super.create();
	}
	
	override public function update(elapsed:Float):Void
	{
		super.update(elapsed);
		
		if (FlxG.keys.anyJustReleased([SPACE]))
		{
			_grpEnemies.forEachAlive(checkPlayer);
			_grpBoxes.forEachAlive(checkPlayerBox);
		}
		FlxG.collide(_mWalls, _player);
		FlxG.collide(_mObj, _player);
		FlxG.collide(_mObj, _grpEnemies);
		FlxG.collide(_player, _grpEnemies);
		FlxG.collide(_mWalls, _grpEnemies);
		FlxG.collide(_grpEnemies, _grpEnemies);
		FlxG.collide(_grpEnemies, _grpBoxes);
		FlxG.collide(_player, _grpBoxes);
		_grpEnemies.forEachAlive(checkEnemyVision);
		_grpEnemies.forEachAlive(checkEnemiesCollision);
		_hud.updateHUD(_player.isHidden, _player.health, _player.clipsCount);
		FlxG.overlap(_player, _grpClips, playerTouchClip);
		FlxG.overlap(_player, _grpEnd, goodOver);
		if (_player.health <= 0) badOver();
	}
	public function returnFromSubState():Void
	{FlxG.camera.fade(FlxColor.BLACK, .33, false, function()
		{
			FlxG.switchState(new MenuState());
		});}
	private function goodOver(P:Player, E:EndGame):Void
	{
		openSubState(new Message(returnFromSubState, "Senpai: Hmm, good! Now you are ready to avenge our Sensei.", ""));
	}
	private function badOver():Void
	{
		FlxG.resetState();
	}
	private function checkPlayer(e:Enemy):Void
	{
		if ( FlxMath.distanceBetween(_player, e) < 30 && !Std.is(e.fsm.state, Chase) && !Std.is(e.fsm.state, Attack) && _player.clipsCount > 0 && !e.isDisabled)
		{
			_player.clipsCount -= 1;
			disabledEnemies++;
			e.isDisabled = true;
		}
	}
	private function checkPlayerBox(b:Box):Void
	{
		if (_player.isHidden && _player.overlaps(b))
		{
			_player.isHidden = false;
			_player.immovable = false;
			_player.facing = FlxObject.UP;
			if (FlxG.keys.anyPressed([A])) _player.setPosition(b.x - _player.width, b.y);
			if (FlxG.keys.anyPressed([W])) _player.setPosition(b.x, b.y - _player.height);
			if (FlxG.keys.anyPressed([D])) _player.setPosition(b.x + _player.width, b.y);
			if (FlxG.keys.anyPressed([S])) _player.setPosition(b.x, b.y + _player.height);
			FlxG.camera.follow(_player, TOPDOWN, 1);
		}
		else if ( FlxMath.distanceBetween(_player, b) < 25 && b.y > _player.y || FlxMath.distanceBetween(_player, b) < 40 && b.y < _player.y)
		{
			if (!_player.isHidden)
			{
				_player.isHidden = true;
				_player.immovable = true;
				_player.setPosition(b.x, b.y + 4);
				_player.animation.play("up", false, false, 7);
				FlxG.camera.follow(b, TOPDOWN, 1);
			}
			for (i in _grpEnemies.iterator())//pizdets mamu ebal
			{
				if ( _mWalls.ray(i.getMidpoint(), b.getMidpoint()) )
				{
					i.seenHiding = true;
				}
			}
		}
	}
	private function checkEnemiesCollision(e:Enemy):Void
	{
		e.isPlayerHidden = _player.isHidden;
		//debugText.text = "State: " + e.fsm.state;
		//debugSprite.fill(FlxColor.TRANSPARENT);
		//debugSprite.drawLine(e.x, e.y, e.playerPos.x, e.playerPos.y);
		
		if (FlxMath.distanceToPoint(e, e.playerPos) <= 25 && Std.is(e.fsm.state, Attack) && e.canAttack && (e.animation.name == "attackDown" || e.animation.name == "attackUp" || e.animation.name == "attackLeftRight"))
		{
			e.velocity.set(0, 0);
			_player.velocity.set(0, 0);
			_player.hurt(1);
			FlxG.camera.shake(0.01, 0.2);
			_player.flicker(0.2, 0.01);
		}
		
	}
	
	private function placeEntities(entityName:String, entityData:Xml):Void
	{
		var x:Int = Std.parseInt(entityData.get("x"));
		var y:Int = Std.parseInt(entityData.get("y"));
		if (entityName == "player")
		{
			_player.x = x;
			_player.y = y;
		}
		else if (entityName == "enemy")
		{
			var enemy:Enemy = new Enemy(x, y);
			_grpEnemies.add(enemy);
		}
		else if (entityName == "clip")
		{
			_grpClips.add(new Clip(x, y));
		}
		else if (entityName == "box")
		{
			_grpBoxes.add(new Box(x, y));
		}
		else if (entityName == "endGame")
		{
			_grpEnd.add(new EndGame(x, y));
		}
	}
	
	private function playerTouchClip(P:Player, C:Clip):Void
	{
		if (P.alive && P.exists && C.alive && C.exists)
		{
			P.clipsCount += 1;
			C.kill();
		}
	}
	
	private function checkEnemyVision(e:Enemy):Void //ДОДЕЛАТЬ И ПЕРЕДЕЛАТЬ
	{
		angle1 = FlxAngle.angleBetween(e, _player, true);
		angle2 = FlxAngle.angleFromFacing(e.facing, true);
		if (e.facing != FlxObject.LEFT)
		{
			if (angle1 > FlxAngle.wrapAngle(angle2 - 80) && angle1 < FlxAngle.wrapAngle(angle2 + 80) && FlxMath.distanceToPoint(e, _player.getPosition())<200/*Math.abs(_player.x - e.x) < 200 && Math.abs(_player.y - e.y) < 200*/)
			cansee = true;
			else cansee = false;
		}
		else if(e.facing == FlxObject.LEFT)
		if (angle1 > FlxAngle.wrapAngle(angle2 - 80) || angle1 < FlxAngle.wrapAngle(angle2 + 80) && FlxMath.distanceToPoint(e, _player.getPosition()) < 200)
			cansee = true;
		else cansee = false;
		if ( (_mWalls.ray(e.getMidpoint(), _player.getMidpoint()) && cansee && !_player.isHidden) || (_mWalls.ray(e.getMidpoint(), _player.getMidpoint()) && cansee && _player.isHidden && e.seenHiding))
		{
			e.seesPlayer = true;
			e.playerPos.copyFrom(_player.getMidpoint());
		}
		else 
		{
			e.seesPlayer = false;
		}
	}
}
