/*
 * Copyright 2010 Google Inc.
 *
 * 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.
 */

// Author: abliss@google.com (Adam Bliss)

#include "pagespeed/kernel/base/mem_file_system.h"

#include <cstddef>
#include <map>
#include <utility>

#include "base/logging.h"
#include "pagespeed/kernel/base/abstract_mutex.h"
#include "pagespeed/kernel/base/basictypes.h"
#include "pagespeed/kernel/base/file_system.h"
#include "pagespeed/kernel/base/message_handler.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/timer.h"
#include "pagespeed/kernel/base/thread_system.h"
#include "pagespeed/kernel/base/mock_timer.h"

namespace net_instaweb {

class MemInputFile : public FileSystem::InputFile {
 public:
  MemInputFile(const StringPiece& filename, const GoogleString& contents)
      : contents_(contents),
        filename_(filename.data(), filename.size()),
        offset_(0) {
  }

  virtual bool Close(MessageHandler* message_handler) {
    offset_ = contents_.length();
    return true;
  }

  virtual const char* filename() { return filename_.c_str(); }

  virtual int Read(char* buf, int size, MessageHandler* message_handler) {
    if (size + offset_ > static_cast<int>(contents_.length())) {
      size = contents_.length() - offset_;
    }
    memcpy(buf, contents_.c_str() + offset_, size);
    offset_ += size;
    return size;
  }

  virtual bool ReadFile(GoogleString* buf, MessageHandler* message_handler) {
    *buf = contents_;
    return true;
  }

 private:
  const GoogleString contents_;
  const GoogleString filename_;
  int offset_;

  DISALLOW_COPY_AND_ASSIGN(MemInputFile);
};


class MemOutputFile : public FileSystem::OutputFile {
 public:
  MemOutputFile(
      const StringPiece& filename, GoogleString* contents, bool append)
      : contents_(contents), filename_(filename.data(), filename.size()) {
    if (!append) {
      contents_->clear();
    }
  }

  virtual bool Close(MessageHandler* message_handler) {
    Flush(message_handler);
    return true;
  }

  virtual const char* filename() { return filename_.c_str(); }

  virtual bool Flush(MessageHandler* message_handler) {
    contents_->append(written_);
    written_.clear();
    return true;
  }

  virtual bool SetWorldReadable(MessageHandler* message_handler) {
    return true;
  }

  virtual bool Write(const StringPiece& buf, MessageHandler* handler) {
    buf.AppendToString(&written_);
    return true;
  }

 private:
  GoogleString* contents_;
  const GoogleString filename_;
  GoogleString written_;

  DISALLOW_COPY_AND_ASSIGN(MemOutputFile);
};

MemFileSystem::MemFileSystem(ThreadSystem* threads, Timer* timer)
    : lock_map_mutex_(threads->NewMutex()),
      all_else_mutex_(threads->NewMutex()),
      enabled_(true),
      timer_(timer),
      mock_timer_(NULL),
      temp_file_index_(0),
      atime_enabled_(true),
      advance_time_on_update_(false) {
  ClearStats();
}

MemFileSystem::~MemFileSystem() {
}

void MemFileSystem::UpdateAtime(const StringPiece& path) {
  if (atime_enabled_) {
    int64 now_us = timer_->NowUs();
    int64 now_s = now_us / Timer::kSecondUs;
    if (advance_time_on_update_) {
      mock_timer_->AdvanceUs(Timer::kSecondUs);
    }
    atime_map_[path.as_string()] = now_s;
  }
}

void MemFileSystem::UpdateMtime(const StringPiece& path) {
  int64 now_us = timer_->NowUs();
  int64 now_s = now_us / Timer::kSecondUs;
  mtime_map_[path.as_string()] = now_s;
}

void MemFileSystem::Clear() {
  ScopedMutex lock(all_else_mutex_.get());
  string_map_.clear();
}

BoolOrError MemFileSystem::Exists(const char* path, MessageHandler* handler) {
  ScopedMutex lock(all_else_mutex_.get());
  StringStringMap::const_iterator iter = string_map_.find(path);
  return BoolOrError(iter != string_map_.end());
}

BoolOrError MemFileSystem::IsDir(const char* path, MessageHandler* handler) {
  return Exists(path, handler).is_true()
      ? BoolOrError(EndsInSlash(path)) : BoolOrError();
}

bool MemFileSystem::MakeDir(const char* path, MessageHandler* handler) {
  // We store directories as empty files with trailing slashes.
  ScopedMutex lock(all_else_mutex_.get());
  GoogleString path_string = path;
  EnsureEndsInSlash(&path_string);
  string_map_[path_string] = "";
  UpdateAtime(path_string);
  UpdateMtime(path_string);
  return true;
}

bool MemFileSystem::RemoveDir(const char* path, MessageHandler* handler) {
  ScopedMutex lock(all_else_mutex_.get());
  GoogleString path_string = path;
  EnsureEndsInSlash(&path_string);

  StringStringMap::const_iterator iter = string_map_.find(path_string);

  // Verify that this directory exists
  if (iter == string_map_.end()) {
    handler->Message(kError, "Failed to remove directory %s: directory does "
                     "not exist", path);
    return false;
  }

  // Verify that no files are stored in this directory. We can do this by
  // checking to see if the next string in the map starts with this directory
  // path. Note this depends on using a data structure that keeps its elements
  // sorted by key (such as a map).
  StringStringMap::const_iterator next_iter = iter;
  ++next_iter;
  if (next_iter != string_map_.end() &&
      next_iter->first.find(iter->first) == 0) {
    handler->Message(kError, "Failed to remove directory %s: directory is not "
                     "empty", path);
    return false;
  }

  // This directory exists and is empty, so remove it
  atime_map_.erase(path_string);
  mtime_map_.erase(path_string);
  string_map_.erase(path_string);
  return true;
}

FileSystem::InputFile* MemFileSystem::OpenInputFile(
    const char* filename, MessageHandler* message_handler) {
  ScopedMutex lock(all_else_mutex_.get());

  ++num_input_file_opens_;
  if (!enabled_) {
    return NULL;
  }

  StringStringMap::const_iterator iter = string_map_.find(filename);
  if (iter == string_map_.end()) {
    message_handler->Error(filename, 0, "opening input file: %s",
                           "file not found");
    return NULL;
  } else {
    UpdateAtime(filename);
    return new MemInputFile(filename, iter->second);
  }
}

FileSystem::OutputFile* MemFileSystem::OpenOutputFileHelper(
    const char* filename, bool append, MessageHandler* message_handler) {
  ScopedMutex lock(all_else_mutex_.get());
  UpdateAtime(filename);
  UpdateMtime(filename);
  ++num_output_file_opens_;
  return new MemOutputFile(filename, &(string_map_[filename]), append);
}

FileSystem::OutputFile* MemFileSystem::OpenTempFileHelper(
    const StringPiece& prefix, MessageHandler* message_handler) {
  ScopedMutex lock(all_else_mutex_.get());
  GoogleString filename = StringPrintf("tmpfile%d", temp_file_index_++);
  UpdateAtime(filename);
  UpdateMtime(filename);
  ++num_temp_file_opens_;
  return new MemOutputFile(filename, &string_map_[filename], false);
}

bool MemFileSystem::RecursivelyMakeDir(const StringPiece& full_path_const,
                                       MessageHandler* handler) {
  // This is called to make sure that files can be written under the
  // named directory.  We don't have directories and files can be
  // written anywhere, so just return true.
  return true;
}

bool MemFileSystem::RemoveFile(const char* filename,
                               MessageHandler* handler) {
  ScopedMutex lock(all_else_mutex_.get());
  atime_map_.erase(filename);
  mtime_map_.erase(filename);
  return (string_map_.erase(filename) == 1);
}

bool MemFileSystem::RenameFileHelper(const char* old_file,
                                     const char* new_file,
                                     MessageHandler* handler) {
  ScopedMutex lock(all_else_mutex_.get());

  if (strcmp(old_file, new_file) == 0) {
    handler->Error(old_file, 0, "Cannot move a file to itself");
    return false;
  }

  StringStringMap::iterator iter = string_map_.find(old_file);
  if (iter == string_map_.end()) {
    handler->Error(old_file, 0, "File not found");
    return false;
  }

  string_map_[new_file] = iter->second;
  string_map_.erase(iter);

  UpdateAtime(new_file);
  atime_map_.erase(old_file);
  mtime_map_[new_file] = mtime_map_[old_file];
  mtime_map_.erase(old_file);

  return true;
}

bool MemFileSystem::ListContents(const StringPiece& dir, StringVector* files,
                                 MessageHandler* handler) {
  ScopedMutex lock(all_else_mutex_.get());
  GoogleString prefix = dir.as_string();
  EnsureEndsInSlash(&prefix);
  const size_t prefix_length = prefix.size();
  // We don't have directories, so we just list everything in the
  // filesystem that matches the prefix and doesn't have another
  // internal slash.
  for (StringStringMap::iterator it = string_map_.begin(),
           end = string_map_.end(); it != end; it++) {
    const GoogleString& path = (*it).first;
    if ((0 == path.compare(0, prefix_length, prefix)) &&
        path.length() > prefix_length) {
      const size_t next_slash = path.find("/", prefix_length + 1);
      // Only want to list files without another slash, unless that
      // slash is the last char in the filename.
      if ((next_slash == GoogleString::npos)
          || (next_slash == path.length() - 1)) {
        files->push_back(path);
      }
    }
  }
  return true;
}

bool MemFileSystem::Atime(const StringPiece& path, int64* timestamp_sec,
                          MessageHandler* handler) {
  ScopedMutex lock(all_else_mutex_.get());
  *timestamp_sec = atime_map_[path.as_string()];
  return true;
}

bool MemFileSystem::Mtime(const StringPiece& path, int64* timestamp_sec,
                          MessageHandler* handler) {
  ScopedMutex lock(all_else_mutex_.get());
  ++num_input_file_stats_;
  *timestamp_sec = mtime_map_[path.as_string()];
  return true;
}

bool MemFileSystem::Size(const StringPiece& path, int64* size,
                         MessageHandler* handler) {
  ScopedMutex lock(all_else_mutex_.get());
  const GoogleString path_string = path.as_string();
  StringStringMap::const_iterator iter = string_map_.find(path_string);
  if (iter != string_map_.end()) {
    *size = iter->second.size();
    return true;
  } else {
    return false;
  }
}

BoolOrError MemFileSystem::TryLock(const StringPiece& lock_name,
                                   MessageHandler* handler) {
  ScopedMutex lock(lock_map_mutex_.get());

  if (lock_map_.count(lock_name.as_string()) != 0) {
    return BoolOrError(false);
  } else {
    lock_map_[lock_name.as_string()] = timer_->NowMs();
    return BoolOrError(true);
  }
}

BoolOrError MemFileSystem::TryLockWithTimeout(const StringPiece& lock_name,
                                              int64 timeout_ms,
                                              const Timer* timer,
                                              MessageHandler* handler) {
  ScopedMutex lock(lock_map_mutex_.get());

  DCHECK_EQ(timer, timer_);
  GoogleString name = lock_name.as_string();
  int64 now = timer->NowMs();
  if (lock_map_.count(name) != 0 &&
      now <= lock_map_[name] + timeout_ms) {
    return BoolOrError(false);
  } else {
    lock_map_[name] = timer->NowMs();
    return BoolOrError(true);
  }
}

bool MemFileSystem::Unlock(const StringPiece& lock_name,
                           MessageHandler* handler) {
  ScopedMutex lock(lock_map_mutex_.get());
  return (lock_map_.erase(lock_name.as_string()) == 1);
}

bool MemFileSystem::WriteFile(const char* filename,
                              const StringPiece& buffer,
                              MessageHandler* handler) {
  bool ret = FileSystem::WriteFile(filename, buffer, handler);
  if (write_callback_.get() != NULL) {
    write_callback_.release()->Run(filename);
  }
  return ret;
}

bool MemFileSystem::WriteTempFile(const StringPiece& prefix_name,
                                  const StringPiece& buffer,
                                  GoogleString* filename,
                                  MessageHandler* handler) {
  bool ret = FileSystem::WriteTempFile(prefix_name, buffer, filename, handler);
  if (write_callback_.get() != NULL) {
    write_callback_.release()->Run(*filename);
  }
  return ret;
}

}  // namespace net_instaweb
