// 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/browser/splash_screen_cache.h"

#include <string>

#include "base/base64.h"
#include "base/memory/scoped_ptr.h"
#include "base/optional.h"
#include "base/string_util.h"
#include "base/synchronization/lock.h"
#include "starboard/directory.h"
#include "starboard/file.h"
#include "starboard/string.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() { 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;
  }

  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, scoped_array<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);
  return result_size;
}

// static
base::optional<std::string> SplashScreenCache::GetKeyForStartUrl(
    const GURL& url) {
  std::string encoded_url = "";
  if (!url.is_valid()) {
    return base::nullopt;
  }
  base::Base64Encode(base::StringPiece(url.host() + url.path()), &encoded_url);

  // Make web-safe.
  ReplaceChars(encoded_url, "/", "_", &encoded_url);
  ReplaceChars(encoded_url, "+", "-", &encoded_url);

  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
