/*
 * Copyright 2016 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/h5vcc/h5vcc_account_manager.h"

#include "base/memory/scoped_ptr.h"
#include "starboard/ps4/application_linking.h"
#include "starboard/user.h"

namespace cobalt {
namespace h5vcc {

H5vccAccountManager::H5vccAccountManager()
    : thread_("AccountManager"), owning_message_loop_(MessageLoop::current()) {
  thread_.Start();
}

void H5vccAccountManager::GetAuthToken(
    const AccessTokenCallbackHolder& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DLOG(INFO) << "Get authorization token.";
  scoped_ptr<AccessTokenCallbackReference> token_callback(
      new AccessTokenCallbackHolder::Reference(this, callback));
  thread_.message_loop()->PostTask(
      FROM_HERE, base::Bind(&H5vccAccountManager::RequestOperationInternal,
                            this, kGetToken, base::Passed(&token_callback)));
}

void H5vccAccountManager::RequestPairing(
    const AccessTokenCallbackHolder& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DLOG(INFO) << "Request application linking.";
  scoped_ptr<AccessTokenCallbackReference> token_callback(
      new AccessTokenCallbackHolder::Reference(this, callback));
  thread_.message_loop()->PostTask(
      FROM_HERE, base::Bind(&H5vccAccountManager::RequestOperationInternal,
                            this, kPairing, base::Passed(&token_callback)));
}

void H5vccAccountManager::RequestUnpairing(
    const AccessTokenCallbackHolder& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DLOG(INFO) << "Request application unlinking.";
  scoped_ptr<AccessTokenCallbackReference> token_callback(
      new AccessTokenCallbackHolder::Reference(this, callback));
  thread_.message_loop()->PostTask(
      FROM_HERE, base::Bind(&H5vccAccountManager::RequestOperationInternal,
                            this, kUnpairing, base::Passed(&token_callback)));
}

H5vccAccountManager::~H5vccAccountManager() {
  DCHECK(thread_checker_.CalledOnValidThread());
}

void H5vccAccountManager::RequestOperationInternal(
    OperationType operation,
    scoped_ptr<AccessTokenCallbackReference> token_callback) {
  DCHECK_EQ(thread_.message_loop(), MessageLoop::current());

  SbUser current_user = SbUserGetCurrent();
  DCHECK(SbUserIsValid(current_user));

  static size_t kBufferSize = SbUserMaxAuthenticationTokenSizeInBytes();
  scoped_array<char> token_buffer(new char[kBufferSize]);
  SbUserApplicationTokenResults token_results;
  token_results.token_buffer_size = kBufferSize;
  token_results.token_buffer = token_buffer.get();

  bool got_valid_token = false;
  switch (operation) {
    case kPairing:
      got_valid_token =
          SbUserRequestApplicationLinking(current_user, &token_results);
      DLOG_IF(INFO, !got_valid_token) << "Application linking request failed.";
      break;
    case kUnpairing:
      if (SbUserRequestApplicationUnlinking(current_user)) {
        got_valid_token = false;
        break;
      }
      // The user canceled the flow, or there was some error. Fall into the next
      // case to get an access token if available and return that.
      DLOG(INFO) << "Application unlinking request failed. Try to get token.";
    case kGetToken:
      got_valid_token =
          SbUserRequestAuthenticationToken(current_user, &token_results);
      DLOG_IF(INFO, !got_valid_token) << "Authentication token request failed.";
      break;
  }

  uint64_t expiration_in_seconds = 0;
  if (got_valid_token) {
    SbTime expires_in = token_results.expiry - SbTimeGetNow();
    // If this token's expiry is in the past, then we didn't get a valid token.
    if (expires_in < 0) {
      DLOG(WARNING) << "Authentication token expires in the past.";
      got_valid_token = false;
    } else {
      expiration_in_seconds = expires_in / kSbTimeSecond;
    }
  }
  // If we did not get a valid token to return to the caller, set the token
  // buffer to an empty string.
  if (!got_valid_token) {
    token_buffer[0] = '\0';
  }

  owning_message_loop_->PostTask(
      FROM_HERE,
      base::Bind(&H5vccAccountManager::SendResult, this,
                 base::Passed(&token_callback), std::string(token_buffer.get()),
                 expiration_in_seconds));
}

void H5vccAccountManager::SendResult(
    scoped_ptr<AccessTokenCallbackReference> token_callback,
    const std::string& token, uint64_t expiration_in_seconds) {
  DCHECK(thread_checker_.CalledOnValidThread());
  token_callback->value().Run(token, expiration_in_seconds);
}

}  // namespace h5vcc
}  // namespace cobalt
