// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#ifndef RUNTIME_BIN_DIRECTORY_H_
#define RUNTIME_BIN_DIRECTORY_H_

#include "bin/builtin.h"
#include "bin/dartutils.h"
#include "bin/reference_counting.h"
#include "bin/thread.h"
#include "platform/globals.h"

namespace dart {
namespace bin {

enum ListType {
  kListFile = 0,
  kListDirectory = 1,
  kListLink = 2,
  kListError = 3,
  kListDone = 4
};

class PathBuffer {
 public:
  PathBuffer();
  ~PathBuffer();

  bool Add(const char* name);
  bool AddW(const wchar_t* name);

  char* AsString() const;
  wchar_t* AsStringW() const;

  // Makes a scope allocated copy of the string.
  const char* AsScopedString() const;

  void Reset(intptr_t new_length);

  intptr_t length() const { return length_; }

 private:
  void* data_;
  intptr_t length_;

  DISALLOW_COPY_AND_ASSIGN(PathBuffer);
};

class DirectoryListing;

struct LinkList;

// DirectoryListingEntry is used as a stack item, when performing recursive
// directory listing. By using DirectoryListingEntry as stack elements, a
// directory listing can be paused e.g. when a buffer is full, and resumed
// later on.
//
// The stack is managed by the DirectoryListing's PathBuffer. Each
// DirectoryListingEntry stored a entry-length, that it'll reset the PathBuffer
// to on each call to Next.
class DirectoryListingEntry {
 public:
  explicit DirectoryListingEntry(DirectoryListingEntry* parent)
      : parent_(parent), lister_(0), done_(false), link_(NULL) {}

  ~DirectoryListingEntry();

  ListType Next(DirectoryListing* listing);

  DirectoryListingEntry* parent() const { return parent_; }

  LinkList* link() { return link_; }

  void set_link(LinkList* link) { link_ = link; }

  void ResetLink();

 private:
  DirectoryListingEntry* parent_;
  intptr_t lister_;
  bool done_;
  int path_length_;
  LinkList* link_;

  DISALLOW_COPY_AND_ASSIGN(DirectoryListingEntry);
};

class DirectoryListing {
 public:
  DirectoryListing(const char* dir_name, bool recursive, bool follow_links)
      : top_(NULL),
        error_(false),
        recursive_(recursive),
        follow_links_(follow_links) {
    if (!path_buffer_.Add(dir_name)) {
      error_ = true;
    }
    Push(new DirectoryListingEntry(NULL));
  }

  virtual ~DirectoryListing() { PopAll(); }

  virtual bool HandleDirectory(const char* dir_name) = 0;
  virtual bool HandleFile(const char* file_name) = 0;
  virtual bool HandleLink(const char* link_name) = 0;
  virtual bool HandleError() = 0;
  virtual void HandleDone() {}

  void Push(DirectoryListingEntry* directory) { top_ = directory; }

  void Pop() {
    ASSERT(!IsEmpty());
    DirectoryListingEntry* current = top_;
    top_ = top_->parent();
    delete current;
  }

  bool IsEmpty() const { return top_ == NULL; }

  void PopAll() {
    while (!IsEmpty()) {
      Pop();
    }
  }

  DirectoryListingEntry* top() const { return top_; }

  bool recursive() const { return recursive_; }

  bool follow_links() const { return follow_links_; }

  const char* CurrentPath() { return path_buffer_.AsScopedString(); }

  PathBuffer& path_buffer() { return path_buffer_; }

  bool error() const { return error_; }

 private:
  PathBuffer path_buffer_;
  DirectoryListingEntry* top_;
  bool error_;
  bool recursive_;
  bool follow_links_;
};


class AsyncDirectoryListing : public ReferenceCounted<AsyncDirectoryListing>,
                              public DirectoryListing {
 public:
  enum Response {
    kListFile = 0,
    kListDirectory = 1,
    kListLink = 2,
    kListError = 3,
    kListDone = 4
  };

  AsyncDirectoryListing(const char* dir_name, bool recursive, bool follow_links)
      : ReferenceCounted(),
        DirectoryListing(dir_name, recursive, follow_links),
        array_(NULL),
        index_(0),
        length_(0) {}

  virtual bool HandleDirectory(const char* dir_name);
  virtual bool HandleFile(const char* file_name);
  virtual bool HandleLink(const char* file_name);
  virtual bool HandleError();
  virtual void HandleDone();

  void SetArray(CObjectArray* array, intptr_t length) {
    ASSERT(length % 2 == 0);
    array_ = array;
    index_ = 0;
    length_ = length;
  }

  intptr_t index() const { return index_; }

 private:
  virtual ~AsyncDirectoryListing() {}
  bool AddFileSystemEntityToResponse(Response response, const char* arg);
  CObjectArray* array_;
  intptr_t index_;
  intptr_t length_;

  friend class ReferenceCounted<AsyncDirectoryListing>;
  DISALLOW_IMPLICIT_CONSTRUCTORS(AsyncDirectoryListing);
};


class SyncDirectoryListing : public DirectoryListing {
 public:
  SyncDirectoryListing(Dart_Handle results,
                       const char* dir_name,
                       bool recursive,
                       bool follow_links)
      : DirectoryListing(dir_name, recursive, follow_links), results_(results) {
    add_string_ = DartUtils::NewString("add");
    directory_type_ = DartUtils::GetDartType(DartUtils::kIOLibURL, "Directory");
    file_type_ = DartUtils::GetDartType(DartUtils::kIOLibURL, "File");
    link_type_ = DartUtils::GetDartType(DartUtils::kIOLibURL, "Link");
  }
  virtual ~SyncDirectoryListing() {}
  virtual bool HandleDirectory(const char* dir_name);
  virtual bool HandleFile(const char* file_name);
  virtual bool HandleLink(const char* file_name);
  virtual bool HandleError();

 private:
  Dart_Handle results_;
  Dart_Handle add_string_;
  Dart_Handle directory_type_;
  Dart_Handle file_type_;
  Dart_Handle link_type_;

  DISALLOW_ALLOCATION()
  DISALLOW_IMPLICIT_CONSTRUCTORS(SyncDirectoryListing);
};


class Directory {
 public:
  enum ExistsResult { UNKNOWN, EXISTS, DOES_NOT_EXIST };

  static void List(DirectoryListing* listing);
  static ExistsResult Exists(const char* path);

  // Returns the current working directory. The caller must call
  // free() on the result.
  static char* CurrentNoScope();

  // Returns the current working directory. The returned string is allocated
  // with Dart_ScopeAllocate(). It lasts only as long as the current API scope.
  static const char* Current();
  static const char* SystemTemp();
  static const char* CreateTemp(const char* path);
  // Set the system temporary directory.
  static void SetSystemTemp(const char* path);
  static bool SetCurrent(const char* path);
  static bool Create(const char* path);
  static bool Delete(const char* path, bool recursive);
  static bool Rename(const char* path, const char* new_path);

  static CObject* CreateRequest(const CObjectArray& request);
  static CObject* DeleteRequest(const CObjectArray& request);
  static CObject* ExistsRequest(const CObjectArray& request);
  static CObject* CreateTempRequest(const CObjectArray& request);
  static CObject* CreateSystemTempRequest(const CObjectArray& request);
  static CObject* ListStartRequest(const CObjectArray& request);
  static CObject* ListNextRequest(const CObjectArray& request);
  static CObject* ListStopRequest(const CObjectArray& request);
  static CObject* RenameRequest(const CObjectArray& request);

 private:
  static char* system_temp_path_override_;
  DISALLOW_ALLOCATION();
  DISALLOW_IMPLICIT_CONSTRUCTORS(Directory);
};

}  // namespace bin
}  // namespace dart

#endif  // RUNTIME_BIN_DIRECTORY_H_
