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

#include "services/viz/public/cpp/compositing/begin_frame_args_mojom_traits.h"

#include "base/notreached.h"
#include "mojo/public/cpp/base/time_mojom_traits.h"

namespace mojo {

// static
viz::mojom::BeginFrameArgsType
EnumTraits<viz::mojom::BeginFrameArgsType,
           viz::BeginFrameArgs::BeginFrameArgsType>::
    ToMojom(viz::BeginFrameArgs::BeginFrameArgsType type) {
  switch (type) {
    case viz::BeginFrameArgs::BeginFrameArgsType::INVALID:
      return viz::mojom::BeginFrameArgsType::INVALID;
    case viz::BeginFrameArgs::BeginFrameArgsType::NORMAL:
      return viz::mojom::BeginFrameArgsType::NORMAL;
    case viz::BeginFrameArgs::BeginFrameArgsType::MISSED:
      return viz::mojom::BeginFrameArgsType::MISSED;
  }
  NOTREACHED();
}

// static
viz::BeginFrameArgs::BeginFrameArgsType
EnumTraits<viz::mojom::BeginFrameArgsType,
           viz::BeginFrameArgs::BeginFrameArgsType>::
    FromMojom(viz::mojom::BeginFrameArgsType input) {
  switch (input) {
    case viz::mojom::BeginFrameArgsType::INVALID:
      return viz::BeginFrameArgs::BeginFrameArgsType::INVALID;
    case viz::mojom::BeginFrameArgsType::NORMAL:
      return viz::BeginFrameArgs::BeginFrameArgsType::NORMAL;
    case viz::mojom::BeginFrameArgsType::MISSED:
      return viz::BeginFrameArgs::BeginFrameArgsType::MISSED;
  }
  NOTREACHED();
}

// static
base::expected<void, DeserializationError>
StructTraits<viz::mojom::BeginFrameIdDataView, viz::BeginFrameId>::Read(
    viz::mojom::BeginFrameIdDataView data,
    viz::BeginFrameId* out) {
  out->source_id = data.source_id();
  out->sequence_number = data.sequence_number();
  return base::ok();
}

// static
base::expected<void, DeserializationError>
StructTraits<viz::mojom::BeginFrameArgsDataView, viz::BeginFrameArgs>::Read(
    viz::mojom::BeginFrameArgsDataView data,
    viz::BeginFrameArgs* out) {
  std::optional<base::TimeDelta> unthrottled_interval;
  if (!data.ReadFrameTime(&out->frame_time) ||
      !data.ReadDeadline(&out->deadline) ||
      !data.ReadInterval(&out->interval) || !data.ReadFrameId(&out->frame_id) ||
      !data.ReadType(&out->type) ||
      !data.ReadDispatchTime(&out->dispatch_time) ||
      !data.ReadClientArrivalTime(&out->client_arrival_time) ||
      !data.ReadUnthrottledInterval(&unthrottled_interval) ||
      !data.ReadDeadlineDerivedInterval(&out->deadline_derived_interval)) {
    return base::unexpected(DeserializationError());
  }

  // If omitted, default to the regular interval.
  out->unthrottled_interval = unthrottled_interval.value_or(out->interval);

  out->frames_throttled_since_last = data.frames_throttled_since_last();
  out->trace_id = data.trace_id();
  out->on_critical_path = data.on_critical_path();
  out->animate_only = data.animate_only();
  return base::ok();
}

// static
base::expected<void, DeserializationError>
StructTraits<viz::mojom::BeginFrameAckDataView, viz::BeginFrameAck>::Read(
    viz::mojom::BeginFrameAckDataView data,
    viz::BeginFrameAck* out) {
  if (data.sequence_number() < viz::BeginFrameArgs::kStartingFrameNumber) {
    return base::unexpected(DeserializationError());
  }
  out->frame_id.source_id = data.source_id();
  out->frame_id.sequence_number = data.sequence_number();
  out->trace_id = data.trace_id();
  out->has_damage = data.has_damage();
  return base::ok();
}

#if BUILDFLAG(IS_MAC)
// static
base::expected<void, DeserializationError> StructTraits<
    viz::mojom::CADisplayLinkParamsDataView,
    viz::CADisplayLinkParams>::Read(viz::mojom::CADisplayLinkParamsDataView
                                        data,
                                    viz::CADisplayLinkParams* out) {
  if (!data.ReadTimestamp(&out->timestamp) ||
      !data.ReadTargetTimestamp(&out->target_timestamp) ||
      !data.ReadInterval(&out->interval) ||
      !data.ReadIpcBeginTimestamp(&out->ipc_begin_timestamp)) {
    return base::unexpected(DeserializationError());
  }
  out->display_id = data.display_id();
  return base::ok();
}
#endif

}  // namespace mojo
