// Copyright (c) 2017, 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_NAMESPACE_H_
#define RUNTIME_BIN_NAMESPACE_H_

#include "bin/builtin.h"
#include "bin/dartutils.h"
#include "bin/reference_counting.h"
#include "platform/syslog.h"

namespace dart {
namespace bin {

class NamespaceImpl;

class Namespace : public ReferenceCounted<Namespace> {
 public:
  // Assumes namespc is a value that can be directly used as namespc_.
  static Namespace* Create(intptr_t namespc);

  // Uses path to compute a value that can be used as namespc_.
  static Namespace* Create(const char* path);

  // Gives a safe default value for namespc_ for the standalone Dart VM.
  static intptr_t Default();

  // Tells whether the given namespace is the default namespace.
  static bool IsDefault(Namespace* namespc);

  // Returns the native namespace wrapper if the argument at the supplied index
  // is a _NamespaceImpl object. If it is not, calls Dart_PropagateError().
  static Namespace* GetNamespace(Dart_NativeArguments args, intptr_t index);

  // Get and set the current working directory through the namespace if there
  // is one.
  static const char* GetCurrent(Namespace* namespc);
  static bool SetCurrent(Namespace* namespc, const char* path);

  NamespaceImpl* namespc() const { return namespc_; }

 private:
  // When namespc_ has this value, it indicates that there is currently
  // no namespace for resolving absolute paths.
  static constexpr intptr_t kNone = 0;

  explicit Namespace(NamespaceImpl* namespc)
      : ReferenceCounted(), namespc_(namespc) {}

  ~Namespace();

  // When the native argument at |index| is a _NamespaceImpl object,
  // write the valueof its native field into |namespc|.
  static Dart_Handle GetNativeNamespaceArgument(Dart_NativeArguments args,
                                                intptr_t index,
                                                Namespace** namespc);

  // Given a namespace and a path, computes the information needed to access the
  // path relative to the namespace. This can include massaging the path and
  // returning a platform specific value in dirfd that together are used to
  // access the path.
  static void ResolvePath(Namespace* namespc,
                          const char* path,
                          intptr_t* dirfd,
                          const char** resolved_path);

  NamespaceImpl* namespc_;
  // TODO(zra): When Isolate-specific cwds are added, we'll need some more
  // fields here to track them.

  friend class NamespaceScope;
  friend class ReferenceCounted<Namespace>;
  DISALLOW_COPY_AND_ASSIGN(Namespace);
};

class NamespaceScope {
 public:
  NamespaceScope(Namespace* namespc, const char* path);
  ~NamespaceScope();

  intptr_t fd() const { return fd_; }
  const char* path() const { return path_; }

 private:
  intptr_t fd_;
  const char* path_;

  DISALLOW_ALLOCATION();
  DISALLOW_COPY_AND_ASSIGN(NamespaceScope);
};

}  // namespace bin
}  // namespace dart

#endif  // RUNTIME_BIN_NAMESPACE_H_
