import{ world, system } from "@minecraft/server";
import { ActionFormData, ModalFormData } from "@minecraft/server-ui";

import { Config } from "./config";

let config_data = {};
let config_temp = {};
let config_value;

//load and save config
function getConfigAddonMenu(playerData, addon_selected){
	let display = new ModalFormData();
	let data = config_data[addon_selected];
	
	for(let config_settings of data.config_data){
		if(config_settings.type == "slider"){
			display.slider(config_settings.name, config_settings.range[0], config_settings.range[1], config_settings.value_step, config_value[config_settings.identifier]);
		}else if(config_settings.type == "toggle"){
			display.toggle(config_settings.name, config_value[config_settings.identifier]);
		}else if(config_settings.type == "input_string"){
			display.textField(config_settings.name, "Input here", config_value[config_settings.identifier]);
		}else if(config_settings.type == "dropdown"){
			display.dropdown(config_settings.name, config_settings.option, config_value[config_settings.identifier]);
		}
	}
	display.show(playerData).then(r=> {
		let i = 0;
		if(r.canceled) return;
		let dimension = world.getDimension("minecraft:overworld");
		let actor = dimension.spawnEntity("kc:config_loader", { x:0, y:320, z:0 });
		for(let config_settings of data["config_data"]){
			let tag_name = config_settings.identifier + "=" + r.formValues[i];
			actor.addTag(tag_name);
			config_value[config_settings.identifier] = r.formValues[i];
			dimension.runCommand("scriptevent config:refresh " + addon_selected + " " + config_settings.identifier + " " + r.formValues[i]);
			i++;
		}

		Object.keys(config_value).forEach(data=>{
			let tag_name = data + "=" + config_value[data];
			actor.addTag(tag_name);
		})

		world.setDynamicProperty("configuration_data", JSON.stringify(config_value));

		actor.runCommandAsync("scriptevent config_loaded:config");
		system.runTimeout(()=> {
			world.setDynamicProperty("configuration_data", JSON.stringify(config_value));
			actor.remove();
		}, 2);
	});
}

//load menu and change data
system.afterEvents.scriptEventReceive.subscribe(s=> {
	if(s.id == "config:open"){
		let past_data = world.getDimension("minecraft:overworld").getEntities({ location: {x:0, y:320, z:0}, maxDistance: 1, type: "kc:config_loader"});
		if(past_data){
			for(let entity of past_data) entity.remove();
		}
		
		let display = new ActionFormData();
		display.title("Addon Script Config Menu");
		display.body("Select addons configuration");
		let config_data_key = Object.keys(config_data);
		if(config_data_key.length > 0){
			for(let config_addon_name of config_data_key){
				display.button(config_data[config_addon_name]["config_display_name"]);
			}
		}else{
			display.body("Your don't have configurable addons\n\n");
			display.button("ok");
		}
		display.show(s.sourceEntity).then( r => {
			if(config_data_key.length > 0){
				if(r.selection >= 0){
					getConfigAddonMenu(s.sourceEntity, config_data_key[r.selection]);
				}
			}
		});
	}else if(s.id == "config:change"){
		let data = s.message.split(" ");

		if(!isNaN(data[1])){
			data[1] = Number(data[1]);
		}else{
			if(data[1] == "false"){
				data[1] = false;
			}else if(value == "true"){
				data[1] = true;
			}
		}
		config_value[data[0]] = data[1];
		console.warn("update " + data[0] + " value!");
		
		world.setDynamicProperty("configuration_data", JSON.stringify(config_value));
	}
			
}, {namespaces: [ "config" ]});


//get config data
config_value = world.getDynamicProperty("configuration_data");
if(config_value == undefined){
	config_value = {};
	world.setDynamicProperty("configuration_data", "{}");
	console.warn("cannot find configuration data, creating new data!");
}else{
	config_value = JSON.parse(config_value)
	console.warn("configuration data founded!");
}

let scan_configuration_timeout;

//compile data
system.afterEvents.scriptEventReceive.subscribe(s=> {
	if(config_temp[s.id] == undefined){
		config_temp[s.id] = s.message;
	}else{
		config_temp[s.id] += s.message;
	}

	try{
		let compile_data = JSON.parse(config_temp[s.id]);
		config_data[s.id] = compile_data;
		console.warn("sucessful collecting data from " + s.id.replace("load_config_addon:", ""));
		let has_new_data = false;
		for(let data_value of compile_data.config_data){
			if(config_value[data_value.identifier] == undefined){
				config_value[data_value.identifier] = data_value.value;
				console.warn("creating new data for " + data_value.name);
				has_new_data = true;
			}
		}
		if(has_new_data){
			world.setDynamicProperty(JSON.stringify(config_value));
			console.warn("update configuration data...");
		}
		delete config_temp[s.id];
	}catch(err){
		console.warn("compailing data from " + s.id.replace("load_config_addon:", "") + "...");
	}
	scan_configuration_timeout = system.currentTick + 20;

}, {namespaces: [ "load_config_addon" ]});

//load config world 
let runId = system.runInterval(()=>{
	if(scan_configuration_timeout == undefined) return;
	let playerData = world.getPlayers();
	if(playerData.length == 0){
		scan_configuration_timeout = system.currentTick + 20;
	}
	if(system.currentTick > scan_configuration_timeout && playerData.length > 0){
		
		let dimension = world.getDimension("minecraft:overworld");
		dimension.runCommand("tickingarea add circle 0 320 0 1 config_actor_ticking");
		let location = playerData[0].location;
		location.y += 8;
		let actor = dimension.spawnEntity("kc:config_loader", { x: 0, y: 320, z: 0 });

		let config_name = Object.keys(config_data);
		
		for(let config_settings of config_name){
			for(let value of config_data[config_settings].config_data){
				let tag_name = value.identifier + "=" + config_value[value.identifier];
				actor.addTag(tag_name);
				dimension.runCommand("scriptevent config:refresh " + config_name + " " + value.identifier + " " + config_value[value.identifier]);
			}
		}

		let send_config_id = system.runInterval(()=>{
			try{
				actor.runCommand("scriptevent config_loaded:config");
			}catch(err){
				system.clearRun(send_config_id);
			}
			// world.setDynamicProperty("configuration_data", JSON.stringify(config_value));

			// console.warn("SOURCE ACTOR TAGS = " + actor.getTags())
			// console.warn(JSON.stringify(actor.location))
			// console.warn("WORELD DATA = " + world.getDynamicProperty("configuration_data"))
			// console.warn("LOCAL DATA = " + JSON.stringify(config_value))
			// console.warn("Name DATA = " +  Object.keys(config_data))
		}, 10);
		system.runTimeout(()=> {
			world.setDynamicProperty("configuration_data", JSON.stringify(config_value));

			actor.remove();
			system.clearRun(send_config_id);
		}, 35);

		console.warn("load configuration data...");
		system.clearRun(runId);
	}
})

//get if configuratiun is changed
world.beforeEvents.entityRemove.subscribe(s=>{
	if(s.removedEntity.typeId != "kc:config_loader") return;
	s.removedEntity.getTags().forEach(s=>{
		let data = s.split("=");
		if(data[1] != String(config_value[data[0]])){
			let value = data[1];
			if(!isNaN(value)){
				value = Number(value);
			}else{
				if(value == "false"){
					value = false;
				}else if(value == "true"){
					value = true;
				}
			}
			console.warn("update " + data[0] + " value!");
			config_value[data[0]] = value;
		}
	});
	
	system.runTimeout(()=> {
		world.setDynamicProperty("configuration_data", JSON.stringify(config_value));
	});
});