// 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/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/file.h"
#include "starboard/common/string.h"
#include "starboard/configuration_constants.h"
#include "starboard/directory.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::AutoLock lock(lock_);
  base::Optional<std::string> key = GetKeyForStartUrl(url_);
  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 = GetKeyForStartUrl(url_);
  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;
}

// 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;
  }

  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 = "";
  std::string subcomponent = kSbFileSepString + std::string("splash_screen");
  if (SbStringConcat(path.data(), subcomponent.c_str(), kSbFileMaxPath) >=
      static_cast<int>(kSbFileMaxPath)) {
    return base::nullopt;
  }
  subpath += "splash_screen";
  subcomponent = kSbFileSepString + *encoded_url;
  if (SbStringConcat(path.data(), subcomponent.c_str(), kSbFileMaxPath) >=
      static_cast<int>(kSbFileMaxPath)) {
    return base::nullopt;
  }
  subpath += subcomponent;
  subcomponent = kSbFileSepString + std::string("splash.html");
  if (SbStringConcat(path.data(), subcomponent.c_str(), kSbFileMaxPath) >
      static_cast<int>(kSbFileMaxPath)) {
    return base::nullopt;
  }
  subpath += subcomponent;

  return subpath;
}

}  // namespace browser
}  // namespace cobalt
