// 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/ui/bin/root_presenter/displays/display_configuration.h"

#include <lib/syslog/cpp/macros.h>

#include "src/lib/files/file.h"
#include "src/lib/fxl/strings/trim.h"

namespace root_presenter {
namespace display_configuration {

void LogDisplayMetrics(const DisplayMetrics& metrics);

float LookupPixelDensityForDisplay(uint32_t width_in_px, uint32_t height_in_px);
fuchsia::ui::policy::DisplayUsage LookupDisplayUsageForDisplay(uint32_t width_in_px,
                                                               uint32_t height_in_px);

void InitializeModelForDisplay(uint32_t width_in_px, uint32_t height_in_px, DisplayModel* model) {
  FX_DCHECK(width_in_px != 0u);
  FX_DCHECK(height_in_px != 0u);
  FX_DCHECK(model != nullptr);

  model->display_info().width_in_px = width_in_px;
  model->display_info().height_in_px = height_in_px;

  model->display_info().density_in_px_per_mm =
      LookupPixelDensityForDisplay(width_in_px, height_in_px);
  model->environment_info().usage = LookupDisplayUsageForDisplay(width_in_px, height_in_px);

  FX_DCHECK(model->display_info().density_in_px_per_mm != 0.f);
  FX_DCHECK(model->environment_info().usage != fuchsia::ui::policy::DisplayUsage::kUnknown);
}

// Returns density_in_px_per_mm. This will be replaced by something that
// talks to the display API.
float LookupPixelDensityForDisplay(uint32_t width_in_px, uint32_t height_in_px) {
  {
    std::string pixel_density;
    if (files::ReadFileToString("/config/data/display_pixel_density", &pixel_density)) {
      auto pixel_density_value = atof(pixel_density.c_str());
      if (pixel_density_value != 0.0) {
        FX_LOGS(INFO) << "Display pixel density applied: " << pixel_density_value << " px/mm.";
        return pixel_density_value;
      } else {
        FX_LOGS(WARNING) << "Invalid display pixel density in configuration: " << pixel_density
                         << " px/mm.";
      }
    }
  }

  // TODO(fxbug.dev/23273): Need to have a database of devices and a more robust way
  // of identifying and classifying them.
  if (width_in_px == 2160 && height_in_px == 1440) {
    // Assume that the device is an Acer Switch 12 Alpha.
    FX_LOGS(INFO) << "RootPresenter: treating device as an Acer Switch 12 Alpha.";
    return 8.5f;
  } else if (width_in_px == 2400 && height_in_px == 1600) {
    // Assume that the device is a Google Pixelbook.
    FX_LOGS(INFO) << "RootPresenter: treating device as a Google Pixelbook.";
    return 9.252f;
  } else if (width_in_px == 3840 && height_in_px == 2160) {
    // Assume the display is a 24in 4K monitor.
    FX_LOGS(INFO) << "RootPresenter: treating display as a 24in 4K monitor.";
    return 7.323761f;
  } else if (width_in_px == 1920 && height_in_px == 1200) {
    // Assume the display is a 24in HD monitor.
    FX_LOGS(INFO) << "RootPresenter: treating display as a 24in monitor.";
    return 4.16f;
  } else if (width_in_px == 2560 && height_in_px == 1440) {
    // TODO(fxbug.dev/42794): Allow Root Presenter clients to specify exact pixel ratio
    // Assume display is a 27in 2K monitor.
    FX_LOGS(INFO) << "RootPresenter: treating device as a 27in 2k monitor.";
    return 5.22f;
  } else {
    // TODO(fxbug.dev/23621): Don't lie.
    FX_LOGS(WARNING) << "RootPresenter: unrecognized display (width_in_px=" << width_in_px
                     << " height_in_px=" << height_in_px << ").";
    return 9.f;
  }
}

fuchsia::ui::policy::DisplayUsage LookupDisplayUsageForDisplay(uint32_t width_in_px,
                                                               uint32_t height_in_px) {
  // TODO(fxbug.dev/23273): Need to have a database of devices and a more robust way
  // of identifying and classifying them.
  {
    std::string raw_display_usage;
    if (files::ReadFileToString("/config/data/display_usage", &raw_display_usage)) {
      std::string_view display_usage = fxl::TrimString(raw_display_usage, "\n ");
      if (display_usage == "handheld") {
        return fuchsia::ui::policy::DisplayUsage::kHandheld;
      } else if (display_usage == "close") {
        return fuchsia::ui::policy::DisplayUsage::kClose;
      } else if (display_usage == "near") {
        return fuchsia::ui::policy::DisplayUsage::kNear;
      } else if (display_usage == "midrange") {
        return fuchsia::ui::policy::DisplayUsage::kMidrange;
      } else if (display_usage == "far") {
        return fuchsia::ui::policy::DisplayUsage::kFar;
      } else {
        FX_LOGS(WARNING) << "Invalid display usage in configuration: " << display_usage << ".";
      }
    }
  }

  if (width_in_px == 2160 && height_in_px == 1440) {
    // Assume that the device is an Acer Switch 12 Alpha.
    return fuchsia::ui::policy::DisplayUsage::kClose;
  } else if (width_in_px == 2400 && height_in_px == 1600) {
    // Assume that the device is a Google Pixelbook.
    return fuchsia::ui::policy::DisplayUsage::kClose;
  } else if (width_in_px == 3840 && height_in_px == 2160) {
    // Assume the display is a 24in 4K monitor.
    return fuchsia::ui::policy::DisplayUsage::kNear;
  } else if (width_in_px == 1920 && height_in_px == 1200) {
    // Assume the display is a 24in monitor.
    return fuchsia::ui::policy::DisplayUsage::kNear;
  } else {
    // TODO(fxbug.dev/23621): Don't lie.
    return fuchsia::ui::policy::DisplayUsage::kClose;
  }
}

void LogDisplayMetrics(const DisplayMetrics& metrics) {
  FX_DLOGS(INFO) << "RootPresenter: Display metrics: "
                 << "width_in_px=" << metrics.width_in_px()
                 << ", height_in_px=" << metrics.height_in_px()
                 << ", width_in_pp=" << metrics.width_in_pp()
                 << ", height_in_pp=" << metrics.height_in_pp()
                 << ", width_in_mm=" << metrics.width_in_mm()
                 << ", height_in_mm=" << metrics.height_in_mm()
                 << ", x_scale_in_px_per_pp=" << metrics.x_scale_in_px_per_pp()
                 << ", y_scale_in_px_per_pp=" << metrics.y_scale_in_px_per_pp()
                 << ", x_scale_in_pp_per_px=" << metrics.x_scale_in_pp_per_px()
                 << ", y_scale_in_pp_per_px=" << metrics.y_scale_in_pp_per_px()
                 << ", density_in_pp_per_mm=" << metrics.density_in_pp_per_mm()
                 << ", density_in_mm_per_pp=" << metrics.density_in_mm_per_pp();
}

}  // namespace display_configuration
}  // namespace root_presenter
