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

#ifndef UI_DISPLAY_DISPLAY_H_
#define UI_DISPLAY_DISPLAY_H_

#include <stdint.h>

#include "base/compiler_specific.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
#include "ui/display/display_export.h"
#include "ui/display/types/display_constants.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/rect.h"

namespace display {

namespace mojom {
class DisplayDataView;
}

// Returns true if one of following conditions is met.
// 1) id1 is internal.
// 2) output index of id1 < output index of id2 and id2 isn't internal.
DISPLAY_EXPORT bool CompareDisplayIds(int64_t id1, int64_t id2);

// This class typically, but does not always, correspond to a physical display
// connected to the system. A fake Display may exist on a headless system, or a
// Display may correspond to a remote, virtual display.
//
// Note: The screen and display currently uses pixel coordinate
// system. For platforms that support DIP (density independent pixel),
// |bounds()| and |work_area| will return values in DIP coordinate
// system, not in backing pixels.
class DISPLAY_EXPORT Display final {
 public:
  // Screen Rotation in clock-wise degrees.
  // This enum corresponds to DisplayRotationDefaultProto::Rotation in
  // components/policy/proto/chrome_device_policy.proto.
  enum Rotation {
    ROTATE_0 = 0,
    ROTATE_90,
    ROTATE_180,
    ROTATE_270,
  };

  // The display rotation can have multiple causes for change. A user can set a
  // preference. On devices with accelerometers, they can change the rotation.
  // RotationSource allows for the tracking of a Rotation per source of the
  // change. ACTIVE is the current rotation of the display. Rotation changes not
  // due to an accelerometer, nor the user, are to use this source directly.
  // UNKNOWN is when no rotation source has been provided.
  enum class RotationSource {
    ACCELEROMETER = 0,
    ACTIVE,
    USER,
    UNKNOWN,
  };

  // Touch support for the display.
  enum class TouchSupport {
    UNKNOWN,
    AVAILABLE,
    UNAVAILABLE,
  };

  // Accelerometer support for the display.
  enum class AccelerometerSupport {
    UNKNOWN,
    AVAILABLE,
    UNAVAILABLE,
  };

  // Creates a display with kInvalidDisplayId as default.
  Display();
  explicit Display(int64_t id);
  Display(int64_t id, const gfx::Rect& bounds);
  Display(const Display& other);
  ~Display();

  // Returns a valid display with default parameters and ID set to
  // |kDefaultDisplayId| which is used when there's no actual display connected
  // to the device.
  static Display GetDefaultDisplay();

  // Returns the forced device scale factor, which is given by
  // "--force-device-scale-factor".
  static float GetForcedDeviceScaleFactor();

  // Indicates if a device scale factor is being explicitly enforced from the
  // command line via "--force-device-scale-factor".
  static bool HasForceDeviceScaleFactor();

  // Returns the forced display color profile, which is given by
  // "--force-color-profile".
  static gfx::ColorSpace GetForcedDisplayColorProfile();

  // Indicates if a display color profile is being explicitly enforced from the
  // command line via "--force-color-profile".
  static bool HasForceDisplayColorProfile();

  // Returns the forced raster color profile, which is given by
  // "--force-raster-color-profile".
  static gfx::ColorSpace GetForcedRasterColorProfile();

  // Indicates if a raster color profile is being explicitly enforced from the
  // command line via "--force-raster-color-profile".
  static bool HasForceRasterColorProfile();

  // Indicates if the display color profile being forced should be ensured to
  // be in use by the operating system as well.
  static bool HasEnsureForcedColorProfile();

  // Resets the caches used to determine if a device scale factor is being
  // forced from the command line via "--force-device-scale-factor", and thus
  // ensures that the command line is reevaluated.
  static void ResetForceDeviceScaleFactorForTesting();

  // Resets the cache and sets a new force device scale factor.
  static void SetForceDeviceScaleFactor(double dsf);

  // Converts the given angle to its corresponding Rotation. The angle is in
  // degrees, and the only valid values are 0, 90, 180, and 270.
  // TODO(crbug.com/840189): we should never need to convert degrees to a
  // Rotation if we were to Rotations internally and only converted to numeric
  // values when required.
  static Rotation DegreesToRotation(int degrees);

  // This is the analog to DegreesToRotation and converts a Rotation to a
  // numeric representation.
  static int RotationToDegrees(Rotation rotation);

  // Returns true if |degrees| is compatible with DegreesToRotation. I.e., that
  // it is 0, 90, 180, or 270.
  static bool IsValidRotation(int degrees);

  // Sets/Gets unique identifier associated with the display.
  // -1 means invalid display and it doesn't not exit.
  int64_t id() const { return id_; }
  void set_id(int64_t id) { id_ = id; }

  // Gets/Sets the display's bounds in Screen's coordinates.
  const gfx::Rect& bounds() const { return bounds_; }
  void set_bounds(const gfx::Rect& bounds) { bounds_ = bounds; }

  // Gets/Sets the display's work area in Screen's coordinates.
  const gfx::Rect& work_area() const { return work_area_; }
  void set_work_area(const gfx::Rect& work_area) { work_area_ = work_area; }

  // Output device's pixel scale factor. This specifies how much the
  // UI should be scaled when the actual output has more pixels than
  // standard displays (which is around 100~120dpi.) The potential return
  // values depend on each platforms.
  float device_scale_factor() const { return device_scale_factor_; }
  void set_device_scale_factor(float scale) { device_scale_factor_ = scale; }

  Rotation rotation() const { return rotation_; }
  void set_rotation(Rotation rotation) { rotation_ = rotation; }
  int RotationAsDegree() const;
  void SetRotationAsDegree(int rotation);

  TouchSupport touch_support() const { return touch_support_; }
  void set_touch_support(TouchSupport support) { touch_support_ = support; }

  AccelerometerSupport accelerometer_support() const {
    return accelerometer_support_;
  }
  void set_accelerometer_support(AccelerometerSupport support) {
    accelerometer_support_ = support;
  }

  // Utility functions that just return the size of display and work area.
  const gfx::Size& size() const { return bounds_.size(); }
  const gfx::Size& work_area_size() const { return work_area_.size(); }

  // Returns the work area insets.
  gfx::Insets GetWorkAreaInsets() const;

  // Sets the device scale factor and display bounds in pixel. This
  // updates the work are using the same insets between old bounds and
  // work area.
  void SetScaleAndBounds(float device_scale_factor,
                         const gfx::Rect& bounds_in_pixel);

  // Sets the display's size. This updates the work area using the same insets
  // between old bounds and work area.
  void SetSize(const gfx::Size& size_in_pixel);

  // Computes and updates the display's work are using
  // |work_area_insets| and the bounds.
  void UpdateWorkAreaFromInsets(const gfx::Insets& work_area_insets);

  // Returns the display's size in pixel coordinates.
  gfx::Size GetSizeInPixel() const;
#if defined(OS_ANDROID)
  void set_size_in_pixels(const gfx::Size& size) { size_in_pixels_ = size; }
#endif  // defined(OS_ANDROID)

  // Returns a string representation of the display;
  std::string ToString() const;

  // True if the display contains valid display id.
  bool is_valid() const { return id_ != kInvalidDisplayId; }

  // True if the display corresponds to internal panel.
  bool IsInternal() const;

  // Gets/Sets an id of display corresponding to internal panel.
  static int64_t InternalDisplayId();
  static void SetInternalDisplayId(int64_t internal_display_id);

  // Test if the |id| is for the internal display if any.
  static bool IsInternalDisplayId(int64_t id);

  // True if there is an internal display.
  static bool HasInternalDisplay();

  // Maximum cursor size in native pixels.
  const gfx::Size& maximum_cursor_size() const { return maximum_cursor_size_; }
  void set_maximum_cursor_size(const gfx::Size& size) {
    maximum_cursor_size_ = size;
  }

  // The color space of the display.
  gfx::ColorSpace color_space() const { return color_space_; }
  void set_color_space(const gfx::ColorSpace& color_space) {
    color_space_ = color_space;
  }

  // SDR white level used to scale HDR color spaces.
  float sdr_white_level() const { return sdr_white_level_; }

  // Set the color space and SDR white level of the display, and reset the color
  // depth and depth per component based on whether the color space is HDR.
  void SetColorSpaceAndDepth(
      const gfx::ColorSpace& color_space,
      float sdr_white_level = gfx::ColorSpace::kDefaultSDRWhiteLevel);

  // The number of bits per pixel. Used by media query APIs.
  int color_depth() const { return color_depth_; }
  void set_color_depth(int color_depth) {
    color_depth_ = color_depth;
  }

  // The number of bits per color component (all color components are assumed to
  // have the same number of bits). Used by media query APIs.
  int depth_per_component() const { return depth_per_component_; }
  void set_depth_per_component(int depth_per_component) {
    depth_per_component_ = depth_per_component;
  }

  // True if this is a monochrome display (e.g, for accessiblity). Used by media
  // query APIs.
  bool is_monochrome() const { return is_monochrome_; }
  void set_is_monochrome(bool is_monochrome) { is_monochrome_ = is_monochrome; }

  // The display frequency of the monitor.
  int display_frequency() const { return display_frequency_; }
  void set_display_frequency(int display_frequency) {
    display_frequency_ = display_frequency;
  }

  bool operator==(const Display& rhs) const;
  bool operator!=(const Display& rhs) const { return !(*this == rhs); }

 private:
  friend struct mojo::StructTraits<mojom::DisplayDataView, Display>;

  int64_t id_ = kInvalidDisplayId;
  gfx::Rect bounds_;
  // If non-empty, then should be same size as |bounds_|. Used to avoid rounding
  // errors.
  gfx::Size size_in_pixels_;
  gfx::Rect work_area_;
  float device_scale_factor_;
  Rotation rotation_ = ROTATE_0;
  TouchSupport touch_support_ = TouchSupport::UNKNOWN;
  AccelerometerSupport accelerometer_support_ = AccelerometerSupport::UNKNOWN;
  gfx::Size maximum_cursor_size_;
  // NOTE: this is not currently written to the mojom as it is not used in
  // aura.
  gfx::ColorSpace color_space_;
  float sdr_white_level_;
  int color_depth_;
  int depth_per_component_;
  bool is_monochrome_ = false;
  int display_frequency_ = 0;
};

}  // namespace display

#endif  // UI_DISPLAY_DISPLAY_H_
