// 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 BIN_DIRECTORY_H_
#define 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);
  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:
  DISALLOW_ALLOCATION();
  DISALLOW_IMPLICIT_CONSTRUCTORS(Directory);
};

}  // namespace bin
}  // namespace dart

#endif  // BIN_DIRECTORY_H_
