// 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 "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/directory.h"
#include "starboard/file.h"

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

}  // namespace

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

bool SplashScreenCache::CacheSplashScreen(const std::string& key,
                                          const std::string& content) const {
  base::AutoLock lock(lock_);
  if (key.empty()) {
    return false;
  }

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

  char path[SB_FILE_MAX_PATH] = {0};
  if (!SbSystemGetPath(kSbSystemPathCacheDirectory, path, SB_FILE_MAX_PATH)) {
    return false;
  }
  if (!CreateDirsForKey(key)) {
    return false;
  }
  std::string full_path = path + (SB_FILE_SEP_STRING + key);
  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 std::string& key) const {
  base::AutoLock lock(lock_);
  char path[SB_FILE_MAX_PATH] = {0};
  if (!SbSystemGetPath(kSbSystemPathCacheDirectory, path, SB_FILE_MAX_PATH)) {
    return false;
  }
  std::string full_path = path + (SB_FILE_SEP_STRING + key);
  return !key.empty() && 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;
  }
  char path[SB_FILE_MAX_PATH] = {0};
  if (!SbSystemGetPath(kSbSystemPathCacheDirectory, path, SB_FILE_MAX_PATH)) {
    result->reset();
    return 0;
  }
  std::string full_path = path + (SB_FILE_SEP_STRING + 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;
}

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

  char path[SB_FILE_MAX_PATH] = {0};
  bool has_cache_dir =
      SbSystemGetPath(kSbSystemPathCacheDirectory, path, SB_FILE_MAX_PATH);
  if (!has_cache_dir) {
    return base::nullopt;
  }

  std::string subpath = "";
  std::string subcomponent = SB_FILE_SEP_STRING + std::string("splash_screen");
  if (SbStringConcat(path, subcomponent.c_str(), SB_FILE_MAX_PATH) >=
      SB_FILE_MAX_PATH) {
    return base::nullopt;
  }
  subpath += "splash_screen";
  subcomponent = SB_FILE_SEP_STRING + *encoded_url;
  if (SbStringConcat(path, subcomponent.c_str(), SB_FILE_MAX_PATH) >=
      SB_FILE_MAX_PATH) {
    return base::nullopt;
  }
  subpath += subcomponent;
  subcomponent = SB_FILE_SEP_STRING + std::string("splash.html");
  if (SbStringConcat(path, subcomponent.c_str(), SB_FILE_MAX_PATH) >
      SB_FILE_MAX_PATH) {
    return base::nullopt;
  }
  subpath += subcomponent;

  return subpath;
}

}  // namespace browser
}  // namespace cobalt
