// 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 <string>

#include "base/memory/scoped_ptr.h"
#include "base/optional.h"
#include "base/string_util.h"
#include "base/synchronization/lock.h"
#include "cobalt/base/get_application_key.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) {
  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
