// Copyright 2015 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef COBALT_SYSTEM_WINDOW_SYSTEM_WINDOW_H_
#define COBALT_SYSTEM_WINDOW_SYSTEM_WINDOW_H_

#include "base/optional.h"
#include "cobalt/base/event_dispatcher.h"
#include "cobalt/math/size.h"
#include "cobalt/system_window/input_event.h"
#include "starboard/input.h"
#include "starboard/key.h"

namespace cobalt {
namespace system_window {

// A SystemWindow represents a window on desktop systems as well as as a
// mechanism for routing system events and notifications.  The SystemWindow
// routes callbacks for user input, and provides the information necessary to
// create a display render target for a graphics system.
class SystemWindow {
 public:
  SystemWindow(base::EventDispatcher* event_dispatcher,
               const base::Optional<math::Size>& window_size);
  ~SystemWindow();

  // Returns the dimensions of the window.
  math::Size GetWindowSize() const;

  // Gets the size of the diagonal length between opposing corners of the
  // screen. This is queried from the window_.
  float GetDiagonalSizeInches() const;

  // video pixel ratio = resolution of video output / resolution of window.  Its
  // value is usually 1.0.  Set it to a value greater than 1.0 allows the video
  // to be played in higher resolution than the window.
  float GetVideoPixelRatio() const;

  // Returns the resolution of the video output size, which may be different
  // from the window size. This will generally be GetWindowSize() multiplied by
  // GetVideoPixelRatio().
  math::Size GetVideoOutputResolution() const;

  base::EventDispatcher* event_dispatcher() const { return event_dispatcher_; }

  // Returns a handle to the Starboard window object.
  SbWindow GetSbWindow();

  // Gets the platform-specific window handle as a void*.
  void* GetWindowHandle();

  // Handles a single Starboard input event, dispatching any appropriate events.
  void HandleInputEvent(const SbInputData& data);

  // Returns the primary SystemWindow currently in use by the application.
  // Only one SystemWindow is currently supported, and this method will return
  // that window, or |nullptr| if it does not exist.
  static SystemWindow* PrimaryWindow();

 private:
  void UpdateModifiers(SbKey key, bool pressed);
  InputEvent::Modifiers GetModifiers();
  void DispatchInputEvent(const SbInputData& data, InputEvent::Type type,
                          bool is_repeat);
  void HandlePointerInputEvent(const SbInputData& data);

  base::EventDispatcher* event_dispatcher_;

  SbWindow window_;

  bool key_down_;
};

}  // namespace system_window
}  // namespace cobalt

#endif  // COBALT_SYSTEM_WINDOW_SYSTEM_WINDOW_H_
