// Copyright 2017 The Cobalt Authors. 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/browser/splash_screen_cache.h"

#include <memory>
#include <string>
#include <vector>

#include "base/base64.h"
#include "base/hash.h"
#include "base/optional.h"
#include "base/strings/string_util.h"
#include "base/synchronization/lock.h"
#include "cobalt/base/get_application_key.h"
#include "starboard/common/string.h"
#include "starboard/configuration_constants.h"
#include "starboard/directory.h"
#include "starboard/file.h"

namespace cobalt {
namespace browser {
namespace {
bool CreateDirsForKey(const std::string& key) {
  std::vector<char> path(kSbFileMaxPath, 0);
  if (!SbSystemGetPath(kSbSystemPathCacheDirectory, path.data(),
                       kSbFileMaxPath)) {
    return false;
  }
  std::size_t prev_found = 0;
  std::size_t found = key.find(kSbFileSepString);
  SbStringConcat(path.data(), kSbFileSepString, kSbFileMaxPath);
  while (found != std::string::npos) {
    SbStringConcat(path.data(),
                   key.substr(prev_found, found - prev_found).c_str(),
                   kSbFileMaxPath);
    if (!SbDirectoryCreate(path.data())) {
      return false;
    }
    prev_found = found;
    found = key.find(kSbFileSepString, prev_found + 1);
  }
  return true;
}

}  // namespace

SplashScreenCache::SplashScreenCache() : last_page_hash_(0) {
  base::AutoLock lock(lock_);
}

bool SplashScreenCache::CacheSplashScreen(
    const std::string& content,
    const base::Optional<std::string>& topic) const {
  base::AutoLock lock(lock_);
  // Cache the content so that it's retrievable for the topic specified in the
  // rel attribute. This topic may or may not match the topic-specified for this
  // particular startup, tracked with "topic_".
  base::Optional<std::string> key = GetKeyForStartConfig(url_, topic);
  if (!key) {
    return false;
  }

  // If an identical page was already read from disk, skip writing
  if (base::Hash(content) == last_page_hash_) {
    return false;
  }

  std::vector<char> path(kSbFileMaxPath, 0);
  if (!SbSystemGetPath(kSbSystemPathCacheDirectory, path.data(),
                       kSbFileMaxPath)) {
    return false;
  }
  if (!CreateDirsForKey(key.value())) {
    return false;
  }
  std::string full_path =
      std::string(path.data()) + kSbFileSepString + key.value();
  starboard::ScopedFile cache_file(
      full_path.c_str(), kSbFileCreateAlways | kSbFileWrite, NULL, NULL);

  return cache_file.WriteAll(content.c_str(),
                             static_cast<int>(content.size())) > 0;
}

bool SplashScreenCache::IsSplashScreenCached() const {
  base::AutoLock lock(lock_);
  std::vector<char> path(kSbFileMaxPath, 0);
  if (!SbSystemGetPath(kSbSystemPathCacheDirectory, path.data(),
                       kSbFileMaxPath)) {
    return false;
  }
  base::Optional<std::string> key = GetKeyForStartConfig(url_, topic_);
  if (!key) return false;
  std::string full_path =
      std::string(path.data()) + kSbFileSepString + key.value();
  return SbFileExists(full_path.c_str());
}

int SplashScreenCache::ReadCachedSplashScreen(
    const std::string& key, std::unique_ptr<char[]>* result) const {
  base::AutoLock lock(lock_);
  if (!result) {
    return 0;
  }
  std::vector<char> path(kSbFileMaxPath, 0);
  if (!SbSystemGetPath(kSbSystemPathCacheDirectory, path.data(),
                       kSbFileMaxPath)) {
    result->reset();
    return 0;
  }
  std::string full_path = std::string(path.data()) + kSbFileSepString + key;
  starboard::ScopedFile cache_file(full_path.c_str(),
                                   kSbFileOpenOnly | kSbFileRead, NULL, NULL);
  SbFileInfo info;
  bool success = SbFileGetPathInfo(full_path.c_str(), &info);
  if (!success) {
    result->reset();
    return 0;
  }
  const int kFileSize = static_cast<int>(info.size);
  result->reset(new char[kFileSize]);
  int result_size = cache_file.ReadAll(result->get(), kFileSize);
  last_page_hash_ = base::Hash(result->get(), result_size);
  return result_size;
}

base::Optional<std::string> SplashScreenCache::GetKeyForStartConfig(
    const GURL& url, const base::Optional<std::string>& topic) const {
  base::Optional<std::string> encoded_url = base::GetApplicationKey(url);
  if (!encoded_url) {
    return base::nullopt;
  }

  std::vector<char> path(kSbFileMaxPath, 0);
  bool has_cache_dir =
      SbSystemGetPath(kSbSystemPathCacheDirectory, path.data(), kSbFileMaxPath);
  if (!has_cache_dir) {
    return base::nullopt;
  }

  std::string subpath = "";
  if (!AddPathDirectory(std::string("splash_screen"), path, subpath)) {
    return base::nullopt;
  }
  if (!AddPathDirectory(*encoded_url, path, subpath)) {
    return base::nullopt;
  }
  if (topic && !topic.value().empty()) {
    std::string encoded_topic;
    base::Base64Encode(topic.value(), &encoded_topic);
    if (!AddPathDirectory(encoded_topic, path, subpath)) {
      return base::nullopt;
    }
  }
  if (!AddPathDirectory(std::string("splash.html"), path, subpath)) {
    return base::nullopt;
  }

  return subpath.erase(0, 1);  // Remove leading separator
}

bool SplashScreenCache::AddPathDirectory(const std::string& directory,
                                         std::vector<char>& path,
                                         std::string& subpath) const {
  std::string subcomponent = kSbFileSepString + directory;
  if (SbStringConcat(path.data(), subcomponent.c_str(), kSbFileMaxPath) >=
      static_cast<int>(kSbFileMaxPath)) {
    return false;
  }
  subpath += subcomponent;
  return true;
}

}  // namespace browser
}  // namespace cobalt
