// Copyright 2017 The Fuchsia 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 "src/media/audio/audio_core/utils.h"

#include <fuchsia/scheduler/cpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/zx/channel.h>

#include <audio-proto-utils/format-utils.h>

#include "src/lib/fxl/logging.h"
#include "src/media/audio/audio_core/driver_utils.h"

namespace media::audio {

zx_status_t SelectBestFormat(const std::vector<audio_stream_format_range_t>& fmts,
                             uint32_t* frames_per_second_inout, uint32_t* channels_inout,
                             fuchsia::media::AudioSampleFormat* sample_format_inout) {
  if ((frames_per_second_inout == nullptr) || (channels_inout == nullptr) ||
      (sample_format_inout == nullptr)) {
    return ZX_ERR_INVALID_ARGS;
  }

  uint32_t pref_frame_rate = *frames_per_second_inout;
  uint32_t pref_channels = *channels_inout;
  audio_sample_format_t pref_sample_format;

  if (!driver_utils::AudioSampleFormatToDriverSampleFormat(*sample_format_inout,
                                                           &pref_sample_format)) {
    FXL_LOG(WARNING) << "Failed to convert FIDL sample format ("
                     << static_cast<uint32_t>(*sample_format_inout) << ") to driver sample format.";
    return ZX_ERR_INVALID_ARGS;
  }

  uint32_t best_frame_rate;
  uint32_t best_channels;
  audio_sample_format_t best_sample_format;
  uint32_t best_score = 0;
  uint32_t best_frame_rate_delta = std::numeric_limits<uint32_t>::max();

  constexpr uint32_t U8_FMT = AUDIO_SAMPLE_FORMAT_8BIT | AUDIO_SAMPLE_FORMAT_FLAG_UNSIGNED;
  constexpr uint32_t S16_FMT = AUDIO_SAMPLE_FORMAT_16BIT;
  constexpr uint32_t S24_FMT = AUDIO_SAMPLE_FORMAT_24BIT_IN32;
  constexpr uint32_t F32_FMT = AUDIO_SAMPLE_FORMAT_32BIT_FLOAT;

  // Users should only ask for unsigned-8, signed-16, signed-24in32 or float-32. If they ask for
  // anything else, change their preference to signed-16.
  //
  // TODO(johngro) : clean this up as part of fixing MTWN-54
  if ((pref_sample_format & AUDIO_SAMPLE_FORMAT_FLAG_INVERT_ENDIAN) ||
      (((pref_sample_format & U8_FMT) != U8_FMT) && ((pref_sample_format & S16_FMT) != S16_FMT) &&
       ((pref_sample_format & S24_FMT) != S24_FMT) &&
       ((pref_sample_format & F32_FMT) != F32_FMT))) {
    pref_sample_format = AUDIO_SAMPLE_FORMAT_16BIT;
  }

  for (const auto& range : fmts) {
    // Start by scoring our sample format. Right now, the audio core supports 8-bit unsigned, 16-bit
    // signed, 24-bit-in-32 signed and 32-bit float. If this sample format range does not support
    // any of these, just skip it for now. Otherwise, 5 points if you match the requested format, 4
    // for signed-24, 3 for signed-16, 2 for float-32, or 1 for unsigned-8.
    audio_sample_format_t this_sample_format;
    int sample_format_score;

    bool supports_u8 = (range.sample_formats & U8_FMT) == U8_FMT;
    bool supports_s16 = (range.sample_formats & S16_FMT) == S16_FMT;
    bool supports_s24 = (range.sample_formats & S24_FMT) == S24_FMT;
    bool supports_f32 = (range.sample_formats & F32_FMT) == F32_FMT;
    if ((range.sample_formats & AUDIO_SAMPLE_FORMAT_FLAG_INVERT_ENDIAN) ||
        (!supports_u8 && !supports_s16 && !supports_s24 && !supports_f32)) {
      continue;  // Otherwise skip: this isn't a sample container we understand.
    }

    if ((pref_sample_format & range.sample_formats) == pref_sample_format) {
      // Direct match.
      this_sample_format = pref_sample_format;
      sample_format_score = 5;
    } else if (supports_s24) {
      this_sample_format = AUDIO_SAMPLE_FORMAT_24BIT_IN32;
      sample_format_score = 4;
    } else if (supports_s16) {
      this_sample_format = AUDIO_SAMPLE_FORMAT_16BIT;
      sample_format_score = 3;
    } else if (supports_f32) {
      this_sample_format = AUDIO_SAMPLE_FORMAT_32BIT_FLOAT;
      sample_format_score = 2;
    } else {
      FXL_DCHECK(supports_u8);
      this_sample_format = static_cast<audio_sample_format_t>(U8_FMT);
      sample_format_score = 1;
    }

    // Next consider the supported channel counts. 3 points for matching the requested channel
    // count. Otherwise, default to stereo (if supported) and score 2 points. Failing that, just
    // pick the top end of the supported channel range and score 1 point.
    uint32_t this_channels;
    int channel_count_score;
    if ((pref_channels >= range.min_channels) && (pref_channels <= range.max_channels)) {
      this_channels = pref_channels;
      channel_count_score = 3;
    } else if ((2 >= range.min_channels) && (2 <= range.max_channels)) {
      this_channels = 2;
      channel_count_score = 2;
    } else {
      this_channels = range.max_channels;
      channel_count_score = 1;
    }

    // Next score based on supported frame rates. Score 3 points for a match, 2 points if we have to
    // scale up to the nearest supported rate, or 1 point if we have to scale down.
    //
    if (range.min_frames_per_second > range.max_frames_per_second) {
      // Skip this frame rate range entirely if it is empty.
      FXL_LOG(INFO) << "Skipping empty frame rate range [" << range.min_frames_per_second << ", "
                    << range.max_frames_per_second
                    << "] while searching for best format in driver list.";
      continue;
    }

    uint32_t this_frame_rate = 0;
    uint32_t frame_rate_delta = std::numeric_limits<uint32_t>::max();
    int frame_rate_score = 0;
    if (range.flags & ASF_RANGE_FLAG_FPS_CONTINUOUS) {
      // This is a continuous sample rate range. If we are within the range, thats a match.
      // Otherwise move up/down as needed to match the min/max of the range as appropriate.
      if ((pref_frame_rate >= range.min_frames_per_second) &&
          (pref_frame_rate <= range.max_frames_per_second)) {
        this_frame_rate = pref_frame_rate;
        frame_rate_score = 3;
        frame_rate_delta = 0;
      } else if (pref_frame_rate < range.min_frames_per_second) {
        this_frame_rate = range.min_frames_per_second;
        frame_rate_score = 2;
        frame_rate_delta = range.min_frames_per_second - pref_frame_rate;
      } else {
        FXL_DCHECK(pref_frame_rate > range.max_frames_per_second);
        this_frame_rate = range.max_frames_per_second;
        frame_rate_score = 1;
        frame_rate_delta = pref_frame_rate - range.max_frames_per_second;
      }
    } else {
      // This is a discrete sample rate range. Use the frame rate enumerator utility class to
      // evaluate each of the possible frame rates.
      for (const uint32_t rate : ::audio::utils::FrameRateEnumerator(range)) {
        if (pref_frame_rate == rate) {
          // We matched our preference. No need to keep searching.
          this_frame_rate = rate;
          frame_rate_score = 3;
          frame_rate_delta = 0;
          break;
        }

        if (pref_frame_rate < rate) {
          // Scaling up; 2 points.  If this better than what we were doing before, just choose it.
          // If we were already going to scale up, pick the frame rate which is closer to our
          // preference. Otherwise, do nothing.
          if ((frame_rate_score < 2) || ((frame_rate_score == 2) && (rate < this_frame_rate))) {
            this_frame_rate = rate;
            frame_rate_score = 2;
            frame_rate_delta = rate - pref_frame_rate;
          }
        } else {
          FXL_DCHECK(pref_frame_rate > rate);

          // Scaling down; 1 point.  If this better than what we were doing before, just choose it.
          // If we were already going to scale down, pick the frame rate which is closer to our
          // preference. Otherwise, do nothing.
          if ((frame_rate_score < 1) || ((frame_rate_score == 1) && (rate > this_frame_rate))) {
            this_frame_rate = rate;
            frame_rate_score = 1;
            frame_rate_delta = pref_frame_rate - rate;
          }
        }
      }
    }

    // If our frame rate score is still zero, it means that we were given a discrete frame range by
    // a driver which was completely empty (even though min was <= max as it should be)  Debug log a
    // warning, then skip the range entirely.
    if (frame_rate_score == 0) {
      FXL_LOG(INFO) << "Skipping empty discrete frame rate range [" << range.min_frames_per_second
                    << ", " << range.max_frames_per_second << "] (flags " << range.flags
                    << ") while searching for best format";
      continue;
    }

    // OK, we have computed the best option supported by this frame rate range. Weight the score,
    // and it if it better then any of our previous best score, replace our previous best with this.
    uint32_t score;
    score = (sample_format_score * 100)   // format is the most important.
            + (channel_count_score * 10)  // channel count comes second.
            + frame_rate_score;           // frame rate is the least important.

    FXL_DCHECK(score > 0);
    FXL_DCHECK(::audio::utils::FormatIsCompatible(this_frame_rate, this_channels,
                                                  this_sample_format, range));

    // If this score is better than the current best score, or this score ties the current best
    // score but the frame rate distance is less, then this is the new best format.
    if ((score > best_score) ||
        ((score == best_score) && (frame_rate_delta < best_frame_rate_delta))) {
      best_frame_rate = this_frame_rate;
      best_frame_rate_delta = frame_rate_delta;
      best_channels = this_channels;
      best_sample_format = this_sample_format;
      best_score = score;
    }
  }

  // If our score is still zero, then there must have be absolutely no supported formats in the set
  // provided by the driver.
  if (!best_score) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  __UNUSED bool convert_res =
      driver_utils::DriverSampleFormatToAudioSampleFormat(best_sample_format, sample_format_inout);
  FXL_DCHECK(convert_res);

  *channels_inout = best_channels;
  *frames_per_second_inout = best_frame_rate;

  return ZX_OK;
}

zx_status_t AcquireHighPriorityProfile(zx::profile* profile) {
  // Use threadsafe static initialization to get our one-and-only copy of this profile object. Each
  // subsequent call will return a duplicate of that profile handle to ensure sharing of thread
  // pools.
  static zx::profile high_priority_profile;
  static zx_status_t initial_status = [](zx::profile* profile) {
    zx::channel ch0, ch1;
    zx_status_t res = zx::channel::create(0u, &ch0, &ch1);
    if (res != ZX_OK) {
      FXL_LOG(ERROR) << "Failed to create channel, res=" << res;
      return res;
    }

    res = fdio_service_connect(
        (std::string("/svc/") + fuchsia::scheduler::ProfileProvider::Name_).c_str(), ch0.get());
    if (res != ZX_OK) {
      FXL_LOG(ERROR) << "Failed to connect to ProfileProvider, res=" << res;
      return res;
    }

    fuchsia::scheduler::ProfileProvider_SyncProxy provider(std::move(ch1));

    zx_status_t fidl_status;
    zx::profile res_profile;
    res = provider.GetProfile(24 /* HIGH_PRIORITY */, "src/media/audio/audio_core", &fidl_status,
                              &res_profile);
    if (res != ZX_OK) {
      FXL_LOG(ERROR) << "Failed to create profile, res=" << res;
      return res;
    }
    if (fidl_status != ZX_OK) {
      FXL_LOG(ERROR) << "Failed to create profile, fidl_status=" << fidl_status;
      return fidl_status;
    }

    *profile = std::move(res_profile);
    return ZX_OK;
  }(&high_priority_profile);

  // If the initial acquisition of the profile failed, return that status.
  if (initial_status != ZX_OK)
    return initial_status;

  // Otherwise, dupe this handle and return it.
  return high_priority_profile.duplicate(ZX_RIGHT_SAME_RIGHTS, profile);
}

}  // namespace media::audio
