// 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 "cobalt/xhr/xhr_modify_headers.h"

#include "base/logging.h"
#include "base/synchronization/waitable_event.h"

#include "starboard/mutex.h"
#include "starboard/shared/uwp/async_utils.h"
#include "starboard/shared/uwp/winrt_workaround.h"
#include "starboard/shared/win32/wchar_utils.h"

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;
using Windows::System::UserAuthenticationStatus;
using Windows::UI::Core::CoreWindow;
using Windows::UI::Core::CoreDispatcherPriority;
using Windows::UI::Core::DispatchedHandler;

namespace sbwin32 = starboard::shared::win32;

namespace {
// The name of the header to send the STS token out on.
const char kXauthHeaderName[] = "Authorization";

// The prefix for the value of the Authorization header when there is an XAuth
// token to attach to the request. The token itself should directly follow this
// prefix.
const char kXauthHeaderPrefix[] = "XBL3.0 x=";

// The name of the header to detect on requests as a trigger to add an STS token
// for the given RelyingPartyId (the value of the header). The header itself
// will be removed from the outgoing request, and replaced with an Authorization
// header with a valid STS token for the current primary user.
const base::StringPiece kXauthTriggerHeaderName = "X-STS-RelyingPartyId";

inline std::ostream& operator<<(std::ostream& os,
                                const UserAuthenticationStatus& state) {
  switch (state) {
    case UserAuthenticationStatus::Unauthenticated:
      os << "Unauthenticated";
      break;
    case UserAuthenticationStatus::LocallyAuthenticated:
      os << "LocallyAuthenticated";
      break;
    case UserAuthenticationStatus::RemotelyAuthenticated:
      os << "RemotelyAuthenticated";
      break;
    default:
      os << "Unknown";
  }
  return os;
}

inline std::ostream& operator<<(std::ostream& os,
                                const WebTokenRequestStatus& status) {
  switch (status) {
    case WebTokenRequestStatus::Success:
      os << "Success";
      break;
    case WebTokenRequestStatus::AccountProviderNotAvailable:
      os << "Account provider is not available.";
      break;
    case WebTokenRequestStatus::AccountSwitch:
      os << "Account associated with the request was switched.";
      break;
    case WebTokenRequestStatus::ProviderError:
      os << "Provider Error.  See Provider's documentation.";
      break;
    case WebTokenRequestStatus::UserCancel:
      os << "User Cancel";
      break;
    case WebTokenRequestStatus::UserInteractionRequired:
      os << "User interaction is required.  Try the request with "
            "RequestTokenAsync";
      break;
    default:
      os << "Unknown case";
  }
  return os;
}

WebTokenRequestResult^ RequestToken(WebTokenRequest^ request) {
  using starboard::shared::uwp::WaitForResult;
  IAsyncOperation<WebTokenRequestResult ^> ^ request_operation = nullptr;
  base::WaitableEvent request_operation_set(false, false);
  // Ensure WebAuthenticationCoreManager::RequestTokenAsync is called on the
  // UI thread, since documentation states that "This method cannot be called
  // from background threads", per
  // https://docs.microsoft.com/en-us/uwp/api/windows.security.authentication.web.core.webauthenticationcoremanager
  Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow
      ->Dispatcher->RunAsync(
          CoreDispatcherPriority::Normal,
          ref new DispatchedHandler(
              [&request, &request_operation_set, &request_operation] {
                request_operation =
                    WebAuthenticationCoreManager::RequestTokenAsync(request);
                request_operation_set.Signal();
              }));
  request_operation_set.Wait();
  WebTokenRequestResult^ result = WaitForResult(request_operation);
  return result;
}

bool PopulateToken(const std::string& relying_party, std::string* out) {
  using starboard::shared::uwp::WaitForResult;
  DCHECK(out);
  WebAccountProvider^ xbox_provider =
      WaitForResult(WebAuthenticationCoreManager::FindAccountProviderAsync(
          "https://xsts.auth.xboxlive.com"));
  WebTokenRequest^ request = ref new WebTokenRequest(xbox_provider);
  Platform::String^ relying_party_cx =
    sbwin32::stringToPlatformString(relying_party);
  request->Properties->Insert("Url", relying_party_cx);
  request->Properties->Insert("Target", "xboxlive.signin");
  request->Properties->Insert("Policy", "DELEGATION");

  WebTokenRequestResult^ token_result = WaitForResult(
      WebAuthenticationCoreManager::GetTokenSilentlyAsync(request));
  if (token_result->ResponseStatus ==
      WebTokenRequestStatus::UserInteractionRequired) {
    token_result = RequestToken(request);
  }

  if (token_result->ResponseStatus == WebTokenRequestStatus::Success) {
    SB_DCHECK(token_result->ResponseData->Size == 1);
    if (token_result->ResponseData->Size != 1) {
      *out = "";
      return false;
    }
    WebTokenResponse^ token_response = token_result->ResponseData->GetAt(0);
    *out = sbwin32::platformStringToString(token_response->Token);
    return true;
  } else {
    SB_DLOG(INFO) << "Response Status " << token_result->ResponseStatus;
    if (token_result->ResponseError) {
      unsigned int error_code = token_result->ResponseError->ErrorCode;
      Platform::String^ message = token_result->ResponseError->ErrorMessage;
      SB_DLOG(INFO) << "Error code: " << error_code;
      SB_DLOG(INFO) << "Error message: "
        << sbwin32::platformStringToString(message);
    }
    *out = "";
  }

  return false;
}

}  // namespace

namespace cobalt {
namespace xhr {

void CobaltXhrModifyHeader(net::HttpRequestHeaders* headers) {
  DCHECK(headers);

  std::string relying_party;
  bool trigger_header_found = headers->GetHeader(kXauthTriggerHeaderName,
    &relying_party);

  if (!trigger_header_found) {
    return;
  }
  std::string out_string;
  if (!PopulateToken(relying_party, &out_string)) {
    return;
  }
  headers->RemoveHeader(kXauthTriggerHeaderName);
  headers->SetHeader(kXauthHeaderName, out_string);
}

}  // namespace xhr
}  // namespace cobalt
