/*
 * Copyright 2020 Google LLC
 *
 */

/*
 * Copyright (c) 2020, Alliance for Open Media. All rights reserved
 *
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
 */

#include "pch.h"
#include "App.h"

#include <ppltasks.h>
#include <Xinput.h>

using namespace uwp_dx12_player;

using namespace concurrency;
using namespace Windows::ApplicationModel;
using namespace Windows::ApplicationModel::Core;
using namespace Windows::ApplicationModel::Activation;
using namespace Windows::UI::Core;
using namespace Windows::UI::Input;
using namespace Windows::System;
using namespace Windows::Foundation;
using namespace Windows::Graphics::Display;

using Microsoft::WRL::ComPtr;

// The DirectX 12 Application template is documented at https://go.microsoft.com/fwlink/?LinkID=613670&clcid=0x409

// The main function is only used to initialize our IFrameworkView class.
[Platform::MTAThread] int main(Platform::Array<Platform::String ^> ^) {
  PlayerWindow::InitializeLog(logging::LOG_INFO);
  XB_LOGI << "Start application";

  auto direct3DApplicationSource = ref new Direct3DApplicationSource();
  CoreApplication::Run(direct3DApplicationSource);
  return 0;
}

    IFrameworkView
    ^ Direct3DApplicationSource::CreateView() {
  return ref new App();
}

App::App() : m_windowClosed(false), m_windowVisible(true) {}

// The first method called when the IFrameworkView is being created.
void App::Initialize(CoreApplicationView ^ applicationView) {
  // Register event handlers for app lifecycle. This example includes Activated, so that we
  // can make the CoreWindow active and start rendering on the window.
  applicationView->Activated +=
      ref new TypedEventHandler<CoreApplicationView ^, IActivatedEventArgs ^>(this, &App::OnActivated);

  CoreApplication::Suspending += ref new EventHandler<SuspendingEventArgs ^>(this, &App::OnSuspending);

  CoreApplication::Resuming += ref new EventHandler<Platform::Object ^>(this, &App::OnResuming);
}

// Called when the CoreWindow object is created (or re-created).
void App::SetWindow(CoreWindow ^ window) {
  window->SizeChanged +=
      ref new TypedEventHandler<CoreWindow ^, WindowSizeChangedEventArgs ^>(this, &App::OnWindowSizeChanged);

  window->VisibilityChanged +=
      ref new TypedEventHandler<CoreWindow ^, VisibilityChangedEventArgs ^>(this, &App::OnVisibilityChanged);

  window->Closed += ref new TypedEventHandler<CoreWindow ^, CoreWindowEventArgs ^>(this, &App::OnWindowClosed);

  DisplayInformation ^ currentDisplayInformation = DisplayInformation::GetForCurrentView();

  currentDisplayInformation->DpiChanged +=
      ref new TypedEventHandler<DisplayInformation ^, Object ^>(this, &App::OnDpiChanged);

  currentDisplayInformation->OrientationChanged +=
      ref new TypedEventHandler<DisplayInformation ^, Object ^>(this, &App::OnOrientationChanged);

  DisplayInformation::DisplayContentsInvalidated +=
      ref new TypedEventHandler<DisplayInformation ^, Object ^>(this, &App::OnDisplayContentsInvalidated);
}

// Initializes scene resources, or loads a previously saved app state.
void App::Load(Platform::String ^ entryPoint) {
  if (m_main == nullptr) {
    m_main = std::unique_ptr<PlayerWindow>(new PlayerWindow(CoreWindow::GetForCurrentThread()));
    m_decoder_state = m_main->Run();
  }
}

// This method is called after the window becomes active.
void App::Run() {
  DWORD lastPacketNumber = 0;
  while (!m_windowClosed) {
    if (m_decoder_state == -1) {
      // Decoder creation failed. Exit
      XB_LOGE << "Unable to create decoder instance. May be due to wrong application mode (must be GAME MODE)";
      break;
    }
    if (m_windowVisible) {
      CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
      XINPUT_STATE state;
      ZeroMemory(&state, sizeof(XINPUT_STATE));
      if (XInputGetState(0, &state) == ERROR_SUCCESS) {
        if (state.dwPacketNumber != lastPacketNumber) {
          if (state.Gamepad.wButtons == XINPUT_GAMEPAD_DPAD_RIGHT) {
            m_main->StopDecode(taskNext);
          }
          lastPacketNumber = state.dwPacketNumber;
        }
      }
      if (m_windowVisible) {
        m_main->ShowFrame();
      }
      if (m_main->isJobsDone()) {
        XB_LOGI << "Close main window";
        m_main->StopDecode(taskStop);
        m_windowClosed = true;
      }

    } else {
      CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
      m_main->StopDecode(taskStopFlush);
      m_windowClosed = true;
    }
  }
}

// Required for IFrameworkView.
// Terminate events do not cause Uninitialize to be called. It will be called if your IFrameworkView
// class is torn down while the app is in the foreground.
void App::Uninitialize() {}

// Application lifecycle event handlers.

void App::OnActivated(CoreApplicationView ^ applicationView, IActivatedEventArgs ^ args) {
  // Run() won't start until the CoreWindow is activated.
  CoreWindow::GetForCurrentThread()->Activate();
}

void App::OnSuspending(Platform::Object ^ sender, SuspendingEventArgs ^ args) {
  // Save app state asynchronously after requesting a deferral. Holding a deferral
  // indicates that the application is busy performing suspending operations. Be
  // aware that a deferral may not be held indefinitely. After about five seconds,
  // the app will be forced to exit.
  SuspendingDeferral ^ deferral = args->SuspendingOperation->GetDeferral();

  create_task([this, deferral]() {
    deferral->Complete();
  });
}

void App::OnResuming(Platform::Object ^ sender, Platform::Object ^ args) {
  // Restore any data or state that was unloaded on suspend. By default, data
  // and state are persisted when resuming from suspend. Note that this event
  // does not occur if the app was previously terminated.

  // m_main->OnResuming();
}

// Window event handlers.

void App::OnWindowSizeChanged(CoreWindow ^ sender, WindowSizeChangedEventArgs ^ args) {
  // GetDeviceResources()->SetLogicalSize(Size(sender->Bounds.Width, sender->Bounds.Height));
  // m_main->OnWindowSizeChanged();
}

void App::OnVisibilityChanged(CoreWindow ^ sender, VisibilityChangedEventArgs ^ args) {
  m_windowVisible = args->Visible;
}

void App::OnWindowClosed(CoreWindow ^ sender, CoreWindowEventArgs ^ args) { m_windowClosed = true; }

// DisplayInformation event handlers.

void App::OnDpiChanged(DisplayInformation ^ sender, Object ^ args) {
  // Note: The value for LogicalDpi retrieved here may not match the effective DPI of the app
  // if it is being scaled for high resolution devices. Once the DPI is set on DeviceResources,
  // you should always retrieve it using the GetDpi method.
  // See DeviceResources.cpp for more details.
  // GetDeviceResources()->SetDpi(sender->LogicalDpi);
  // m_main->OnWindowSizeChanged();
}

void App::OnOrientationChanged(DisplayInformation ^ sender, Object ^ args) {
  // GetDeviceResources()->SetCurrentOrientation(sender->CurrentOrientation);
  // m_main->OnWindowSizeChanged();
}

void App::OnDisplayContentsInvalidated(DisplayInformation ^ sender, Object ^ args) {
  // GetDeviceResources()->ValidateDevice();
}
