export function Name() { return "NZXT Kraken X3"; }
export function VendorId() { return 0x1E71; }
export function ProductId() { return [0x2007, 0x2014]; }
export function Publisher() { return "WhirlwindFX"; }
export function Documentation(){ return "troubleshooting/nzxt"; }
export function DefaultComponentBrand() { return "NZXT";}
export function Size() { return [4, 4]; }
export function DefaultPosition(){return [165, 60];}
export function DefaultScale(){return 7.0;}
/* global
shutdownColor:readonly
LightingMode:readonly
forcedColor:readonly
*/
export function ControllableParameters() {
	return [
		{"property":"shutdownColor", "group":"lighting", "label":"Shutdown Color", "min":"0", "max":"360", "type":"color", "default":"#009bde"},
		{"property":"LightingMode", "group":"lighting", "label":"Lighting Mode", "type":"combobox", "values":["Canvas", "Forced"], "default":"Canvas"},
		{"property":"forcedColor", "group":"lighting", "label":"Forced Color", "min":"0", "max":"360", "type":"color", "default":"#009bde"},
	];
}

let Liquid_Temp;
let Pump_Speed;
let Pump_RPM;

const vLedPositions = [
	    [1, 0], [2, 0],
	[0, 1],          [3, 1],
	[0, 2],          [3, 2],
	[1, 3], [2, 3],

	[1, 2]
];

const vLedMap =[
	7, 0,
	6,        1,
	5,        2,
	4, 3
];

const vLedNames = [ "Led 1", "Led 2", "Led 3", "Led 4", "Led 5", "Led 6", "Led 7", "Led 8", "Logo" ];
const DeviceMaxLedLimit = 80;
const MinimumSpeed = 25;

//Channel Name, Led Limit
const ChannelArray = [ ["Channel 1", 40] ];

function SetupChannels() {
	device.SetLedLimit(DeviceMaxLedLimit);

	for(let i = 0; i < ChannelArray.length; i++) {
		device.addChannel(ChannelArray[i][0], ChannelArray[i][1]);
	}
}

export function LedNames() {
	return vLedNames;
}

export function LedPositions() {
	return vLedPositions;
}

export function Initialize() {
	SetupChannels();
	BurstFans();//This acts as a primer. If we don't have an rpm value to begin with, it trips the fanpolling function.
}

export function Render() {
	PollFans();
	sendchannel1Colors(0);
	sendchannelPumpColors(1);
	sendLogo();
}

export function Shutdown(SystemSuspending) {

	if(SystemSuspending){
		sendchannelPumpColors(1, "#000000"); // Go Dark on System Sleep/Shutdown
		sendchannel1Colors(0, "#000000");
		sendLogo("#000000");
	}else{

		sendchannelPumpColors(1, shutdownColor);
		sendchannel1Colors(0, shutdownColor);
		sendLogo(shutdownColor);
	}

}

function StreamLightingPacketChanneled(count, data, channel) {

	const packetNumber = 0;
	let totalLedCount = count;

	for(let packetNumber = 0; packetNumber < 2; packetNumber++ ) {
		const ledsToSend = totalLedCount >= 60 ? 60 : totalLedCount;
		totalLedCount -= ledsToSend;

		const packet = [0x22, 0x10 | packetNumber, 0x01 << channel, 0x00];
		packet.push(...data.splice(0, ledsToSend));

		device.write(packet, 64);
	}
}

function sendchannelPumpColors(channel, overrideColor) {
	const RGBdata = [];
	let TotalLedCount = 0;

	for(let iIdx = 0; iIdx < vLedMap.length; iIdx++) {
		const iPxX = vLedPositions[iIdx][0];
		const iPxY = vLedPositions[iIdx][1];
		let col;

		if(overrideColor) {
			col = hexToRgb(overrideColor);
		} else if (LightingMode == "Forced") {
			col = hexToRgb(forcedColor);
		} else {
			col = device.color(iPxX, iPxY);
		}

		RGBdata[vLedMap[iIdx]*3] = col[1];
		RGBdata[vLedMap[iIdx]*3 + 1] = col[0];
		RGBdata[vLedMap[iIdx]*3 + 2] = col[2];
		TotalLedCount += 3;
	}

	StreamLightingPacketChanneled(TotalLedCount, RGBdata, channel);
	SubmitLightingColors(channel);
}

function sendchannel1Colors(Channel, overrideColor) {
	let ChannelLedCount = device.channel(ChannelArray[Channel][0]).LedCount();
	const componentChannel = device.channel(ChannelArray[Channel][0]);

	if(!ChannelLedCount) {
		return;
	}
	let RGBData = [];

	if(overrideColor){
		RGBData = device.createColorArray(overrideColor, ChannelLedCount, "Inline", "GRB");
	}else if(LightingMode == "Forced") {
		RGBData = device.createColorArray(forcedColor, ChannelLedCount, "Inline", "GRB");
	} else if(componentChannel.shouldPulseColors()) {
		ChannelLedCount = 40;

		const pulseColor = device.getChannelPulseColor(ChannelArray[Channel][0]);
		RGBData = device.createColorArray(pulseColor, ChannelLedCount, "Inline", "GRB");
	} else {
		RGBData = device.channel(ChannelArray[Channel][0]).getColors("Inline", "GRB");
	}

	StreamLightingPacketChanneled(ChannelLedCount*3, RGBData, Channel);
	SubmitLightingColors(Channel);
}

function sendLogo(overrideColor) {
	const iPxX = vLedPositions[8][0];
	const iPxY = vLedPositions[8][1];

	let col;

	if(overrideColor) {
		col = hexToRgb(overrideColor);
	} else if (LightingMode == "Forced") {
		col = hexToRgb(forcedColor);
	} else {
		col = device.color(iPxX, iPxY);
	}

	//let packet = [0x21, 0x04, 0x04, 0x04, 0x00, 0x32, 0x00, col[1], col[0], col[2]] // 0x2007

	const packet = [0x2A, 0x04, 0x04, 0x04, 0x00, 0x32, 0x00, col[1], col[0], col[2]]; // 0x2014

	packet[56]   = 0x01;
	packet[57]   = 0x00;
	packet[58]   = 0x01;
	packet[59]   = 0x03;

	device.write(packet, 64);
}

function SubmitLightingColors(channel) {
	const packet = [0x22, 0xA0, 1 << channel, 0x00, 0x01, 0x00, 0x00, 0x28, 0x00, 0x00, 0x80, 0x00, 0x32, 0x00, 0x00, 0x01];
	device.write(packet, 64);
}

let savedPollFanTimer = Date.now();
const PollModeInternal = 3000;

function PollFans() {
	//Break if were not ready to poll
	if (Date.now() - savedPollFanTimer < PollModeInternal) {
		return;
	}

	savedPollFanTimer = Date.now();

	if(device.fanControlDisabled()) {
		return;
	}
	const pump = 1;
	const pumprpm = Pump_RPM;
	device.log(`Pump RPM: ${pumprpm}`);

	if(pumprpm > 0) {
		device.createFanControl(`Pump ${pump}`);
	}

	device.setRPM(`Pump ${pump}`, pumprpm);

	const newSpeed = device.getNormalizedFanlevel(`Pump ${pump}`) * 100;
	PumpSetup(newSpeed);
}

function BurstFans() {

	const BurstSpeed = 50;

	if(device.fanControlDisabled()) {
		return;
	}

	device.log("Bursting Fans for RPM based Detection");

	PumpSetup(BurstSpeed);
}

function PumpSetup(speed) {

	const packet = [0x72, 0x01, 0x00, 0x00];

	for(let RPMBytes = 0; RPMBytes < 40; RPMBytes++) {
		const Offset = RPMBytes + 4;
		packet[Offset] = Math.max(speed, MinimumSpeed);
	}

	device.log(`Setting Kraken Pump to ${Math.round(speed)}% `);
	device.write(packet, 64);

	do {
		const packet = device.read([0x0], 64, 10);

		if(packet[0] == 0x75 && packet[1] == 0x02) {
			Liquid_Temp = packet[15] + packet[16]/10;
			Pump_RPM = packet[18] << 8 | packet[17];
			Pump_Speed = packet[19];
			device.log("Reported Pump Speed: " + Pump_Speed + " %");
			device.log("Liquid Temperature: " + Liquid_Temp + " °C");
		}
	}
	while(device.getLastReadSize() > 0);
}

function hexToRgb(hex) {
	const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
	const colors = [];
	colors[0] = parseInt(result[1], 16);
	colors[1] = parseInt(result[2], 16);
	colors[2] = parseInt(result[3], 16);

	return colors;
}

export function ImageUrl(){
	return "https://assets.signalrgb.com/devices/brands/nzxt/aio/kraken-x3-aio.png";
}