// Copyright 2017 Google Inc. 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_UWP_APPLICATION_UWP_H_
#define STARBOARD_SHARED_UWP_APPLICATION_UWP_H_

#include <agile.h>
#include <string>
#include <unordered_map>

#include "starboard/configuration.h"
#include "starboard/input.h"
#include "starboard/key.h"
#include "starboard/mutex.h"
#include "starboard/shared/internal_only.h"
#include "starboard/shared/starboard/application.h"
#include "starboard/shared/starboard/command_line.h"
#include "starboard/shared/starboard/localized_strings.h"
#include "starboard/shared/uwp/analog_thumbstick_input_thread.h"
#include "starboard/types.h"
#include "starboard/window.h"

namespace starboard {
namespace shared {
namespace uwp {

// Including <agile.h>, will eventually include <windows.h>, which includes
// C:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\um\processenv.h,
// line 164 in processenv.h redefines GetCommandLine to GetCommandLineW if
// UNICODE is defined.
// This function was added so that it could be used as a work around when
// GetCommandLine() needed to be called.
const starboard::CommandLine*
GetCommandLinePointer(starboard::Application* app);

class ApplicationUwp : public shared::starboard::Application,
                       private AnalogThumbstickThread::Callback {
 public:
  ApplicationUwp();
  ~ApplicationUwp() override;

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

  SbWindow CreateWindowForUWP(const SbWindowOptions* options);

  bool DestroyWindow(SbWindow window);

  void DispatchStart() { shared::starboard::Application::DispatchStart(); }

  // public for IFrameworkView subclass
  void SetCommandLine(int argc, const char** argv) {
    shared::starboard::Application::SetCommandLine(argc, argv);
  }

  // public for IFrameworkView subclass
  bool DispatchAndDelete(Application::Event* event) {
    return shared::starboard::Application::DispatchAndDelete(event);
  }

  Platform::Agile<Windows::UI::Core::CoreWindow> GetCoreWindow() const {
    return core_window_;
  }

  Platform::Agile<Windows::UI::Core::CoreDispatcher> GetDispatcher() const {
    return dispatcher_;
  }

  Platform::Agile<Windows::Media::SystemMediaTransportControls>
      GetTransportControls() const {
    return transport_controls_;
  }

  // public for IFrameworkView subclass
  void SetCoreWindow(Windows::UI::Core::CoreWindow^ window) {
    core_window_ = window;

    dispatcher_ = window->Dispatcher;
    transport_controls_ =
        Windows::Media::SystemMediaTransportControls::GetForCurrentView();
  }

  void OnKeyEvent(Windows::UI::Core::CoreWindow^ sender,
                  Windows::UI::Core::KeyEventArgs^ args,
                  bool up);

  void Inject(Event* event) override;

  void SetStartLink(const char* link) {
    shared::starboard::Application::SetStartLink(link);
  }

  Platform::String^ GetString(const char* id, const char* fallback) const;

  bool IsHdcpOn();
  // Returns true on success.
  bool TurnOnHdcp();
  // Returns true on success.
  bool TurnOffHdcp();

 private:
  // --- Application overrides ---
  bool IsStartImmediate() override { return false; }
  void Initialize() override;
  void Teardown() override;
  Event* GetNextEvent() override;
  bool DispatchNextEvent() override;
  void InjectTimedEvent(TimedEvent* timed_event) override;
  void CancelTimedEvent(SbEventId event_id) override;
  TimedEvent* GetNextDueTimedEvent() override;
  SbTimeMonotonic GetNextTimedEventTargetTime() override;

  int device_id() const { return device_id_; }
  void OnJoystickUpdate(SbKey key, SbInputVector value) override;

  // These two functions should only be called while holding
  // |hdcp_session_mutex_|.
  Windows::Media::Protection::HdcpSession^ GetHdcpSession();
  void ResetHdcpSession();

  // The single open window, if any.
  SbWindow window_;
  Platform::Agile<Windows::UI::Core::CoreWindow> core_window_;

  Platform::Agile<Windows::UI::Core::CoreDispatcher> dispatcher_;
  Platform::Agile<Windows::Media::SystemMediaTransportControls>
      transport_controls_;

  shared::starboard::LocalizedStrings localized_strings_;

  Mutex mutex_;
  // |timer_event_map_| is locked by |mutex_|.
  std::unordered_map<SbEventId, Windows::System::Threading::ThreadPoolTimer^>
      timer_event_map_;

  int device_id_;

  // |hdcp_session_| is locked by |hdcp_session_mutex_|.
  Mutex hdcp_session_mutex_;
  Windows::Media::Protection::HdcpSession^ hdcp_session_;

  scoped_ptr<AnalogThumbstickThread> analog_thumbstick_thread_;
};

}  // namespace uwp
}  // namespace shared
}  // namespace starboard

#endif  // STARBOARD_SHARED_UWP_APPLICATION_UWP_H_
