import { NodeInfo } from '../../Model/NodeInfo.js';

import { Family } from '../../Definitions/index.js';
import type { ISYDevice } from '../../ISYDevice.js';

import { ColorControl, LevelControl, OnOff } from '@matter/main/clusters';
import { ClusterId, type ClusterType } from '@matter/types';
import { ISY, writeDebugFile } from '../../ISY.js';

import { ColorTemperatureLight, DimmableLight, ExtendedColorLight } from './index.js';
import { OnOffLight } from './OnOffLight.js';
import { hasBitFlag, type ZigBeeClusterData } from './ZigbeeClusterData.js';

export function parseZigbeeClusterData(input: string): { [x: string]: ZigBeeClusterData<any> } {
	const clusters: { [x: ClusterId]: ZigBeeClusterData<ClusterType> } = {};
	const clusterRegex = /Cluster (\d+) 0x([0-9A-Fa-f]+) ([\w_]+)/g;
	const dataRegex = /(\w+)\s+DATA\s+devices\.\d+\.endpoints\.(\d+)\.clusters\.\d+\.data\.?([\w\.]*)\s*=\s*(.+)/gm;

	let currentCluster: ZigBeeClusterData<ClusterType> | null = null;

	input?.split('\n').forEach(line => {
		clusterRegex.lastIndex = 0; // Reset lastIndex for clusterRegex
		const clusterMatch = clusterRegex.exec(line);
		if (clusterMatch) {
			if (currentCluster) clusters[currentCluster.clusterName] = currentCluster;
			currentCluster = {
				clusterId: ClusterId(parseInt(clusterMatch[1], 10)),
				clusterName: clusterMatch[3] as Uppercase<string>,
				endpoint: 0, // Placeholder, will be updated later
				data: {},
			};
			return;
		}
		dataRegex.lastIndex = 0; // Reset lastIndex for dataRegex
		const dataMatch = dataRegex.exec(line);
		if (dataMatch && currentCluster) {
			const [, type, endpoint, key, value] = dataMatch;
			currentCluster.endpoint = parseInt(endpoint, 10);
			currentCluster.data[key] = parseValue(type, value);
		}
	});
	if (currentCluster) {
		clusters[currentCluster?.clusterName] = currentCluster;
	}
	return clusters;
}

function parseValue(type: string, value: string): any {
	switch (type) {
		case 'Boolean':
			return value.trim() === 'True';
		case 'Integer':
			return parseInt(value, 10);
		case 'Binary':
			return value.match(/\[([0-9A-Fa-f]+)\]/)?.[1] || value;
		case 'Empty':
			return null;
		default:
			return value.trim();
	}
}
export class ZigBeeDeviceFactory {
	public static async create(
		isy: ISY,
		nodeInfo: NodeInfo<Family.ZigBee>
	): Promise<ISYDevice<Family.ZigBee, any, any, any>> {
		let clusterInfo = await isy.sendRequest(`zmatter/zigbee/dh/node/${nodeInfo.address}/cluster/0`, {
			trailingSlash: false,
		});
		if (clusterInfo) {
			if (isy.isDebugEnabled) {
				await writeDebugFile(clusterInfo, `${nodeInfo.address}_ClusterData.txt`, isy.logger, isy.storagePath);
			}

			let cd = parseZigbeeClusterData(clusterInfo);
			//@ts-expect-error
			let cc = cd['COLOR_CONTROL'] as ZigBeeClusterData<ColorControl.Cluster>;
			//@ts-expect-error
			let lc = cd['LEVEL_CONTROL'] as ZigBeeClusterData<LevelControl.Cluster>;
			//@ts-expect-error
			let os = cd['ON_OFF_SWITCH'] as ZigBeeClusterData<OnOff.Cluster>;
			if (cc) {
				if (hasBitFlag(cc.data.colorCapabilities, ColorControl.ColorCapabilities.xy)) {
					return new ExtendedColorLight(isy, nodeInfo, cd);
				} else if (hasBitFlag(cc.data.colorCapabilities, ColorControl.ColorCapabilities.colorTemperature)) {
					return new ColorTemperatureLight(isy, nodeInfo);
				}
			} else if (lc && os) return new DimmableLight(isy, nodeInfo);
			else if (os) return new OnOffLight(isy, nodeInfo);
		}
	}

	// public static buildDeviceMap() {

	// 	var fams = new Map<Family, FamilyDef<Family>>();
	// 	s.forEach((item) => {
	// 		var id = item.id as Family;
	// 		fams.set(id, { id: item.id, description: item.description, name: item.name, categories: new Map<string, CategoryDef<typeof id>>() });
	// 		var famDef = fams[id] as FamilyDef<Family>;
	// 		item.categories.forEach((element) => {
	// 			var catDef = { id: element.id, name: element.name, devices: new Map<string, DeviceDef<Family>> };
	// 			element.devices.forEach(
	// 				device => {
	// 					const r = this.getDeviceDetails({
	// 						family: item.id,
	// 						type: `${element.id}.${device.id}.0.0`,
	// 						address: '0 0 0 1',
	// 						nodeDefId: '',
	// 						enabled: undefined,
	// 						pnode: undefined,
	// 						name: '',
	// 						startDelay: 0,
	// 						hint: '',
	// 						endDelay: 0,
	// 						wattage: 0,
	// 						dcPeriod: 0
	// 					});
	// 					if (!r.unsupported) {
	// 						device.name = r.name;
	// 						device.modelNumber = r.modelNumber;
	// 						device.class = r.class.name;
	// 					}
	// 					catDef.devices.set(`${device.id}`, { id: device.id, modelNumber: device.modelNumber, name: device.name, class: r.class });
	// 				}

	// 			);
	// 			famDef.categories.set(element.name, catDef);
	// 			element.devices = element.devices.sort((a, b) => a.id - b.id);
	// 		});
	// 	}

	// 	);
	// 	writeFileSync("DeviceMapClean.json", JSON.stringify(fams));
	// }
}
