// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media_perception/proto_mojom_conversion.h"

#include <utility>
#include <vector>

namespace chromeos {
namespace media_perception {
namespace mojom {

SuccessStatusPtr ToMojom(const mri::SuccessStatus& status) {
  SuccessStatusPtr status_ptr = SuccessStatus::New();
  status_ptr->success = status.success();
  status_ptr->failure_reason = status.failure_reason();
  return status_ptr;
}

PixelFormat ToMojom(mri::PixelFormat format) {
  switch (format) {
    case mri::PixelFormat::I420:
      return PixelFormat::I420;
    case mri::PixelFormat::MJPEG:
      return PixelFormat::MJPEG;
    case mri::PixelFormat::FORMAT_UNKNOWN:
      return PixelFormat::FORMAT_UNKNOWN;
  }
  return PixelFormat::FORMAT_UNKNOWN;
}

VideoStreamParamsPtr ToMojom(const mri::VideoStreamParams& params) {
  VideoStreamParamsPtr params_ptr = VideoStreamParams::New();
  params_ptr->width_in_pixels = params.width_in_pixels();
  params_ptr->height_in_pixels = params.height_in_pixels();
  params_ptr->frame_rate_in_frames_per_second =
      params.frame_rate_in_frames_per_second();
  params_ptr->pixel_format = ToMojom(params.pixel_format());
  return params_ptr;
}

VideoDevicePtr ToMojom(const mri::VideoDevice& device) {
  VideoDevicePtr device_ptr = VideoDevice::New();
  device_ptr->id = device.id();
  device_ptr->display_name = device.display_name();
  device_ptr->model_id = device.model_id();
  std::vector<VideoStreamParamsPtr> supported_configurations;
  for (const mri::VideoStreamParams& params :
       device.supported_configurations()) {
    supported_configurations.push_back(ToMojom(params));
  }
  device_ptr->supported_configurations = std::move(supported_configurations);
  if (device.has_configuration()) {
    device_ptr->configuration = ToMojom(device.configuration());
  }
  device_ptr->in_use = device.in_use();
  return device_ptr;
}

VirtualVideoDevicePtr ToMojom(const mri::VirtualVideoDevice& device) {
  VirtualVideoDevicePtr device_ptr = VirtualVideoDevice::New();
  if (device.has_video_device())
    device_ptr->video_device = ToMojom(device.video_device());
  return device_ptr;
}

SampleFormat ToMojom(mri::SampleFormat format) {
  switch (format) {
    case mri::SampleFormat::SND_PCM_FORMAT_S32_LE:
      return SampleFormat::SND_PCM_FORMAT_S32_LE;
    case mri::SampleFormat::SND_PCM_FORMAT_S16_LE:
      return SampleFormat::SND_PCM_FORMAT_S16_LE;
    case mri::SampleFormat::SND_PCM_UNKNOWN_FORMAT:
      return SampleFormat::SND_PCM_UNKNOWN_FORMAT;
  }
  return SampleFormat::SND_PCM_UNKNOWN_FORMAT;
}

AudioStreamParamsPtr ToMojom(const mri::AudioStreamParams& params) {
  AudioStreamParamsPtr params_ptr = AudioStreamParams::New();
  params_ptr->frequency_in_hz = params.frequency_in_hz();
  params_ptr->num_channels = params.num_channels();
  params_ptr->frame_size = params.frame_size();
  params_ptr->sample_format = ToMojom(params.sample_format());
  return params_ptr;
}

AudioDevicePtr ToMojom(const mri::AudioDevice& device) {
  AudioDevicePtr device_ptr = AudioDevice::New();
  device_ptr->id = device.id();
  device_ptr->display_name = device.display_name();
  std::vector<AudioStreamParamsPtr> supported_configurations;
  for (const mri::AudioStreamParams& params :
       device.supported_configurations()) {
    supported_configurations.push_back(ToMojom(params));
  }
  device_ptr->supported_configurations = std::move(supported_configurations);
  if (device.has_configuration()) {
    device_ptr->configuration = ToMojom(device.configuration());
  }
  return device_ptr;
}

DeviceType ToMojom(mri::DeviceType type) {
  switch (type) {
    case mri::DeviceType::VIDEO:
      return DeviceType::VIDEO;
    case mri::DeviceType::AUDIO:
      return DeviceType::AUDIO;
    case mri::DeviceType::VIRTUAL_VIDEO:
      return DeviceType::VIRTUAL_VIDEO;
    case mri::DeviceType::DEVICE_TYPE_UNKNOWN:
      return DeviceType::TYPE_UNKNOWN;
  }
  return DeviceType::TYPE_UNKNOWN;
}

DeviceTemplatePtr ToMojom(const mri::DeviceTemplate& device_template) {
  DeviceTemplatePtr template_ptr = DeviceTemplate::New();
  template_ptr->template_name = device_template.template_name();
  template_ptr->device_type = ToMojom(device_template.device_type());
  return template_ptr;
}

DistanceUnits ToMojom(mri::DistanceUnits units) {
  switch (units) {
    case mri::DistanceUnits::METERS:
      return DistanceUnits::METERS;
    case mri::DistanceUnits::PIXELS:
      return DistanceUnits::PIXELS;
    case mri::DistanceUnits::UNITS_UNKNOWN:
      return DistanceUnits::UNITS_UNKNOWN;
  }
  return DistanceUnits::UNITS_UNKNOWN;
}

NormalizedBoundingBoxPtr ToMojom(const mri::NormalizedBoundingBox& bbox) {
  NormalizedBoundingBoxPtr bbox_ptr = NormalizedBoundingBox::New();
  bbox_ptr->x_min = bbox.x_min();
  bbox_ptr->y_min = bbox.y_min();
  bbox_ptr->x_max = bbox.x_max();
  bbox_ptr->y_max = bbox.y_max();
  bbox_ptr->normalization_width = bbox.normalization_width();
  bbox_ptr->normalization_height = bbox.normalization_height();
  return bbox_ptr;
}

DistancePtr ToMojom(const mri::Distance& distance) {
  DistancePtr distance_ptr = Distance::New();
  distance_ptr->units = ToMojom(distance.units());
  distance_ptr->magnitude = distance.magnitude();
  return distance_ptr;
}

HotwordType ToMojom(mri::HotwordType type) {
  switch (type) {
    case mri::HotwordType::OK_GOOGLE:
      return HotwordType::OK_GOOGLE;
    case mri::HotwordType::HOTWORD_TYPE_UNKNOWN:
      return HotwordType::HOTWORD_TYPE_UNKNOWN;
  }
  return HotwordType::HOTWORD_TYPE_UNKNOWN;
}

HotwordPtr ToMojom(const mri::Hotword& hotword) {
  HotwordPtr hotword_ptr = Hotword::New();
  hotword_ptr->type = ToMojom(hotword.type());
  hotword_ptr->start_timestamp_ms = hotword.start_timestamp_ms();
  hotword_ptr->end_timestamp_ms = hotword.end_timestamp_ms();
  return hotword_ptr;
}

HotwordDetectionPtr ToMojom(const mri::HotwordDetection& hotword_detection) {
  HotwordDetectionPtr hotword_detection_ptr = HotwordDetection::New();
  for (int i = 0; i < hotword_detection.hotwords_size(); ++i) {
    hotword_detection_ptr->hotwords.push_back(
        ToMojom(hotword_detection.hotwords(i)));
  }
  return hotword_detection_ptr;
}

EntityType ToMojom(mri::EntityType type) {
  switch (type) {
    case mri::EntityType::FACE:
      return EntityType::FACE;
    case mri::EntityType::PERSON:
      return EntityType::PERSON;
    case mri::EntityType::MOTION_REGION:
      return EntityType::MOTION_REGION;
    case mri::EntityType::LABELED_REGION:
      return EntityType::LABELED_REGION;
    case mri::EntityType::ENTITY_TYPE_UNKNOWN:
      return EntityType::ENTITY_TYPE_UNKNOWN;
  }
  return EntityType::ENTITY_TYPE_UNKNOWN;
}

FramePerceptionType ToMojom(mri::FramePerceptionType type) {
  switch (type) {
    case mri::FramePerceptionType::FACE_DETECTION:
      return FramePerceptionType::FACE_DETECTION;
    case mri::FramePerceptionType::PERSON_DETECTION:
      return FramePerceptionType::PERSON_DETECTION;
    case mri::FramePerceptionType::MOTION_DETECTION:
      return FramePerceptionType::MOTION_DETECTION;
    case mri::FramePerceptionType::FRAME_PERCEPTION_TYPE_UNKNOWN:
      return FramePerceptionType::FRAME_PERCEPTION_TYPE_UNKNOWN;
  }
  return FramePerceptionType::FRAME_PERCEPTION_TYPE_UNKNOWN;
}

EntityPtr ToMojom(const mri::Entity& entity) {
  EntityPtr entity_ptr = Entity::New();
  entity_ptr->type = ToMojom(entity.type());
  entity_ptr->label = entity.label();
  entity_ptr->bounding_box = ToMojom(entity.bounding_box());
  entity_ptr->confidence = entity.confidence();
  entity_ptr->depth = ToMojom(entity.depth());
  return entity_ptr;
}

FramePerceptionPtr ToMojom(const mri::FramePerception& perception) {
  FramePerceptionPtr perception_ptr = FramePerception::New();
  perception_ptr->frame_id = perception.frame_id();
  perception_ptr->timestamp_us = perception.timestamp_us();

  for (int i = 0; i < perception.entities_size(); ++i) {
    perception_ptr->entities.push_back(ToMojom(perception.entities(i)));
  }

  for (int i = 0; i < perception.perception_types_size(); ++i) {
    perception_ptr->perception_types.push_back(
        ToMojom(perception.perception_types(i)));
  }

  return perception_ptr;
}

PipelineStatus ToMojom(mri::PipelineStatus status) {
  switch (status) {
    case mri::PipelineStatus::STARTED:
      return PipelineStatus::STARTED;
    case mri::PipelineStatus::RUNNING:
      return PipelineStatus::RUNNING;
    case mri::PipelineStatus::SUSPENDED:
      return PipelineStatus::SUSPENDED;
    case mri::PipelineStatus::ERROR:
      return PipelineStatus::ERROR;
    case mri::PIPELINE_STATUS_UNKNOWN:
      return PipelineStatus::UNKNOWN;
  }
  return PipelineStatus::UNKNOWN;
}

PipelineErrorType ToMojom(mri::PipelineErrorType error_type) {
  switch (error_type) {
    case mri::PipelineErrorType::CONFIGURATION:
      return PipelineErrorType::CONFIGURATION;
    case mri::PipelineErrorType::STARTUP:
      return PipelineErrorType::STARTUP;
    case mri::PipelineErrorType::RUNTIME:
      return PipelineErrorType::RUNTIME;
    case mri::PipelineErrorType::CONTENT:
      return PipelineErrorType::CONTENT;
    case mri::PIPELINE_ERROR_TYPE_UNKNOWN:
      return PipelineErrorType::UNKNOWN;
  }
  return PipelineErrorType::UNKNOWN;
}

PipelineErrorPtr ToMojom(const mri::PipelineError& error) {
  PipelineErrorPtr error_ptr = PipelineError::New();
  error_ptr->error_type = ToMojom(error.error_type());
  error_ptr->error_source = error.error_source();
  error_ptr->error_string = error.error_string();
  return error_ptr;
}

PipelineStatePtr ToMojom(const mri::PipelineState& state) {
  PipelineStatePtr state_ptr = PipelineState::New();
  state_ptr->status = ToMojom(state.status());
  state_ptr->error = ToMojom(state.error());
  state_ptr->configuration_name = state.configuration_name();
  return state_ptr;
}

GlobalPipelineStatePtr ToMojom(const mri::GlobalPipelineState& state) {
  GlobalPipelineStatePtr state_ptr = GlobalPipelineState::New();
  std::vector<PipelineStatePtr> states;
  for (const mri::PipelineState& pipeline_state : state.states()) {
    states.push_back(ToMojom(pipeline_state));
  }
  state_ptr->states = std::move(states);
  return state_ptr;
}

PresencePerceptionPtr ToMojom(const mri::PresencePerception& perception) {
  PresencePerceptionPtr perception_ptr = PresencePerception::New();
  perception_ptr->timestamp_us = perception.timestamp_us();
  perception_ptr->presence_confidence = perception.presence_confidence();
  return perception_ptr;
}

OccupancyTriggerPtr ToMojom(const mri::OccupancyTrigger& occupancy_trigger) {
  OccupancyTriggerPtr occupancy_ptr = OccupancyTrigger::New();
  occupancy_ptr->trigger = occupancy_trigger.trigger();
  occupancy_ptr->timestamp_ms = occupancy_trigger.timestamp_ms();
  return occupancy_ptr;
}

}  // namespace mojom
}  // namespace media_perception
}  // namespace chromeos

namespace mri {

SuccessStatus ToProto(
    const chromeos::media_perception::mojom::SuccessStatusPtr& status_ptr) {
  SuccessStatus status;
  if (status_ptr.is_null())
    return status;
  status.set_success(status_ptr->success);
  status.set_failure_reason(*status_ptr->failure_reason);
  return status;
}

PixelFormat ToProto(
    chromeos::media_perception::mojom::PixelFormat format) {
  switch (format) {
    case chromeos::media_perception::mojom::PixelFormat::I420:
      return PixelFormat::I420;
    case chromeos::media_perception::mojom::PixelFormat::MJPEG:
      return PixelFormat::MJPEG;
    case chromeos::media_perception::mojom::PixelFormat::FORMAT_UNKNOWN:
      return PixelFormat::FORMAT_UNKNOWN;
  }
  return PixelFormat::FORMAT_UNKNOWN;
}

VideoStreamParams ToProto(
    const chromeos::media_perception::mojom::VideoStreamParamsPtr& params_ptr) {
  VideoStreamParams params;
  if (params_ptr.is_null())
    return params;
  params.set_width_in_pixels(params_ptr->width_in_pixels);
  params.set_height_in_pixels(params_ptr->height_in_pixels);
  params.set_frame_rate_in_frames_per_second(
      params_ptr->frame_rate_in_frames_per_second);
  params.set_pixel_format(
      ToProto(params_ptr->pixel_format));
  return params;
}

VideoDevice ToProto(
    const chromeos::media_perception::mojom::VideoDevicePtr& device_ptr) {
  VideoDevice device;
  if (device_ptr.is_null())
    return device;
  device.set_id(device_ptr->id);
  device.set_display_name(*device_ptr->display_name);
  device.set_model_id(*device_ptr->model_id);
  for (int i = 0; i < device_ptr->supported_configurations.size(); i++) {
    mri::VideoStreamParams* params = device.add_supported_configurations();
    *params = ToProto(device_ptr->supported_configurations[i]);
  }
  if (!device_ptr->configuration.is_null()) {
    mri::VideoStreamParams* params = device.mutable_configuration();
    *params = ToProto(device_ptr->configuration);
  }
  device.set_in_use(device_ptr->in_use);
  return device;
}

VirtualVideoDevice ToProto(
    const chromeos::media_perception::mojom::VirtualVideoDevicePtr&
    device_ptr) {
  VirtualVideoDevice device;
  if (device_ptr.is_null())
    return device;

  VideoDevice* video_device = device.mutable_video_device();
  *video_device = ToProto(device_ptr->video_device);
  return device;
}

SampleFormat ToProto(
    chromeos::media_perception::mojom::SampleFormat format) {
  switch (format) {
    case chromeos::media_perception::mojom::SampleFormat::SND_PCM_FORMAT_S32_LE:
      return SampleFormat::SND_PCM_FORMAT_S32_LE;
    case chromeos::media_perception::mojom::SampleFormat::SND_PCM_FORMAT_S16_LE:
      return SampleFormat::SND_PCM_FORMAT_S16_LE;
    case chromeos::media_perception::mojom::SampleFormat
        ::SND_PCM_UNKNOWN_FORMAT:
      return SampleFormat::SND_PCM_UNKNOWN_FORMAT;
  }
  return SampleFormat::SND_PCM_UNKNOWN_FORMAT;
}

AudioStreamParams ToProto(
    const chromeos::media_perception::mojom::AudioStreamParamsPtr&
    params_ptr) {
  AudioStreamParams params;
  if (params_ptr.is_null())
    return params;

  params.set_frequency_in_hz(params_ptr->frequency_in_hz);
  params.set_num_channels(params_ptr->num_channels);
  params.set_frame_size(params_ptr->frame_size);
  params.set_sample_format(ToProto(params_ptr->sample_format));
  return params;
}

AudioDevice ToProto(
    const chromeos::media_perception::mojom::AudioDevicePtr& device_ptr) {
  AudioDevice device;
  if (device_ptr.is_null())
    return device;

  device.set_id(device_ptr->id);
  device.set_display_name(*device_ptr->display_name);
  for (int i = 0; i < device_ptr->supported_configurations.size(); i++) {
    mri::AudioStreamParams* params = device.add_supported_configurations();
    *params = ToProto(device_ptr->supported_configurations[i]);
  }
  if (!device_ptr->configuration.is_null()) {
    mri::AudioStreamParams* params = device.mutable_configuration();
    *params = ToProto(device_ptr->configuration);
  }
  return device;
}

DeviceType ToProto(
    const chromeos::media_perception::mojom::DeviceType type) {
  switch (type) {
    case chromeos::media_perception::mojom::DeviceType::VIDEO:
      return DeviceType::VIDEO;
    case chromeos::media_perception::mojom::DeviceType::AUDIO:
      return DeviceType::AUDIO;
    case chromeos::media_perception::mojom::DeviceType::VIRTUAL_VIDEO:
      return DeviceType::VIRTUAL_VIDEO;
    case chromeos::media_perception::mojom::DeviceType::TYPE_UNKNOWN:
      return DeviceType::DEVICE_TYPE_UNKNOWN;
  }
  return DeviceType::DEVICE_TYPE_UNKNOWN;
}

DeviceTemplate ToProto(
    const chromeos::media_perception::mojom::DeviceTemplatePtr& template_ptr) {
  DeviceTemplate device_template;
  if (template_ptr.is_null())
    return device_template;

  device_template.set_template_name(template_ptr->template_name);
  device_template.set_device_type(ToProto(template_ptr->device_type));
  return device_template;
}

DistanceUnits ToProto(chromeos::media_perception::mojom::DistanceUnits units) {
  switch (units) {
    case chromeos::media_perception::mojom::DistanceUnits::METERS:
      return DistanceUnits::METERS;
    case chromeos::media_perception::mojom::DistanceUnits::PIXELS:
      return DistanceUnits::PIXELS;
    case chromeos::media_perception::mojom::DistanceUnits::UNITS_UNKNOWN:
      return DistanceUnits::UNITS_UNKNOWN;
  }
  return DistanceUnits::UNITS_UNKNOWN;
}

NormalizedBoundingBox ToProto(
    const chromeos::media_perception::mojom::NormalizedBoundingBoxPtr&
        bbox_ptr) {
  NormalizedBoundingBox bbox;
  if (bbox_ptr.is_null())
    return bbox;

  bbox.set_x_min(bbox_ptr->x_min);
  bbox.set_y_min(bbox_ptr->y_min);
  bbox.set_x_max(bbox_ptr->x_max);
  bbox.set_y_max(bbox_ptr->y_max);
  bbox.set_normalization_width(bbox_ptr->normalization_width);
  bbox.set_normalization_height(bbox_ptr->normalization_height);
  return bbox;
}

Distance ToProto(
    const chromeos::media_perception::mojom::DistancePtr& distance_ptr) {
  Distance distance;
  if (distance_ptr.is_null())
    return distance;

  distance.set_units(ToProto(distance_ptr->units));
  distance.set_magnitude(distance_ptr->magnitude);
  return distance;
}

HotwordType ToProto(chromeos::media_perception::mojom::HotwordType type) {
  switch (type) {
    case chromeos::media_perception::mojom::HotwordType::OK_GOOGLE:
      return HotwordType::OK_GOOGLE;
    case chromeos::media_perception::mojom::HotwordType::HOTWORD_TYPE_UNKNOWN:
      return HotwordType::HOTWORD_TYPE_UNKNOWN;
  }
  return HotwordType::HOTWORD_TYPE_UNKNOWN;
}

Hotword ToProto(
    const chromeos::media_perception::mojom::HotwordPtr& hotword_ptr) {
  Hotword hotword;
  if (hotword_ptr.is_null())
    return hotword;

  hotword.set_type(ToProto(hotword_ptr->type));
  hotword.set_start_timestamp_ms(hotword_ptr->start_timestamp_ms);
  hotword.set_end_timestamp_ms(hotword_ptr->end_timestamp_ms);
  return hotword;
}

HotwordDetection ToProto(
    const chromeos::media_perception::mojom::HotwordDetectionPtr&
        hotword_detection_ptr) {
  HotwordDetection hotword_detection;
  if (hotword_detection_ptr.is_null())
    return hotword_detection;

  for (const auto& hotword : hotword_detection_ptr->hotwords)
    *hotword_detection.add_hotwords() = ToProto(hotword);

  return hotword_detection;
}

EntityType ToProto(chromeos::media_perception::mojom::EntityType type) {
  switch (type) {
    case chromeos::media_perception::mojom::EntityType::FACE:
      return EntityType::FACE;
    case chromeos::media_perception::mojom::EntityType::PERSON:
      return EntityType::PERSON;
    case chromeos::media_perception::mojom::EntityType::MOTION_REGION:
      return EntityType::MOTION_REGION;
    case chromeos::media_perception::mojom::EntityType::LABELED_REGION:
      return EntityType::LABELED_REGION;
    case chromeos::media_perception::mojom::EntityType::ENTITY_TYPE_UNKNOWN:
      return EntityType::ENTITY_TYPE_UNKNOWN;
  }
  return EntityType::ENTITY_TYPE_UNKNOWN;
}

FramePerceptionType ToProto(
    chromeos::media_perception::mojom::FramePerceptionType type) {
  switch (type) {
    case chromeos::media_perception::mojom::FramePerceptionType::FACE_DETECTION:
      return FramePerceptionType::FACE_DETECTION;
    case chromeos::media_perception::mojom::FramePerceptionType
        ::PERSON_DETECTION:
      return FramePerceptionType::PERSON_DETECTION;
    case chromeos::media_perception::mojom::FramePerceptionType
        ::MOTION_DETECTION:
      return FramePerceptionType::MOTION_DETECTION;
    case chromeos::media_perception::mojom::FramePerceptionType
        ::FRAME_PERCEPTION_TYPE_UNKNOWN:
      return FramePerceptionType::FRAME_PERCEPTION_TYPE_UNKNOWN;
  }
  return FramePerceptionType::FRAME_PERCEPTION_TYPE_UNKNOWN;
}

Entity ToProto(const chromeos::media_perception::mojom::EntityPtr& entity_ptr) {
  Entity entity;
  if (entity_ptr.is_null())
    return entity;

  entity.set_type(ToProto(entity_ptr->type));
  entity.set_label(*entity_ptr->label);
  *entity.mutable_bounding_box() = ToProto(entity_ptr->bounding_box);
  entity.set_confidence(entity_ptr->confidence);
  *entity.mutable_depth() = ToProto(entity_ptr->depth);
  return entity;
}

FramePerception ToProto(
    const chromeos::media_perception::mojom::FramePerceptionPtr&
        perception_ptr) {
  FramePerception perception;
  if (perception_ptr.is_null())
    return perception;

  perception.set_frame_id(perception_ptr->frame_id);
  perception.set_timestamp_us(perception_ptr->timestamp_us);

  for (const auto& entity : perception_ptr->entities)
    *perception.add_entities() = ToProto(entity);

  for (const auto& perception_type : perception_ptr->perception_types)
    perception.add_perception_types(ToProto(perception_type));

  return perception;
}

PipelineStatus ToProto(
    chromeos::media_perception::mojom::PipelineStatus status) {
  switch (status) {
    case chromeos::media_perception::mojom::PipelineStatus::STARTED:
      return PipelineStatus::STARTED;
    case chromeos::media_perception::mojom::PipelineStatus::RUNNING:
      return PipelineStatus::RUNNING;
    case chromeos::media_perception::mojom::PipelineStatus::SUSPENDED:
      return PipelineStatus::SUSPENDED;
    case chromeos::media_perception::mojom::PipelineStatus::ERROR:
      return PipelineStatus::ERROR;
    case chromeos::media_perception::mojom::PipelineStatus::UNKNOWN:
      return PipelineStatus::PIPELINE_STATUS_UNKNOWN;
  }
  return PipelineStatus::PIPELINE_STATUS_UNKNOWN;
}

PipelineErrorType ToProto(
    chromeos::media_perception::mojom::PipelineErrorType error_type) {
  switch (error_type) {
    case chromeos::media_perception::mojom::PipelineErrorType::CONFIGURATION:
      return PipelineErrorType::CONFIGURATION;
    case chromeos::media_perception::mojom::PipelineErrorType::STARTUP:
      return PipelineErrorType::STARTUP;
    case chromeos::media_perception::mojom::PipelineErrorType::RUNTIME:
      return PipelineErrorType::RUNTIME;
    case chromeos::media_perception::mojom::PipelineErrorType::CONTENT:
      return PipelineErrorType::CONTENT;
    case chromeos::media_perception::mojom::PipelineErrorType::UNKNOWN:
      return PipelineErrorType::PIPELINE_ERROR_TYPE_UNKNOWN;
  }
  return PipelineErrorType::PIPELINE_ERROR_TYPE_UNKNOWN;
}

PipelineError ToProto(
    const chromeos::media_perception::mojom::PipelineErrorPtr& error_ptr) {
  PipelineError error;
  if (error_ptr.is_null())
    return error;
  error.set_error_type(ToProto(error_ptr->error_type));
  error.set_error_source(*error_ptr->error_source);
  error.set_error_string(*error_ptr->error_string);
  return error;
}

PipelineState ToProto(
    const chromeos::media_perception::mojom::PipelineStatePtr& state_ptr) {
  PipelineState state;
  if (state_ptr.is_null())
    return state;
  state.set_status(ToProto(state_ptr->status));

  *state.mutable_error() = ToProto(state_ptr->error);
  state.set_configuration_name(*state_ptr->configuration_name);
  return state;
}

PresencePerception ToProto(
    const chromeos::media_perception::mojom::PresencePerceptionPtr&
        perception_ptr) {
  PresencePerception perception;
  if (perception_ptr.is_null())
    return perception;

  perception.set_timestamp_us(perception_ptr->timestamp_us);
  perception.set_presence_confidence(perception_ptr->presence_confidence);
  return perception;
}

OccupancyTrigger ToProto(
    const chromeos::media_perception::mojom::OccupancyTriggerPtr&
        occupancy_ptr) {
  OccupancyTrigger occupancy_trigger;
  if (occupancy_ptr.is_null())
    return occupancy_trigger;

  occupancy_trigger.set_trigger(occupancy_ptr->trigger);
  occupancy_trigger.set_timestamp_ms(occupancy_ptr->timestamp_ms);
  return occupancy_trigger;
}

}  // namespace mri
