import * as plugins from '../../plugins.js';
import type { IIntegrationEntity, IIntegrationEvent, IServiceCallRequest, TEntityPlatform } from '../../core/types.js';
import type {
  IOpenRGBClientCommand,
  IOpenRGBConfig,
  IOpenRGBDevice,
  IOpenRGBDeviceMetadata,
  IOpenRGBEvent,
  IOpenRGBManualEntry,
  IOpenRGBMode,
  IOpenRGBRgbColor,
  IOpenRGBSnapshot,
  IOpenRGBZone,
  TOpenRGBCommandOperation,
} from './openrgb.types.js';
import { openrgbDefaultPort, openrgbUidSeparator } from './openrgb.types.js';

const openrgbModeOff = 'Off';
const openrgbModeStatic = 'Static';
const openrgbModeDirect = 'Direct';
const openrgbModeCustom = 'Custom';
const effectOffModes = new Set([openrgbModeStatic, openrgbModeDirect, openrgbModeCustom].map((modeArg) => modeArg.toLowerCase()));
const black: IOpenRGBRgbColor = { red: 0, green: 0, blue: 0 };
const white: IOpenRGBRgbColor = { red: 255, green: 255, blue: 255 };

const deviceTypeNames = [
  'motherboard',
  'dram',
  'gpu',
  'cooler',
  'ledstrip',
  'keyboard',
  'mouse',
  'mousemat',
  'headset',
  'headset_stand',
  'gamepad',
  'light',
  'speaker',
  'virtual',
  'storage',
  'case',
  'microphone',
  'accessory',
  'keypad',
  'unknown',
];

const zoneTypeNames = ['single', 'linear', 'matrix'];

interface IOpenRGBResolvedLight {
  entity: IIntegrationEntity;
  device: IOpenRGBDevice;
  zone?: IOpenRGBZone;
  info: IOpenRGBLightInfo;
}

interface IOpenRGBLightInfo {
  activeMode?: IOpenRGBMode;
  modeName?: string;
  modeIsOff: boolean;
  supportsColor: boolean;
  supportedColorModes: string[];
  rgbColor?: IOpenRGBRgbColor;
  brightness?: number;
  colorMode?: string;
  isOn: boolean;
  effect?: string;
  effectList: string[];
  effectToMode: Map<string, IOpenRGBMode>;
  preferredNoEffectMode?: IOpenRGBMode;
  offMode?: IOpenRGBMode;
  supportsOffMode: boolean;
}

export class OpenRGBMapper {
  public static toSnapshot(configArg: IOpenRGBConfig, connectedArg?: boolean, eventsArg: IOpenRGBEvent[] = []): IOpenRGBSnapshot {
    const source = configArg.snapshot;
    const host = configArg.host || source?.host;
    const port = configArg.port || source?.port || openrgbDefaultPort;
    const name = configArg.name || source?.name || source?.controller?.name || 'OpenRGB SDK Server';
    const protocolVersion = configArg.protocolVersion || source?.protocolVersion || source?.controller?.protocolVersion;
    const controller = {
      ...source?.controller,
      ...configArg.controller,
      id: configArg.controller?.id || source?.controller?.id || configArg.entryId || (host ? `${host}:${port}` : name),
      name,
      host,
      port,
      protocolVersion,
      manufacturer: configArg.controller?.manufacturer || source?.controller?.manufacturer || 'OpenRGB',
      model: configArg.controller?.model || source?.controller?.model || 'OpenRGB SDK Server',
      softwareVersion: configArg.controller?.softwareVersion || source?.controller?.softwareVersion || (protocolVersion === undefined ? undefined : `${protocolVersion} (Protocol)`),
    };

    const serverKey = configArg.entryId || controller.id || (host ? `${host}:${port}` : name);
    const devices = this.uniqueDevices([
      ...(source?.devices || []),
      ...(configArg.devices || []),
      ...(configArg.device ? [configArg.device] : []),
      ...this.devicesFromManualEntries(configArg.manualEntries || []),
    ], String(serverKey));

    return {
      connected: connectedArg ?? source?.connected ?? false,
      host,
      port,
      name,
      protocolVersion,
      controller,
      devices,
      profiles: [...new Set([...(source?.profiles || []), ...(configArg.profiles || []), ...this.profilesFromManualEntries(configArg.manualEntries || [])])],
      events: [...(source?.events || []), ...(configArg.events || []), ...eventsArg],
      metadata: {
        ...source?.metadata,
        ...configArg.metadata,
      },
    };
  }

  public static toDevices(snapshotArg: IOpenRGBSnapshot): plugins.shxInterfaces.data.IDeviceDefinition[] {
    const updatedAt = new Date().toISOString();
    const devices: plugins.shxInterfaces.data.IDeviceDefinition[] = [this.controllerDevice(snapshotArg, updatedAt)];
    for (const device of snapshotArg.devices) {
      devices.push(this.openrgbDevice(snapshotArg, device, updatedAt));
      for (const zone of device.zones || []) {
        devices.push(this.zoneDevice(snapshotArg, device, zone, updatedAt));
      }
    }
    return devices;
  }

  public static toEntities(snapshotArg: IOpenRGBSnapshot): IIntegrationEntity[] {
    const entities: IIntegrationEntity[] = [];
    const usedIds = new Map<string, number>();
    if (snapshotArg.profiles.length) {
      const name = `${this.controllerName(snapshotArg)} Profile`;
      entities.push(this.entity('select', name, this.controllerDeviceId(snapshotArg), `openrgb_${this.slug(this.controllerDeviceId(snapshotArg))}_profile`, null, usedIds, {
        options: snapshotArg.profiles,
        currentOption: undefined,
        writable: true,
      }, snapshotArg.connected));
    }

    for (const device of snapshotArg.devices) {
      const info = this.lightInfo(device);
      entities.push(this.lightEntity(snapshotArg, device, undefined, info, usedIds));
      for (const zone of device.zones || []) {
        const zoneInfo = this.lightInfo(device, zone);
        entities.push(this.lightEntity(snapshotArg, device, zone, zoneInfo, usedIds));
      }
    }
    return entities;
  }

  public static toIntegrationEvent(eventArg: IOpenRGBEvent): IIntegrationEvent {
    return {
      type: eventArg.type === 'command_failed' || eventArg.type === 'error' ? 'error' : 'state_changed',
      integrationDomain: 'openrgb',
      deviceId: eventArg.deviceId,
      entityId: eventArg.entityId,
      data: eventArg,
      timestamp: eventArg.timestamp || Date.now(),
    };
  }

  public static commandForService(snapshotArg: IOpenRGBSnapshot, requestArg: IServiceCallRequest): IOpenRGBClientCommand | undefined {
    if (requestArg.domain === 'select' && requestArg.service === 'select_option') {
      const profile = this.stringFromData(requestArg.data, ['option', 'value', 'profile']);
      const targetEntity = this.toEntities(snapshotArg).find((entityArg) => entityArg.id === requestArg.target.entityId || entityArg.uniqueId === requestArg.target.entityId);
      if (profile && targetEntity?.platform === 'select' && targetEntity.attributes?.options && Array.isArray(targetEntity.attributes.options)) {
        return this.command(requestArg, targetEntity, undefined, undefined, [{ action: 'loadProfile', profile }], { profile });
      }
    }

    const target = this.resolveLight(snapshotArg, requestArg);
    if (!target) {
      return undefined;
    }

    if (requestArg.domain !== 'light' && requestArg.domain !== 'select') {
      return undefined;
    }

    if (requestArg.service === 'turn_off') {
      return this.turnOffCommand(requestArg, target);
    }
    if (requestArg.service === 'turn_on') {
      return this.turnOnCommand(requestArg, target);
    }
    if (requestArg.service === 'set_brightness' || requestArg.service === 'set_percentage') {
      const brightness = this.brightnessFromData(requestArg.data, requestArg.service);
      if (brightness === undefined) {
        return undefined;
      }
      if (brightness <= 0) {
        return this.turnOffCommand(requestArg, target);
      }
      return this.turnOnCommand({ ...requestArg, service: 'turn_on', data: { ...requestArg.data, brightness } }, target);
    }
    if (requestArg.service === 'set_color' || requestArg.service === 'set_rgb_color') {
      const rgb = this.rgbFromData(requestArg.data);
      if (!rgb) {
        return undefined;
      }
      return this.turnOnCommand({ ...requestArg, service: 'turn_on', data: { ...requestArg.data, rgb_color: [rgb.red, rgb.green, rgb.blue] } }, target);
    }
    if (requestArg.service === 'select_effect') {
      const effect = this.stringFromData(requestArg.data, ['effect', 'option', 'value']);
      if (!effect) {
        return undefined;
      }
      return this.turnOnCommand({ ...requestArg, service: 'turn_on', data: { ...requestArg.data, effect } }, target);
    }

    return undefined;
  }

  public static deviceKey(snapshotArg: IOpenRGBSnapshot, deviceArg: IOpenRGBDevice): string {
    return deviceArg.key || this.deviceKeyFor(String(snapshotArg.controller.id || snapshotArg.host || snapshotArg.name || 'openrgb'), deviceArg);
  }

  public static deviceId(snapshotArg: IOpenRGBSnapshot, deviceArg: IOpenRGBDevice): string {
    return `openrgb.device.${this.slug(this.deviceKey(snapshotArg, deviceArg))}`;
  }

  private static controllerDevice(snapshotArg: IOpenRGBSnapshot, updatedAtArg: string): plugins.shxInterfaces.data.IDeviceDefinition {
    const features: plugins.shxInterfaces.data.IDeviceFeature[] = [
      { id: 'connectivity', capability: 'sensor', name: 'Connectivity', readable: true, writable: false },
    ];
    const state: plugins.shxInterfaces.data.IDeviceState[] = [
      { featureId: 'connectivity', value: snapshotArg.connected ? 'online' : 'offline', updatedAt: updatedAtArg },
    ];
    if (snapshotArg.protocolVersion !== undefined) {
      features.push({ id: 'protocol_version', capability: 'sensor', name: 'Protocol version', readable: true, writable: false });
      state.push({ featureId: 'protocol_version', value: snapshotArg.protocolVersion, updatedAt: updatedAtArg });
    }
    if (snapshotArg.profiles.length) {
      features.push({ id: 'profile', capability: 'sensor', name: 'Profile', readable: true, writable: true });
      state.push({ featureId: 'profile', value: null, updatedAt: updatedAtArg });
    }
    return {
      id: this.controllerDeviceId(snapshotArg),
      integrationDomain: 'openrgb',
      name: this.controllerName(snapshotArg),
      protocol: 'unknown',
      manufacturer: snapshotArg.controller.manufacturer || 'OpenRGB',
      model: snapshotArg.controller.model || 'OpenRGB SDK Server',
      online: snapshotArg.connected,
      features,
      state,
      metadata: {
        host: snapshotArg.host,
        port: snapshotArg.port || openrgbDefaultPort,
        protocolVersion: snapshotArg.protocolVersion,
        profiles: snapshotArg.profiles,
        ...snapshotArg.controller.metadata,
      },
    };
  }

  private static openrgbDevice(snapshotArg: IOpenRGBSnapshot, deviceArg: IOpenRGBDevice, updatedAtArg: string): plugins.shxInterfaces.data.IDeviceDefinition {
    const info = this.lightInfo(deviceArg);
    const features: plugins.shxInterfaces.data.IDeviceFeature[] = [
      { id: 'availability', capability: 'sensor', name: 'Availability', readable: true, writable: false },
      { id: 'power', capability: 'light', name: 'Power', readable: true, writable: true },
      { id: 'active_mode', capability: 'sensor', name: 'Active mode', readable: true, writable: false },
    ];
    const state: plugins.shxInterfaces.data.IDeviceState[] = [
      { featureId: 'availability', value: deviceArg.available === false ? 'offline' : 'online', updatedAt: updatedAtArg },
      { featureId: 'power', value: info.isOn, updatedAt: updatedAtArg },
      { featureId: 'active_mode', value: info.modeName || null, updatedAt: updatedAtArg },
    ];
    if (info.supportsColor) {
      features.push({ id: 'brightness', capability: 'light', name: 'Brightness', readable: true, writable: true });
      features.push({ id: 'rgb', capability: 'light', name: 'RGB color', readable: true, writable: true });
      this.pushState(state, 'brightness', info.brightness, updatedAtArg);
      this.pushState(state, 'rgb', info.rgbColor, updatedAtArg);
    }
    if (info.effectList.length) {
      features.push({ id: 'effect', capability: 'light', name: 'Effect', readable: true, writable: true });
      this.pushState(state, 'effect', info.effect, updatedAtArg);
    }
    if (deviceArg.zones?.length) {
      features.push({ id: 'zones', capability: 'sensor', name: 'Zones', readable: true, writable: false });
      state.push({ featureId: 'zones', value: deviceArg.zones.length, updatedAt: updatedAtArg });
    }
    const metadata = deviceArg.metadata || {};
    return {
      id: this.deviceId(snapshotArg, deviceArg),
      integrationDomain: 'openrgb',
      name: this.deviceName(deviceArg),
      protocol: 'unknown',
      manufacturer: metadata.vendor || 'OpenRGB',
      model: this.deviceModel(deviceArg),
      online: deviceArg.available !== false,
      features,
      state,
      metadata: {
        openrgbDeviceKey: this.deviceKey(snapshotArg, deviceArg),
        openrgbDeviceIndex: typeof deviceArg.id === 'number' ? deviceArg.id : undefined,
        openrgbType: this.deviceTypeName(deviceArg),
        firmwareVersion: metadata.version,
        serialNumber: metadata.serial,
        location: metadata.location,
        modes: (deviceArg.modes || []).map((modeArg) => modeArg.name),
        effects: info.effectList,
      },
    };
  }

  private static zoneDevice(snapshotArg: IOpenRGBSnapshot, deviceArg: IOpenRGBDevice, zoneArg: IOpenRGBZone, updatedAtArg: string): plugins.shxInterfaces.data.IDeviceDefinition {
    const info = this.lightInfo(deviceArg, zoneArg);
    const zoneId = this.zoneDeviceId(snapshotArg, deviceArg, zoneArg);
    const features: plugins.shxInterfaces.data.IDeviceFeature[] = [
      { id: 'availability', capability: 'sensor', name: 'Availability', readable: true, writable: false },
      { id: 'power', capability: 'light', name: 'Power', readable: true, writable: true },
      { id: 'led_count', capability: 'sensor', name: 'LED count', readable: true, writable: false },
    ];
    const state: plugins.shxInterfaces.data.IDeviceState[] = [
      { featureId: 'availability', value: deviceArg.available === false ? 'offline' : 'online', updatedAt: updatedAtArg },
      { featureId: 'power', value: info.isOn, updatedAt: updatedAtArg },
      { featureId: 'led_count', value: this.zoneLedCount(zoneArg), updatedAt: updatedAtArg },
    ];
    if (info.supportsColor) {
      features.push({ id: 'brightness', capability: 'light', name: 'Brightness', readable: true, writable: true });
      features.push({ id: 'rgb', capability: 'light', name: 'RGB color', readable: true, writable: true });
      this.pushState(state, 'brightness', info.brightness, updatedAtArg);
      this.pushState(state, 'rgb', info.rgbColor, updatedAtArg);
    }
    return {
      id: zoneId,
      integrationDomain: 'openrgb',
      name: this.zoneName(deviceArg, zoneArg),
      protocol: 'unknown',
      manufacturer: deviceArg.metadata?.vendor || 'OpenRGB',
      model: `OpenRGB zone (${zoneArg.typeName || this.zoneTypeName(zoneArg)})`,
      online: deviceArg.available !== false,
      features,
      state,
      metadata: {
        parentDeviceId: this.deviceId(snapshotArg, deviceArg),
        openrgbDeviceKey: this.deviceKey(snapshotArg, deviceArg),
        openrgbDeviceIndex: typeof deviceArg.id === 'number' ? deviceArg.id : undefined,
        openrgbZoneIndex: this.zoneIndex(deviceArg, zoneArg),
        openrgbZoneType: zoneArg.typeName || this.zoneTypeName(zoneArg),
      },
    };
  }

  private static lightEntity(snapshotArg: IOpenRGBSnapshot, deviceArg: IOpenRGBDevice, zoneArg: IOpenRGBZone | undefined, infoArg: ReturnType<typeof OpenRGBMapper.lightInfo>, usedIdsArg: Map<string, number>): IIntegrationEntity {
    const deviceKey = this.deviceKey(snapshotArg, deviceArg);
    const deviceIndex = typeof deviceArg.id === 'number' ? deviceArg.id : undefined;
    const zoneIndex = zoneArg ? this.zoneIndex(deviceArg, zoneArg) : undefined;
    const name = zoneArg ? this.zoneName(deviceArg, zoneArg) : this.deviceName(deviceArg);
    const uniqueId = zoneArg
      ? `openrgb_${this.slug(deviceKey)}_zone_${zoneIndex ?? this.slug(zoneArg.name || 'zone')}_light`
      : `openrgb_${this.slug(deviceKey)}_light`;
    return this.entity('light', name, zoneArg ? this.zoneDeviceId(snapshotArg, deviceArg, zoneArg) : this.deviceId(snapshotArg, deviceArg), uniqueId, infoArg.isOn ? 'on' : 'off', usedIdsArg, {
      openrgbDeviceKey: deviceKey,
      openrgbDeviceIndex: deviceIndex,
      openrgbZoneIndex: zoneIndex,
      openrgbMode: infoArg.modeName,
      brightness: infoArg.brightness,
      rgbColor: infoArg.rgbColor ? [infoArg.rgbColor.red, infoArg.rgbColor.green, infoArg.rgbColor.blue] : undefined,
      colorMode: infoArg.colorMode,
      effect: infoArg.effect,
      effectList: zoneArg ? [] : infoArg.effectList,
      supportedColorModes: infoArg.supportedColorModes,
      preferredNoEffectMode: infoArg.preferredNoEffectMode?.name,
      supportsOffMode: infoArg.supportsOffMode,
      writable: true,
    }, deviceArg.available !== false);
  }

  private static turnOffCommand(requestArg: IServiceCallRequest, targetArg: IOpenRGBResolvedLight): IOpenRGBClientCommand | undefined {
    const operations: TOpenRGBCommandOperation[] = [];
    if (!targetArg.zone && targetArg.info.offMode) {
      operations.push(this.setModeOperation(targetArg.device, targetArg.info.offMode));
    } else {
      const colorOperation = this.setColorOperation(targetArg.device, targetArg.zone, black, 0);
      if (!colorOperation) {
        return undefined;
      }
      operations.push(colorOperation);
    }
    return this.command(requestArg, targetArg.entity, targetArg.device, targetArg.zone, operations, { state: false });
  }

  private static turnOnCommand(requestArg: IServiceCallRequest, targetArg: IOpenRGBResolvedLight): IOpenRGBClientCommand | undefined {
    let mode: IOpenRGBMode | undefined;
    const effect = this.stringFromData(requestArg.data, ['effect', 'option', 'value']);
    if (effect) {
      if (targetArg.zone) {
        return undefined;
      }
      if (effect.toLowerCase() === 'off') {
        mode = targetArg.info.preferredNoEffectMode;
      } else {
        mode = targetArg.info.effectToMode.get(this.slug(effect));
      }
      if (!mode) {
        return undefined;
      }
    } else if (targetArg.info.modeIsOff || (targetArg.info.rgbColor === undefined && targetArg.info.brightness === undefined)) {
      mode = targetArg.info.preferredNoEffectMode;
    }

    let modeForColor = mode || targetArg.info.activeMode;
    let modeSupportsColor = this.modeSupportsColor(modeForColor);
    const requestedBrightness = this.brightnessFromData(requestArg.data, requestArg.service);
    const requestedRgb = this.rgbFromData(requestArg.data);
    const colorOrBrightnessRequested = requestedBrightness !== undefined || requestedRgb !== undefined;
    if (colorOrBrightnessRequested && !modeSupportsColor) {
      return undefined;
    }
    let needColor = colorOrBrightnessRequested || (modeSupportsColor && (targetArg.info.rgbColor === undefined || targetArg.info.brightness === undefined));
    if (needColor && !modeSupportsColor) {
      mode = targetArg.info.preferredNoEffectMode;
      modeForColor = mode || modeForColor;
      modeSupportsColor = this.modeSupportsColor(modeForColor);
      if (!modeSupportsColor) {
        return undefined;
      }
    }

    const operations: TOpenRGBCommandOperation[] = [];
    if (mode) {
      operations.push(this.setModeOperation(targetArg.device, mode));
    }
    if (needColor) {
      const brightness = requestedBrightness ?? targetArg.info.brightness ?? 255;
      const color = requestedRgb ?? targetArg.info.rgbColor ?? white;
      const colorOperation = this.setColorOperation(targetArg.device, targetArg.zone, color, brightness);
      if (!colorOperation) {
        return undefined;
      }
      operations.push(colorOperation);
    }
    if (!operations.length) {
      return undefined;
    }
    return this.command(requestArg, targetArg.entity, targetArg.device, targetArg.zone, operations, {
      state: true,
      effect,
      brightness: requestedBrightness,
      rgb: requestedRgb,
    });
  }

  private static command(requestArg: IServiceCallRequest, entityArg: IIntegrationEntity, deviceArg: IOpenRGBDevice | undefined, zoneArg: IOpenRGBZone | undefined, operationsArg: TOpenRGBCommandOperation[], payloadArg: Record<string, unknown>): IOpenRGBClientCommand {
    return {
      type: 'openrgb.sdk_command',
      service: requestArg.service,
      deviceId: entityArg.deviceId,
      entityId: entityArg.id,
      deviceKey: typeof entityArg.attributes?.openrgbDeviceKey === 'string' ? entityArg.attributes.openrgbDeviceKey : deviceArg?.key,
      zoneId: zoneArg ? String(zoneArg.id ?? zoneArg.name ?? '') : undefined,
      target: requestArg.target,
      operations: operationsArg,
      payload: {
        ...payloadArg,
        data: requestArg.data || {},
      },
    };
  }

  private static setModeOperation(deviceArg: IOpenRGBDevice, modeArg: IOpenRGBMode): TOpenRGBCommandOperation {
    return {
      action: 'setMode',
      deviceIndex: typeof deviceArg.id === 'number' ? deviceArg.id : undefined,
      deviceKey: deviceArg.key,
      modeName: modeArg.name,
      mode: modeArg,
    };
  }

  private static setColorOperation(deviceArg: IOpenRGBDevice, zoneArg: IOpenRGBZone | undefined, colorArg: IOpenRGBRgbColor, brightnessArg: number): TOpenRGBCommandOperation | undefined {
    const ledCount = zoneArg ? this.zoneLedCount(zoneArg) : this.deviceLedCount(deviceArg);
    if (!ledCount) {
      return undefined;
    }
    return {
      action: 'setColor',
      deviceIndex: typeof deviceArg.id === 'number' ? deviceArg.id : undefined,
      deviceKey: deviceArg.key,
      zoneIndex: zoneArg ? this.zoneIndex(deviceArg, zoneArg) : undefined,
      zoneName: zoneArg?.name,
      ledCount,
      rgb: this.scaleColor(colorArg, brightnessArg),
      brightness: brightnessArg,
    };
  }

  private static resolveLight(snapshotArg: IOpenRGBSnapshot, requestArg: IServiceCallRequest): IOpenRGBResolvedLight | undefined {
    const entities = this.toEntities(snapshotArg).filter((entityArg) => entityArg.platform === 'light');
    let entity = requestArg.target.entityId
      ? entities.find((entityArg) => entityArg.id === requestArg.target.entityId || entityArg.uniqueId === requestArg.target.entityId)
      : undefined;
    if (!entity && requestArg.target.deviceId) {
      entity = entities.find((entityArg) => entityArg.deviceId === requestArg.target.deviceId)
        || entities.find((entityArg) => entityArg.attributes?.openrgbDeviceKey === requestArg.target.deviceId);
    }
    if (!entity) {
      entity = entities.find((entityArg) => entityArg.available && entityArg.attributes?.writable === true);
    }
    if (!entity) {
      return undefined;
    }

    const deviceKey = this.stringValue(entity.attributes?.openrgbDeviceKey);
    const device = snapshotArg.devices.find((deviceArg) => this.deviceKey(snapshotArg, deviceArg) === deviceKey || this.deviceId(snapshotArg, deviceArg) === entity?.deviceId);
    if (!device) {
      return undefined;
    }
    const zoneIndex = this.numberValue(entity.attributes?.openrgbZoneIndex);
    const zone = zoneIndex === undefined ? undefined : device.zones?.[zoneIndex];
    return { entity, device, zone, info: this.lightInfo(device, zone) };
  }

  private static lightInfo(deviceArg: IOpenRGBDevice, zoneArg?: IOpenRGBZone): IOpenRGBLightInfo {
    const modes = deviceArg.modes || [];
    const activeMode = this.activeMode(deviceArg);
    const modeName = activeMode?.name;
    const modeIsOff = this.sameName(modeName, openrgbModeOff);
    const supportsColor = !modeIsOff && this.modeSupportsColor(activeMode);
    const colors = zoneArg?.colors?.length ? zoneArg.colors : deviceArg.colors || [];
    const color = colors.find((colorArg) => !this.isBlack(colorArg)) || black;
    const colorDetails = supportsColor && !this.isBlack(color) ? this.colorDetails(color) : {};
    const effectToMode = new Map<string, IOpenRGBMode>();
    for (const mode of modes) {
      if (!this.sameName(mode.name, openrgbModeOff) && !effectOffModes.has(mode.name.toLowerCase())) {
        effectToMode.set(this.slug(mode.name), mode);
      }
    }
    const effectList = [...effectToMode.keys()];
    const effect = !effectList.length || modeIsOff
      ? undefined
      : modeName && effectOffModes.has(modeName.toLowerCase())
        ? 'off'
        : modeName ? this.slug(modeName) : undefined;
    return {
      activeMode,
      modeName,
      modeIsOff,
      supportsColor,
      supportedColorModes: modes.filter((modeArg) => this.modeSupportsColor(modeArg)).map((modeArg) => modeArg.name),
      rgbColor: colorDetails.rgbColor,
      brightness: colorDetails.brightness,
      colorMode: supportsColor ? 'rgb' : modeIsOff ? undefined : 'onoff',
      isOn: modeIsOff ? false : supportsColor ? !this.isBlack(color) : true,
      effect,
      effectList: effectList.length ? ['off', ...effectList] : [],
      effectToMode,
      preferredNoEffectMode: this.preferredNoEffectMode(deviceArg),
      offMode: modes.find((modeArg) => this.sameName(modeArg.name, openrgbModeOff)),
      supportsOffMode: modes.some((modeArg) => this.sameName(modeArg.name, openrgbModeOff)),
    };
  }

  private static devicesFromManualEntries(entriesArg: IOpenRGBManualEntry[]): IOpenRGBDevice[] {
    const devices: IOpenRGBDevice[] = [];
    for (const entry of entriesArg) {
      if (entry.snapshot) {
        devices.push(...entry.snapshot.devices);
      }
      if (entry.devices) {
        devices.push(...entry.devices);
      }
      if (entry.device) {
        devices.push(entry.device);
      }
    }
    return devices;
  }

  private static profilesFromManualEntries(entriesArg: IOpenRGBManualEntry[]): string[] {
    return entriesArg.flatMap((entryArg) => entryArg.snapshot?.profiles || entryArg.profiles || []);
  }

  private static uniqueDevices(devicesArg: IOpenRGBDevice[], serverKeyArg: string): IOpenRGBDevice[] {
    const devices = new Map<string, IOpenRGBDevice>();
    for (const device of devicesArg) {
      const key = device.key || this.deviceKeyFor(serverKeyArg, device);
      const previous = devices.get(key) || {};
      devices.set(key, { ...previous, ...device, key });
    }
    return [...devices.values()];
  }

  private static controllerDeviceId(snapshotArg: IOpenRGBSnapshot): string {
    return `openrgb.controller.${this.slug(String(snapshotArg.controller.id || snapshotArg.host || snapshotArg.name || 'server'))}`;
  }

  private static controllerName(snapshotArg: IOpenRGBSnapshot): string {
    return snapshotArg.name || snapshotArg.controller.name || 'OpenRGB SDK Server';
  }

  private static zoneDeviceId(snapshotArg: IOpenRGBSnapshot, deviceArg: IOpenRGBDevice, zoneArg: IOpenRGBZone): string {
    return `openrgb.zone.${this.slug(this.deviceKey(snapshotArg, deviceArg))}.${this.zoneIndex(deviceArg, zoneArg) ?? this.slug(zoneArg.name || 'zone')}`;
  }

  private static deviceKeyFor(serverKeyArg: string, deviceArg: IOpenRGBDevice): string {
    const metadata = deviceArg.metadata || {};
    return [
      serverKeyArg,
      this.deviceTypeName(deviceArg) || 'unknown',
      metadata.vendor || 'none',
      metadata.description || deviceArg.name || 'none',
      metadata.serial || 'none',
      metadata.location || 'none',
    ].join(openrgbUidSeparator);
  }

  private static deviceName(deviceArg: IOpenRGBDevice): string {
    return deviceArg.name || deviceArg.metadata?.description || (deviceArg.metadata?.serial ? `OpenRGB ${deviceArg.metadata.serial}` : 'OpenRGB device');
  }

  private static zoneName(deviceArg: IOpenRGBDevice, zoneArg: IOpenRGBZone): string {
    return `${this.deviceName(deviceArg)} ${zoneArg.name || `Zone ${this.zoneIndex(deviceArg, zoneArg) ?? ''}`.trim()}`;
  }

  private static deviceModel(deviceArg: IOpenRGBDevice): string {
    const metadata = deviceArg.metadata || {};
    const description = metadata.description || this.deviceTypeName(deviceArg) || 'OpenRGB device';
    const type = this.deviceTypeName(deviceArg);
    return type ? `${description} (${type})` : description;
  }

  private static deviceTypeName(deviceArg: IOpenRGBDevice): string | undefined {
    if (typeof deviceArg.typeName === 'string') {
      return deviceArg.typeName;
    }
    if (typeof deviceArg.type === 'string') {
      return deviceArg.type;
    }
    if (typeof deviceArg.type === 'number') {
      return deviceTypeNames[deviceArg.type] || 'unknown';
    }
    return undefined;
  }

  private static zoneTypeName(zoneArg: IOpenRGBZone): string | undefined {
    if (typeof zoneArg.typeName === 'string') {
      return zoneArg.typeName;
    }
    if (typeof zoneArg.type === 'string') {
      return zoneArg.type;
    }
    if (typeof zoneArg.type === 'number') {
      return zoneTypeNames[zoneArg.type] || 'unknown';
    }
    return undefined;
  }

  private static activeMode(deviceArg: IOpenRGBDevice): IOpenRGBMode | undefined {
    const active = deviceArg.activeMode;
    const modes = deviceArg.modes || [];
    if (typeof active === 'number') {
      return modes[active] || modes.find((modeArg) => modeArg.id === active);
    }
    if (typeof active === 'string') {
      return modes.find((modeArg) => this.sameName(modeArg.name, active));
    }
    return modes[0];
  }

  private static preferredNoEffectMode(deviceArg: IOpenRGBDevice): IOpenRGBMode | undefined {
    const modes = deviceArg.modes || [];
    const findMode = (nameArg: string) => modes.find((modeArg) => this.sameName(modeArg.name, nameArg));
    if (deviceArg.metadata?.description === 'ASRock Polychrome USB Device') {
      return findMode(openrgbModeStatic) || findMode(openrgbModeDirect) || findMode(openrgbModeCustom);
    }
    return findMode(openrgbModeDirect) || findMode(openrgbModeCustom) || findMode(openrgbModeStatic);
  }

  private static modeSupportsColor(modeArg: IOpenRGBMode | undefined): boolean {
    if (!modeArg) {
      return false;
    }
    if (modeArg.supportsColor === true) {
      return true;
    }
    if (typeof modeArg.colorMode === 'number') {
      return modeArg.colorMode === 1;
    }
    if (typeof modeArg.colorMode === 'string') {
      const colorMode = modeArg.colorMode.toLowerCase().replace(/[-\s]+/g, '_');
      return colorMode === 'per_led' || colorMode === 'perled';
    }
    return typeof modeArg.flags === 'number' && (modeArg.flags & (1 << 5)) !== 0;
  }

  private static zoneIndex(deviceArg: IOpenRGBDevice, zoneArg: IOpenRGBZone): number | undefined {
    if (typeof zoneArg.id === 'number') {
      return zoneArg.id;
    }
    const index = (deviceArg.zones || []).indexOf(zoneArg);
    return index >= 0 ? index : undefined;
  }

  private static deviceLedCount(deviceArg: IOpenRGBDevice): number {
    if (deviceArg.colors?.length) {
      return deviceArg.colors.length;
    }
    if (deviceArg.leds?.length) {
      return deviceArg.leds.length;
    }
    return (deviceArg.zones || []).reduce((sumArg, zoneArg) => sumArg + this.zoneLedCount(zoneArg), 0);
  }

  private static zoneLedCount(zoneArg: IOpenRGBZone): number {
    return zoneArg.numLeds || zoneArg.colors?.length || zoneArg.leds?.length || 0;
  }

  private static colorDetails(colorArg: IOpenRGBRgbColor): { rgbColor?: IOpenRGBRgbColor; brightness?: number } {
    const brightness = Math.max(colorArg.red, colorArg.green, colorArg.blue);
    if (brightness <= 0) {
      return {};
    }
    return {
      brightness,
      rgbColor: {
        red: this.clamp(Math.round(colorArg.red / brightness * 255), 0, 255),
        green: this.clamp(Math.round(colorArg.green / brightness * 255), 0, 255),
        blue: this.clamp(Math.round(colorArg.blue / brightness * 255), 0, 255),
      },
    };
  }

  private static scaleColor(colorArg: IOpenRGBRgbColor, brightnessArg: number): IOpenRGBRgbColor {
    const factor = this.clamp(brightnessArg, 0, 255) / 255;
    return {
      red: this.clamp(Math.round(colorArg.red * factor), 0, 255),
      green: this.clamp(Math.round(colorArg.green * factor), 0, 255),
      blue: this.clamp(Math.round(colorArg.blue * factor), 0, 255),
    };
  }

  private static rgbFromData(dataArg: Record<string, unknown> | undefined): IOpenRGBRgbColor | undefined {
    const value = this.valueFromData(dataArg, ['rgb_color', 'rgb', 'color']);
    if (Array.isArray(value) && value.length >= 3) {
      const numbers = value.slice(0, 3).map((entryArg) => this.byteValue(entryArg));
      return numbers.every((entryArg) => entryArg !== undefined)
        ? { red: numbers[0]!, green: numbers[1]!, blue: numbers[2]! }
        : undefined;
    }
    if (this.isRecord(value)) {
      const red = this.byteValue(value.red ?? value.r);
      const green = this.byteValue(value.green ?? value.g);
      const blue = this.byteValue(value.blue ?? value.b);
      return red !== undefined && green !== undefined && blue !== undefined ? { red, green, blue } : undefined;
    }
    return undefined;
  }

  private static brightnessFromData(dataArg: Record<string, unknown> | undefined, serviceArg: string): number | undefined {
    const percentage = this.numberFromData(dataArg, ['brightness_pct', 'percentage', 'percent']);
    if (percentage !== undefined) {
      return this.clamp(Math.round(percentage / 100 * 255), 0, 255);
    }
    const value = this.numberFromData(dataArg, serviceArg === 'set_percentage' ? ['value'] : ['brightness', 'value']);
    return value === undefined ? undefined : this.clamp(Math.round(value), 0, 255);
  }

  private static entity(platformArg: TEntityPlatform, nameArg: string, deviceIdArg: string, uniqueIdArg: string, stateArg: unknown, usedIdsArg: Map<string, number>, attributesArg: Record<string, unknown>, availableArg: boolean): IIntegrationEntity {
    return {
      id: this.entityId(platformArg, nameArg, usedIdsArg),
      uniqueId: uniqueIdArg,
      integrationDomain: 'openrgb',
      deviceId: deviceIdArg,
      platform: platformArg,
      name: nameArg,
      state: stateArg,
      attributes: attributesArg,
      available: availableArg,
    };
  }

  private static entityId(platformArg: TEntityPlatform, nameArg: string, usedIdsArg: Map<string, number>): string {
    const base = `${platformArg}.${this.slug(nameArg)}`;
    const count = usedIdsArg.get(base) || 0;
    usedIdsArg.set(base, count + 1);
    return count ? `${base}_${count + 1}` : base;
  }

  private static pushState(stateArg: plugins.shxInterfaces.data.IDeviceState[], featureIdArg: string, valueArg: unknown, updatedAtArg: string): void {
    if (valueArg === undefined) {
      return;
    }
    stateArg.push({ featureId: featureIdArg, value: this.deviceStateValue(valueArg), updatedAt: updatedAtArg });
  }

  private static deviceStateValue(valueArg: unknown): plugins.shxInterfaces.data.TDeviceStateValue {
    if (typeof valueArg === 'string' || typeof valueArg === 'number' || typeof valueArg === 'boolean' || valueArg === null || this.isRecord(valueArg)) {
      return valueArg;
    }
    if (Array.isArray(valueArg)) {
      return { values: valueArg };
    }
    return valueArg === undefined ? null : String(valueArg);
  }

  private static isBlack(colorArg: IOpenRGBRgbColor): boolean {
    return colorArg.red <= 0 && colorArg.green <= 0 && colorArg.blue <= 0;
  }

  private static sameName(leftArg: string | undefined, rightArg: string): boolean {
    return (leftArg || '').toLowerCase() === rightArg.toLowerCase();
  }

  private static valueFromData(dataArg: Record<string, unknown> | undefined, keysArg: string[]): unknown {
    for (const key of keysArg) {
      if (dataArg && key in dataArg) {
        return dataArg[key];
      }
    }
    return undefined;
  }

  private static numberFromData(dataArg: Record<string, unknown> | undefined, keysArg: string[]): number | undefined {
    const value = this.valueFromData(dataArg, keysArg);
    return this.numberValue(value);
  }

  private static stringFromData(dataArg: Record<string, unknown> | undefined, keysArg: string[]): string | undefined {
    const value = this.valueFromData(dataArg, keysArg);
    return this.stringValue(value);
  }

  private static byteValue(valueArg: unknown): number | undefined {
    if (typeof valueArg !== 'number' || !Number.isFinite(valueArg)) {
      return undefined;
    }
    return this.clamp(Math.round(valueArg), 0, 255);
  }

  private static numberValue(valueArg: unknown): number | undefined {
    return typeof valueArg === 'number' && Number.isFinite(valueArg) ? valueArg : undefined;
  }

  private static stringValue(valueArg: unknown): string | undefined {
    return typeof valueArg === 'string' && valueArg.trim() ? valueArg.trim() : undefined;
  }

  private static slug(valueArg: string): string {
    return valueArg.toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '') || 'openrgb';
  }

  private static clamp(valueArg: number, minArg: number, maxArg: number): number {
    return Math.max(minArg, Math.min(maxArg, valueArg));
  }

  private static isRecord(valueArg: unknown): valueArg is Record<string, unknown> {
    return typeof valueArg === 'object' && valueArg !== null && !Array.isArray(valueArg);
  }
}
