// 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.

#include "starboard/shared/uwp/app_accessors.h"

#include "starboard/file.h"
#include "starboard/log.h"
#include "starboard/shared/win32/wchar_utils.h"

namespace sbuwp = starboard::shared::uwp;
namespace sbwin32 = starboard::shared::win32;

using Windows::Security::Authentication::Web::Core::
    WebAuthenticationCoreManager;
using Windows::Security::Authentication::Web::Core::WebTokenRequest;
using Windows::Security::Authentication::Web::Core::WebTokenResponse;
using Windows::Security::Authentication::Web::Core::WebTokenRequestResult;
using Windows::Security::Authentication::Web::Core::WebTokenRequestStatus;
using Windows::Security::Credentials::WebAccountProvider;

namespace {

const char kXboxLiveAccountProviderId[] = "https://xsts.auth.xboxlive.com";

// Filename, placed in the cache dir, whose presence indicates
// that the user has rejected the SSO approval dialog
const char kSsoRejectionFilename[] = "sso_rejection";

std::string GetSsoRejectionFilePath() {
  char path[SB_FILE_MAX_PATH];
  bool success = SbSystemGetPath(kSbSystemPathCacheDirectory,
                                 path, SB_FILE_MAX_PATH);
  SB_DCHECK(success);
  std::string file_path(path);
  file_path.append(1, '/');
  file_path.append(kSsoRejectionFilename);

  return file_path;
}

}  // namespace

namespace starboard {
namespace shared {
namespace uwp {

concurrency::task<WebTokenRequestResult^> TryToFetchSsoToken(
    const std::string& url) {
  if (SbFileExists(GetSsoRejectionFilePath().c_str())) {
    concurrency::task_completion_event<WebTokenRequestResult^> result;
    result.set(nullptr);
    return concurrency::task<WebTokenRequestResult^>(result);
  }
  return concurrency::create_task(
      WebAuthenticationCoreManager::FindAccountProviderAsync(
          sbwin32::stringToPlatformString(kXboxLiveAccountProviderId)))
  .then([url](concurrency::task<WebAccountProvider^> previous_task) {
    WebAccountProvider^ xbox_provider = nullptr;
    try {
      xbox_provider = previous_task.get();
    } catch (Platform::Exception^) {
      SB_LOG(INFO) << "Exception with FindAccountProviderAsync";
      concurrency::task_completion_event<WebTokenRequestResult^> result;
      result.set(nullptr);
      return concurrency::task<WebTokenRequestResult^>(result);
    }
    WebTokenRequest^ request = ref new WebTokenRequest(xbox_provider);
    request->Properties->Insert("Url",
        sbwin32::stringToPlatformString(url));
    request->Properties->Insert("Target", "xboxlive.signin");
    request->Properties->Insert("Policy", "DELEGATION");

    bool main_thread = sbuwp::GetDispatcher()->HasThreadAccess;

    if (main_thread) {
      return concurrency::create_task(
          WebAuthenticationCoreManager::RequestTokenAsync(request));
    } else {
      return concurrency::create_task(
          WebAuthenticationCoreManager::GetTokenSilentlyAsync(request));
    }
  })
  .then([url](concurrency::task<WebTokenRequestResult^> previous_task) {
    WebTokenRequestResult^ token_result = previous_task.get();
    try {
      token_result = previous_task.get();
    } catch(Platform::Exception^ ex) {
      SB_LOG(INFO) << "Exception during RequestTokenAsync";
      concurrency::task_completion_event<WebTokenRequestResult^> result;
      result.set_exception(ex);
      return concurrency::task<WebTokenRequestResult^>(result);
    }

    if (!token_result) {
      return previous_task;
    }

    switch (token_result->ResponseStatus) {
      case WebTokenRequestStatus::UserCancel: {
        bool created;
        SbFile file = SbFileOpen(GetSsoRejectionFilePath().c_str(),
            kSbFileRead | kSbFileOpenAlways, &created, nullptr);
        SbFileClose(file);
        return previous_task;
      }

      case WebTokenRequestStatus::UserInteractionRequired: {
        concurrency::task_completion_event<WebTokenRequestResult^> completion;
        RunInMainThreadAsync([url, completion]() {
          // When we run TryToFetchSsoToken in the main thread,
          // we'll always ask for user input via RequestTokenAsync, which
          // never returns this case.
          TryToFetchSsoToken(url)
          .then([completion](concurrency::task<WebTokenRequestResult^> result) {
            try {
              completion.set(result.get());
            } catch (Platform::Exception^ ex) {
              completion.set_exception(ex);
            }
          });
        });

        return concurrency::task<WebTokenRequestResult^>(completion);
      }

      default:
        return previous_task;
    }
  });
}

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