

var DiagramView = MindFusion.Diagramming.DiagramView;
var Diagram = MindFusion.Diagramming.Diagram;
var Style = MindFusion.Diagramming.Style;
var PathFinder = MindFusion.Diagramming.PathFinder;
var AnchorPattern = MindFusion.Diagramming.AnchorPattern;
var AnchorPoint = MindFusion.Diagramming.AnchorPoint;
var SvgContent = MindFusion.Diagramming.SvgContent;
var SvgNode = MindFusion.Diagramming.SvgNode;
var AdjustmentHandles = MindFusion.Diagramming.AdjustmentHandles;
var ArrowHeads = MindFusion.Diagramming.ArrowHeads;
var LinkShape = MindFusion.Diagramming.LinkShape;
var ShapeNode = MindFusion.Diagramming.ShapeNode;

var Rect = MindFusion.Drawing.Rect;
var Size = MindFusion.Drawing.Size;

var shapeNodeStyle = new Style();
var diagram = null;

// New global variables for default styles
var defaultLinkStrokeColor = '#000000';
var defaultLinkHeadBrush = "#FFFFFF";
var defaultTextColor = '#000000';
var defaultStrokeThickness = 0.6;
var defaultLinkHeadShape = 'Triangle';
var defaultLinkBaseShape = null;

var nodeAnchorPattern = null;


document.addEventListener("DOMContentLoaded", function () {

	// create a DiagramView component that wraps the "diagram" canvas
	var diagramView = DiagramView.create(document.getElementById("diagram"));
	diagramView.linkBackId = "mindfusionLink";
	diagramView.allowInplaceEdit = true;
	
	diagram = diagramView.diagram;
	diagram.allowUnconnectedLinks = true;

	// styling
	shapeNodeStyle.brush = { type: 'SolidBrush', color: '#e0e9e9' };
	shapeNodeStyle.stroke = "#7F7F7F";
	shapeNodeStyle.fontName = "Verdana";
	shapeNodeStyle.fontSize = 4;

	diagram.style = shapeNodeStyle;
	diagram.shadowOffsetX = 0;
	diagram.shadowOffsetY = 0;
	diagram.gridSizeX = 3;
	diagram.gridSizeY = 3;
	diagram.showGrid = true;
	// automatically route links drawn by user
	diagram.routeLinks = true;
	diagram.alignToGrid = false;
	

	// set the size of diagram's scrollable area (unit is millimeter by default)
	diagram.bounds = new Rect(0, 0, 1000, 1000);
	
	nodeAnchorPattern = new AnchorPattern([
	    new AnchorPoint(0, 0, true, true),// top left
        new AnchorPoint(50, 0, true, true),//center top
		new AnchorPoint(100, 0, true, true),//top right
        new AnchorPoint(100, 50, true, true),//center right
        new AnchorPoint(50, 100, true, true),//center bottom
		new AnchorPoint(100, 100, true, true),//bottom right
        new AnchorPoint(0, 50, true, true),// left center
		new AnchorPoint(0, 100, true, true),//bottom left
    ]);
    nodeAnchorPattern.points[0].toolTip = "Top Left";
    nodeAnchorPattern.points[1].toolTip = "Center Top";
    nodeAnchorPattern.points[2].toolTip = "Top Right";
    nodeAnchorPattern.points[3].toolTip = "Center Right";
	nodeAnchorPattern.points[4].toolTip = "Center Bottom";
    nodeAnchorPattern.points[5].toolTip = "Bottom Right";
    nodeAnchorPattern.points[6].toolTip = "Left Center";
    nodeAnchorPattern.points[7].toolTip = "Bottom Left";
	

	//load diagram from json
	fetch('diagram.json')
		.then(response => response.text())
		.then(data => {
			diagram.fromJson(data);
		})
		.catch(error => {
			console.error('Error loading diagram.json:', error);
		});

	// the Palette component lets users create shapes using drag-and-drop;
	// users can also draw on the canvas using mouse or other pointing devices, as
	// specified via DiagramView.behavior property;
	var palette = MindFusion.Diagramming.Controls.Palette.create(document.getElementById("palette"));
	//palette.padding = 2;
	palette.captionFont = new MindFusion.Drawing.Font("sans-serif", 3);
	palette.setTop("200px");
	palette.setWidth("250px");
	palette.setHeight("");
	palette.theme = "business";
	palette.iconSize = new Size(10, 10);
    palette.newInstanceSize = new Size(20, 20);
	initPalette(palette);

	// create an Overview component that displays scaled-down version of the diagram
	var overview = MindFusion.Diagramming.Overview.create(document.getElementById("overview"));
	overview.diagramView = diagramView;
	overview.backColor = "#eee";

	// create a ZoomControl to allow changing zoom level using slider UI
	var zoomer = MindFusion.Controls.ZoomControl.create(document.getElementById("zoomer"));
	zoomer.target = diagramView;
	zoomer.backColor = 'transperant';
	zoomer.borderColor = "#5a79a5";

	// create a Ruler component that shows measurement scales and allows aligning nodes
	var ruler = MindFusion.Diagramming.Ruler.create(document.getElementById("ruler"));
	ruler.diagramView = diagramView;
	ruler.backColor = "#fff";
	ruler.foreColor = "#5a79a5";
	ruler.textColor = "#5a79a5";

	// buttons to save and load diagrams
	document.getElementById("newButton").addEventListener("click", onNewClick);
	document.getElementById("saveButton").addEventListener("click", onSaveClick);
	document.getElementById("loadButton").addEventListener("click", onLoadClick);
	
	// Get style control elements
	const linkColorPicker = document.getElementById('linkColorPicker');
	const linkThicknessInput = document.getElementById('linkThickness');
	const textColorPicker = document.getElementById('textColorPicker');
	
	// Initialize default styles from controls
	defaultLinkStrokeColor = linkColorPicker.value;
	defaultTextColor = textColorPicker.value;
	defaultStrokeThickness = parseFloat(linkThicknessInput.value);
	
	
	 // Event listeners for style controls
	textColorPicker.addEventListener('change', (event) => {
		defaultTextColor = event.target.value;
		diagram.selection.items.forEach(item => {
			item.textColor = defaultTextColor;
		});
    });

	 linkColorPicker.addEventListener('change', (event) => {
		defaultLinkStrokeColor = event.target.value;
		diagram.selection.links.forEach(link => {
			link.stroke = defaultLinkStrokeColor;
			link.headStroke = defaultLinkStrokeColor;

			if (link.headShape === 'Triangle') {
                link.headBrush = defaultLinkStrokeColor;
            } else {
                link.headBrush = 'white';
            }
		});
    });

	linkThicknessInput.addEventListener('change', (event) => {
		const newThickness = parseFloat(event.target.value);
		if (!isNaN(newThickness)) {
			defaultStrokeThickness = newThickness;
			diagram.selection.links.forEach(link => {
				link.strokeThickness = defaultStrokeThickness;
			});
		}
	});
	
	

	// detect user's actions by handling diagram events, such as nodeCreated
	diagram.nodeCreated.addEventListener(
		(sender, args) =>
		{
			args.node.textColor = defaultTextColor;
			args.node.shadowOffsetX = 0;
			args.node.shadowOffsetY = 0;
			//uncomment to enable anchor pattern for nodes
		//	args.node.anchorPattern = nodeAnchorPattern;
			args.node.enabledHandlers = AdjustmentHandles.All;
		});
	

	diagram.linkCreated.addEventListener(
		(sender, args) =>
		{		
			args.link.stroke = defaultLinkStrokeColor;
			args.link.strokeThickness = defaultStrokeThickness;
			args.link.headStrokeThickness = defaultStrokeThickness;
			args.link.headStroke = defaultLinkStrokeColor;
			args.link.textColor = defaultTextColor;
			args.link.shadowOffsetX = 0;
			args.link.shadowOffsetY = 0;
			args.link.autoRoute = true;
	
			if (args.link.headShape && args.link.headShape.id === 'Triangle') {
                args.link.headBrush = defaultLinkStrokeColor;
            }
		});
		
		diagram.addEventListener('linkCreating', onLinkCreating);
		diagram.addEventListener('nodeCreating', onNodeCreating);
		
	});
	

function onNodeCreating(diagram, args)
{
	args.node.textColor = defaultTextColor;
	args.node.shadowOffsetX = 0;
	args.node.shadowOffsetY = 0;
	args.link.headStrokeThickness = defaultStrokeThickness;
}

function onLinkCreating(diagram, args)
{
	defaultLinkHeadShape = args.link.headShape;
	defaultLinkBaseShape = args.link.baseShape;
			
	args.link.stroke = defaultLinkStrokeColor;
	args.link.strokeThickness = defaultStrokeThickness;
	args.link.headStrokeThickness = defaultStrokeThickness;
	args.link.headStroke = defaultLinkStrokeColor;
	args.link.textColor = defaultTextColor;
	args.link.shadowOffsetX = 0;
	args.link.shadowOffsetY = 0;
			
	if (args.link.headShape && args.link.headShape.id === 'Triangle') {
		args.link.headBrush = defaultLinkStrokeColor;
	}
			
    if (args.destination == null)
    {
        // not pointing to a node yet
        return;
    }

    var pathFinder = new PathFinder(diagram);
    var path = pathFinder.findShortestPath(
        args.destination, args.origin);

    if (path != null)
    {
        // adding this new link would create a cycle
        // [origin]--[dest]--[path internal nodes]--[origin]

        args.cancel = true;
    }
}

function initPalette(palette)
{
	// stock shape geometries are listed here:
	// https://mindfusion.dev/docs/javascript/diagramming/CC_refTable_of_Predefined_Shapes_4.htm

	// use the shape designer tool to draw custom shape geometries:
	// https://mindfusion.dev/tools/shape-designer.html

	// apart from ShapeNode, you could also add TableNode or ContainerNode objects

	palette.addCategory("Electrical Circuit");
	var shapeFileNames = ["resistor.svg", "resistor1.svg", "resistor2.svg", "capacitor.svg", "capacitor1.svg", "variable_capacitor.svg", "polarized_capacitor.svg", "polarized_capacitor1.svg", "inductor.svg", "grounding.svg", "ac.svg", "ac1.svg", "electric_diode.svg", "diode.svg", "zener_diode.svg", "bjt.svg", "bjt1.svg", "mosfet.svg", "transformer.svg", "transformer1.svg", "op-amp.svg", "switch.svg", "spdt.svg", "closed_switch.svg", "closed_switch1.svg"];
	var elCircuitNames = ["resistor", "resistor 1", "resistor 2", "capacitor", "capacitor 1", "variable capacitor", "polarized capacitor", "polarized capacitor 1", "inductor", "grounding", "alternating current", "alternating current 1", "electric diode", "diode", "Zener diode", "NPN bipolar junction transistor", "NPN bipolar junction transistor 1", "metal-oxide-semiconductor field-effect transistor", "transformer", "transformer 1", "Operational Amplifier ", "switch", "single pole double throw switch", "closed switch", "closed switch 1"];
	
	
	var bounds = new Rect(0, 0, 15, 30);
	for (var i = 0; i < shapeFileNames.length; ++i) {
		var node = new SvgNode(diagram);
		node.transparent = true;
		node.enabledHandles = AdjustmentHandles.All;
		
		var svg = new SvgContent();
		svg.parse("icons\\" + shapeFileNames[i]);
		node.content = svg;
		palette.addItem(node, "Electrical Circuit", elCircuitNames[i]);
	}

    var appliancesIcons = ["lamp.svg", "antenna.svg", "cross_switch.svg", "switch_dimmer.svg", "switch_1pin.svg", "switch_2pin.svg", "switch_3pin.svg", "microwave.svg", "fridge.svg", "freezer.svg", "cooker.svg", "cooker1.svg", "dish_washer.svg", "washing_machine.svg", "air_conditioner.svg", "clothes_dryer.svg"];

	var appliancesNames = ["lamp", "antenna", "cross switch", "switch dimmer", "switch 1 pin", "switch 2 pin", "switch 3 pin", "microwave", "fridge", "freezer", "cooker", "cooker 1", "dish washer", "washing machine", "air conditioner", "clothes dryer"];
	palette.addCategory("Home Appliances");
	
	for (var i = 0; i < appliancesIcons.length; ++i) {
		var node = new SvgNode(diagram);
		node.transparent = true;
		node.enabledHandles = AdjustmentHandles.All;
		
		var svg = new SvgContent();
		svg.parse("icons\\" + appliancesIcons[i]);
		node.content = svg;
		palette.addItem(node, "Home Appliances", appliancesNames[i]);
	}

	var linkHeadShapes = ["", "Circle", "Circle", "Triangle"];
	var linkHeadFills = ["#FFFFFF", defaultLinkStrokeColor, "#FFFFFF", defaultLinkStrokeColor]
	palette.addCategory("Electrical Connectors");
	
	for(var i = 1; i <= linkHeadShapes.length; i++)
	{
		var link = new MindFusion.Diagramming.DiagramLink();
		link.baseShape = null;
		link.headShape = linkHeadShapes[i-1];
		link.headShapeSize = 3;
		link.headBrush = linkHeadFills[i-1];
		link.headStroke = defaultLinkStrokeColor;
		link.shadowOffsetX = 0;
		link.shadowOffsetY = 0;
		link.headStrokeThickness = defaultStrokeThickness;
		link.strokeThickness = defaultStrokeThickness;
		link.shape = LinkShape.Polyline;	
		palette.addItem(link, "Electrical Connectors", "connector " + i);
	}
	
	var node = new ShapeNode(diagram);
	node.shape = "Circle";
	node.brush = defaultLinkStrokeColor;
	node.stroke = defaultLinkStrokeColor;
	palette.addItem(node, "Electrical Connectors", "connection point 1");
	
	node = new ShapeNode(diagram);
	node.shape = "Circle";
	node.brush = "white";
	node.stroke = defaultLinkStrokeColor;
	palette.addItem(node, "Electrical Connectors", "connection point 2");
	
	palette.addCategory("Miscellaneous");
	node = new ShapeNode(diagram);
	node.shape = "Rectangle";
	node.transparent = true;
	node.text = "Text";
	palette.addItem(node, "Miscellaneous", "label");
	
	// expand the first and last accordion items (Electrical Connectors category)
	palette.collapseItems(palette.items.item(1));
	palette.collapseItems(palette.items.item(2));
	palette.expandItems(palette.items.item(3));
	palette.expandItems(palette.items.item(0));
}

function onNewClick()
{
	diagram.clearAll();
}

const insecureContextMessage = 'The File System API is not available in this context. Please run the page from a web server (npm start).';

async function onSaveClick()
{
	try
	{
		// in this example we store diagram JSON files on local file system;
		// alternatively you could send JSON to server-side using fetch API, e.g.
		// fetch('api_url', { method: 'POST', ... }
		const json = diagram.toJson();

		// file system API is not fully supported in some browsers yet
		if (window.showSaveFilePicker)
		{
			if (!window.isSecureContext)
			{
				alert(insecureContextMessage);
				return;
			}
		
			const handle = await window.showSaveFilePicker(
			{
				startIn: 'documents',
					suggestedName: 'diagram.json',
					types: [{
						description: 'JSON Files',
						accept: {
							'application/json': ['.json'],
						},
					}],
			});
			const writable = await handle.createWritable();
			await writable.write(json);
			await writable.close();
		}
		else
		{
			// work-around for browsers that do not support file system
			const blob = new Blob([json], { type: 'application/json' });
			const url = URL.createObjectURL(blob);
			const a = document.createElement('a');
			a.href = url;
			a.download = 'diagram.json';
			document.body.appendChild(a);
			a.click();
			document.body.removeChild(a);
			URL.revokeObjectURL(url);
		}
	}
	catch (err)
	{
		console.error(err.name, err.message);
	}
}

async function onLoadClick()
{
	try
	{
		// in this example we store diagram JSON files on local file system;
		// alternatively you could load JSON from server-side using fetch API, e.g.
		// fetch('api_url', { method: 'GET', ... }

		// file system API is not fully supported in some browsers yet
		if (window.showOpenFilePicker)
		{
			if (!window.isSecureContext)
			{
				alert(insecureContextMessage);
				return;
			}
		
			const [handle] = await window.showOpenFilePicker(
			{
				startIn: 'documents',
					types: [{
						description: 'JSON Files',
						accept: {
							'application/json': ['.json'],
						},
					}],
			});
			const file = await handle.getFile();
			const content = await file.text();
			diagram.fromJson(content);
		}
		else
		{
			// work-around for browsers that do not support file system
			const input = document.createElement('input');
			input.type = 'file';
			input.accept = '.json,application/json';
			input.onchange = async (e) => {
				const file = e.target.files[0];
				const content = await file.text();
				diagram.fromJson(content);
			};
			input.click();
		}
	}
	catch (err)
	{
		console.error(err.name, err.message);
	}
}
