import * as path from 'path';
import * as fs from 'fs';
import { cloneObject, emit } from './utils';

// считывает камеры (РАБОТАЕТ ТОЛЬКО НА ФРОНТЕНДЕ)
const getCameras = async (): Promise<MediaDeviceInfo[]> => {
  if (globalThis.window) {
    const devices = await window.navigator.mediaDevices.enumerateDevices();
    const cameras = devices.filter((device) => device.kind === 'videoinput');

    emit('info', 'информация о периферии устройства получена');

    return cameras;
  } else {
    emit('error', 'невозможно получить информацию о камерах');
    return [];
  }
};

// создаёт часть конфига с камерами
const addCamerasInConfig = async (config: Config): Promise<DynamicObject> => {
  const cameras: Option[] = (await getCameras()).map((camera) => ({
    value: camera.deviceId,
    name: camera.label,
    chosen: false,
  }));

  const camerasConfigPattern = JSON.parse(
    fs.readFileSync(path.join(__dirname, './cameraConfigPattern.json'), {
      encoding: 'utf-8',
    }),
  );

  const camerasInConfig = config.united?.devices?.value?.camera?.value;
  const camerasConfig: DynamicObject = camerasInConfig
    ? cloneObject(camerasInConfig)
    : camerasConfigPattern;

  if (cameras.length === 0) {
    return camerasConfig;
  }

  if (
    camerasConfig?.front_camera?.value?.selected_camera?.value?.length === 1 &&
    camerasConfig?.back_camera?.value?.selected_camera?.value?.length === 1
  ) {
    cameras.unshift({ value: 'none', name: 'не выбрано', chosen: true });

    camerasConfig.front_camera.value.selected_camera.value = cloneObject(cameras);
    camerasConfig.back_camera.value.selected_camera.value = cameras;
  } else {
    const selectedFrontCamera: Option =
      camerasConfig.front_camera.value.selected_camera.value.find(
        (camera: Option) => camera.chosen,
      );
    const selectedBackCamera: Option =
      camerasConfig.back_camera.value.selected_camera.value.find(
        (camera: Option) => camera.chosen,
      );

    camerasConfig.front_camera.value.selected_camera.value = syncCameras(
      cameras,
      selectedFrontCamera,
    );
    camerasConfig.back_camera.value.selected_camera.value = syncCameras(
      cameras,
      selectedBackCamera,
    );
  }

  emit('info', 'камеры успешно обновлены');

  return camerasConfig;
};

// сверяет старые камеры с новыми
const syncCameras = (cameras: Option[], currentCamera: Option) => {
  const camerasCopy: Option[] = cloneObject(cameras);
  const selectedCamera = camerasCopy.find(
    (camera) =>
      camera.name === currentCamera.name || camera.value === currentCamera.value,
  );

  if (
    !selectedCamera &&
    currentCamera.value !== 'none' &&
    currentCamera.name !== 'не выбрано'
  ) {
    camerasCopy[0].chosen = false;
    currentCamera.disabled = true;
    camerasCopy.push(currentCamera);
  } else {
    if (selectedCamera) {
      camerasCopy[0].chosen = false;
      selectedCamera.chosen = true;
    }
  }

  camerasCopy.unshift({
    name: 'не выбрано',
    value: 'none',
    chosen: currentCamera.value === 'none',
  });

  return camerasCopy;
};

export default addCamerasInConfig;
