package;

import MapDesc.TileDesc;
import MapDesc;
import haxe.Json;
import lime.ui.FileDialog;
import openfl.display.Bitmap;
import openfl.display.BitmapData;
import openfl.display.Sprite;
import openfl.events.Event;
import openfl.events.MouseEvent;
import openfl.text.TextField;
import sys.io.File;

using haxe.io.Path;
using sys.FileSystem;

enum EditMode {
	Tiles;
	Mobs;
}

class Main extends Sprite {
	var filepath:String = null;

	public var assetsPath:String;

	public var textures:Array<String> = [];

	public var wallTexture:Textures;
	public var floorTexture:Textures;
	public var ceilTexture:Textures;

	public var bitmaps:Map<String, BitmapData> = [];

	public var field:Field;

	public var mobsLayer:Mobs;

	public var mode(default, set):EditMode = Tiles;

	public var selectedMob:String;

	function set_mode(newMode:EditMode):EditMode {
		mode = newMode;
		mobsLayer.mouseEnabled = newMode == Mobs;
		dispatchEvent(new Event('mode'));
		return mode;
	}

	public var mobs:MobsList;

	var modeSelect:Modes;

	public function new() {
		super();

		assetsPath = Path.join([Sys.programPath(), '..', '..', '..', '..', '..', 'assets']).normalize();

		if (!assetsPath.exists())
			throw '$assetsPath - invalid path';

		for (file in Path.join([assetsPath, 'textures']).readDirectory()) {
			textures.push(file);
		}

		loadTextures();

		scaleX = scaleY = 2;

		var loadButton = new Button('load', () -> {
			var dialog = new FileDialog();
			dialog.onSelect.add((openPath:String) -> {
				load(openPath);
			});
			dialog.browse(OPEN, null, assetsPath);
		});

		loadButton.x = loadButton.y = 10;

		var saveButton = new Button('save', () -> {
			if (filepath == null) {
				var saveDialog = new FileDialog();
				saveDialog.onSelect.add((newpath) -> {
					filepath = newpath;
					save();
				});
				saveDialog.browse(SAVE, null, assetsPath);
			} else {
				save();
			}
		});

		saveButton.x = loadButton.x + loadButton.width + 10;
		saveButton.y = 10;

		addChild(loadButton);
		addChild(saveButton);

		var newForm = new NewForm(newMap);
		newForm.x = saveButton.x + saveButton.width + 10;
		newForm.y = 10;
		addChild(newForm);

		modeSelect = new Modes(this);

		modeSelect.y = saveButton.y + saveButton.height + 10;
		modeSelect.x = 10;

		addChild(modeSelect);

		field = new Field(this, 10, 10);
		field.y = modeSelect.y + modeSelect.height + 10;
		addChild(field);

		mobsLayer = new Mobs();
		mobsLayer.x = field.x;
		mobsLayer.y = field.y;
		addChild(mobsLayer);

		wallTexture = new Textures(this, 'Wall:', textures);
		wallTexture.x = field.x + field.width + 10;
		wallTexture.y = field.y;
		addChild(wallTexture);

		floorTexture = new Textures(this, 'Floor:', textures);
		floorTexture.x = wallTexture.x + wallTexture.width + 10;
		floorTexture.y = wallTexture.y;
		addChild(floorTexture);

		ceilTexture = new Textures(this, 'Ceiling:', textures);
		ceilTexture.x = floorTexture.x + floorTexture.width + 10;
		ceilTexture.y = floorTexture.y;
		addChild(ceilTexture);

		mobs = new MobsList(this);
		mobs.x = wallTexture.x;
		mobs.y = wallTexture.y + wallTexture.height + 10;
		addChild(mobs);
	}

	function loadTextures() {
		for (file in textures)
			bitmaps[file] = BitmapData.fromFile(Path.join([assetsPath, 'textures', file]));
	}

	function newMap(w:Int, h:Int) {
		var newField = new Field(this, w, h);
		newField.x = field.x;
		newField.y = field.y;

		removeChild(field);
		addChild(newField);

		var newMobsLayer = new Mobs();
		newMobsLayer.x = field.x;
		newMobsLayer.y = field.y;

		removeChild(mobsLayer);
		mobsLayer = newMobsLayer;
		addChild(mobsLayer);

		field = newField;
	}

	function load(file:String) {
		trace('load', file);
		filepath = file;
		var map:MapDesc = cast Json.parse(File.getContent(file));

		textures = map.textures;

		loadTextures();

		var newField = new Field(this, map.mapWidth, map.mapHeight);
		newField.x = field.x;
		newField.y = field.y;
		newField.setTiles(map.tiles);

		removeChild(field);
		addChild(newField);

		var newMobsLayer = new Mobs();
		newMobsLayer.x = field.x;
		newMobsLayer.y = field.y;

		for (desc in map.mobs) {
			newMobsLayer.addMob(desc);
		}

		removeChild(mobsLayer);
		mobsLayer = newMobsLayer;
		addChild(mobsLayer);

		field = newField;
	}

	function save() {
		trace('save', filepath);
		var map:MapDesc = {
			mapWidth: field.mapWidth,
			mapHeight: field.mapHeight,
			tiles: field.tileDescs,
			defaultCeilTextureID: null,
			defaultFloorTextureID: null,
			textures: textures,
			mobs: mobsLayer.mobs
		};

		File.saveContent(filepath, Json.stringify(map));
	}
}
