// Copyright 2017 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 STARBOARD_SHARED_WIN32_APPLICATION_WIN32_H_
#define STARBOARD_SHARED_WIN32_APPLICATION_WIN32_H_

// Windows headers.
#include <windows.h>

#include <memory>
#include <string>
#include <unordered_map>

#include "starboard/common/mutex.h"
#include "starboard/shared/starboard/application.h"
#include "starboard/shared/starboard/localized_strings.h"
#include "starboard/shared/starboard/queue_application.h"
#include "starboard/shared/win32/window_internal.h"
#include "starboard/system.h"
#include "starboard/window.h"

namespace starboard {
namespace shared {
namespace win32 {

class ApplicationWin32 : public starboard::QueueApplication {
 public:
  ApplicationWin32();
  ~ApplicationWin32() override;

  static ApplicationWin32* Get() {
    return static_cast<ApplicationWin32*>(
        ::starboard::shared::starboard::Application::Get());
  }

  SbWindow CreateWindowForWin32(const SbWindowOptions* options);

  bool DestroyWindow(SbWindow window);

#if SB_API_VERSION >= 13
  void DispatchStart(SbTimeMonotonic timestamp) {
    shared::starboard::Application::DispatchStart(timestamp);
  }
#else  // SB_API_VERSION >= 13
void DispatchStart() {
    shared::starboard::Application::DispatchStart();
  }
#endif  // SB_API_VERSION >= 13

  SbWindow GetCoreWindow() {
    return SbWindowIsValid(window_.get()) ? window_.get() : kSbWindowInvalid;
  }

  bool OnSbSystemRaisePlatformError(SbSystemPlatformErrorType type,
                                    SbSystemPlatformErrorCallback callback,
                                    void* user_data);

  std::string GetLocalizedString(const char* id, const char* fallback) const {
    return localized_strings_.GetString(id, fallback);
  }

  // Returns true if it is valid to poll/query for system events.
  bool MayHaveSystemEvents() override { return true; }

  // Waits for an event until the timeout |time| runs out.  If an event occurs
  // in this time, it is returned, otherwise NULL is returned. If |time| is zero
  // or negative, then this should function effectively like a no-wait poll.
  Event* WaitForSystemEventWithTimeout(SbTime time) override;

  // Wakes up any thread waiting within a call to
  // WaitForSystemEventWithTimeout().
  void WakeSystemEventWait() override {
    ScopedLock lock(stop_waiting_for_system_events_mutex_);
    stop_waiting_for_system_events_ = true;
  }

  LRESULT WindowProcess(HWND hWnd, UINT msg, WPARAM w_param, LPARAM l_param);
  VOID TimedEventCallback(PVOID lp, BOOLEAN timer_or_wait_fired);

  // Non-virtual override. Calls into super class Run().
  int Run(int argc, char** argv);

 private:
  // --- Application overrides ---
  bool IsStartImmediate() override { return true; }
  void Initialize() override {}
  void Teardown() override {}

  void ProcessNextSystemMessage();
  SbTimeMonotonic GetNextTimedEventTargetTime() override {
    return SbTimeGetMonotonicNow();
  }

  // Processes window key events, returning a corresponding Event instance.
  // This transfers ownership of the returned Event.
  Event* ProcessWinKeyEvent(SbWindow window,
                            UINT msg,
                            WPARAM w_param,
                            LPARAM l_param);

  // Processes window mouse events, returning a corresponding Event instance.
  // This transfers ownership of the returned Event. The Event may be nullptr.
  Event* ProcessWinMouseEvent(SbWindow window,
                              UINT msg,
                              WPARAM w_param,
                              LPARAM l_param);

  Event* pending_event_ = nullptr;

  // The single open window, if any.
  std::unique_ptr<SbWindowPrivate> window_;

  starboard::LocalizedStrings localized_strings_;

  Mutex stop_waiting_for_system_events_mutex_;
  bool stop_waiting_for_system_events_;

  // The current depressed SbKeyModifiers - if there are any.
  unsigned int current_key_modifiers_ = 0;
};

}  // namespace win32
}  // namespace shared
}  // namespace starboard

#endif  // STARBOARD_SHARED_WIN32_APPLICATION_WIN32_H_
