// 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.

part of dart.io;

class _Directory extends FileSystemEntity implements Directory {
  String _path;
  Uint8List _rawPath;

  _Directory(String path) {
    if (path is! String) {
      throw new ArgumentError('${Error.safeToString(path)} is not a String');
    }
    _path = path;
    _rawPath = FileSystemEntity._toUtf8Array(_path);
  }

  _Directory.fromRawPath(Uint8List rawPath) {
    if (rawPath == null) {
      throw new ArgumentError('rawPath cannot be null');
    }
    _rawPath = FileSystemEntity._toNullTerminatedUtf8Array(rawPath);
    _path = FileSystemEntity._toStringFromUtf8Array(rawPath);
  }

  String get path => _path;

  external static _current(_Namespace namespace);
  external static _setCurrent(_Namespace namespace, Uint8List rawPath);
  external static _createTemp(_Namespace namespace, Uint8List rawPath);
  external static String _systemTemp(_Namespace namespace);
  external static _exists(_Namespace namespace, Uint8List rawPath);
  external static _create(_Namespace namespace, Uint8List rawPath);
  external static _deleteNative(
      _Namespace namespace, Uint8List rawPath, bool recursive);
  external static _rename(
      _Namespace namespace, Uint8List rawPath, String newPath);
  external static void _fillWithDirectoryListing(
      _Namespace namespace,
      List<FileSystemEntity> list,
      Uint8List rawPath,
      bool recursive,
      bool followLinks);

  static Directory get current {
    var result = _current(_Namespace._namespace);
    if (result is OSError) {
      throw new FileSystemException(
          "Getting current working directory failed", "", result);
    }
    return new _Directory(result);
  }

  static void set current(path) {
    Uint8List _rawPath;
    if (path is _Directory) {
      // For our internal Directory implementation, go ahead and use the raw
      // path.
      _rawPath = path._rawPath;
    } else if (path is Directory) {
      // FIXME(bkonyi): package:file passes in instances of classes which do
      // not have _path defined, so we will fallback to using the existing
      // path String for now.
      _rawPath = FileSystemEntity._toUtf8Array(path.path);
    } else if (path is String) {
      _rawPath = FileSystemEntity._toUtf8Array(path);
    } else {
      throw new ArgumentError('${Error.safeToString(path)} is not a String or'
          ' Directory');
    }
    if (!_EmbedderConfig._mayChdir) {
      throw new UnsupportedError(
          "This embedder disallows setting Directory.current");
    }
    var result = _setCurrent(_Namespace._namespace, _rawPath);
    if (result is ArgumentError) throw result;
    if (result is OSError) {
      throw new FileSystemException(
          "Setting current working directory failed", path, result);
    }
  }

  Uri get uri {
    return new Uri.directory(path);
  }

  Future<bool> exists() {
    return _File._dispatchWithNamespace(
        _IOService.directoryExists, [null, _rawPath]).then((response) {
      if (_isErrorResponse(response)) {
        throw _exceptionOrErrorFromResponse(response, "Exists failed");
      }
      return response == 1;
    });
  }

  bool existsSync() {
    var result = _exists(_Namespace._namespace, _rawPath);
    if (result is OSError) {
      throw new FileSystemException("Exists failed", path, result);
    }
    return (result == 1);
  }

  Directory get absolute => new Directory(_absolutePath);

  Future<Directory> create({bool recursive: false}) {
    if (recursive) {
      return exists().then((exists) {
        if (exists) return this;
        if (path != parent.path) {
          return parent.create(recursive: true).then((_) {
            return create();
          });
        } else {
          return create();
        }
      });
    } else {
      return _File._dispatchWithNamespace(
          _IOService.directoryCreate, [null, _rawPath]).then((response) {
        if (_isErrorResponse(response)) {
          throw _exceptionOrErrorFromResponse(response, "Creation failed");
        }
        return this;
      });
    }
  }

  void createSync({bool recursive: false}) {
    if (recursive) {
      if (existsSync()) return;
      if (path != parent.path) {
        parent.createSync(recursive: true);
      }
    }
    var result = _create(_Namespace._namespace, _rawPath);
    if (result is OSError) {
      throw new FileSystemException("Creation failed", path, result);
    }
  }

  static Directory get systemTemp =>
      new Directory(_systemTemp(_Namespace._namespace));

  Future<Directory> createTemp([String prefix]) {
    if (prefix == null) prefix = '';
    if (path == '') {
      throw new ArgumentError("Directory.createTemp called with an empty path. "
          "To use the system temp directory, use Directory.systemTemp");
    }
    String fullPrefix;
    // FIXME(bkonyi): here we're using `path` directly, which might cause
    // issues if it is not UTF-8 encoded.
    if (path.endsWith('/') || (Platform.isWindows && path.endsWith('\\'))) {
      fullPrefix = "$path$prefix";
    } else {
      fullPrefix = "$path${Platform.pathSeparator}$prefix";
    }
    return _File._dispatchWithNamespace(_IOService.directoryCreateTemp,
        [null, FileSystemEntity._toUtf8Array(fullPrefix)]).then((response) {
      if (_isErrorResponse(response)) {
        throw _exceptionOrErrorFromResponse(
            response, "Creation of temporary directory failed");
      }
      return new Directory(response);
    });
  }

  Directory createTempSync([String prefix]) {
    if (prefix == null) prefix = '';
    if (path == '') {
      throw new ArgumentError("Directory.createTemp called with an empty path. "
          "To use the system temp directory, use Directory.systemTemp");
    }
    String fullPrefix;
    // FIXME(bkonyi): here we're using `path` directly, which might cause
    // issues if it is not UTF-8 encoded.
    if (path.endsWith('/') || (Platform.isWindows && path.endsWith('\\'))) {
      fullPrefix = "$path$prefix";
    } else {
      fullPrefix = "$path${Platform.pathSeparator}$prefix";
    }
    var result = _createTemp(
        _Namespace._namespace, FileSystemEntity._toUtf8Array(fullPrefix));
    if (result is OSError) {
      throw new FileSystemException(
          "Creation of temporary directory failed", fullPrefix, result);
    }
    return new Directory(result);
  }

  Future<Directory> _delete({bool recursive: false}) {
    return _File._dispatchWithNamespace(_IOService.directoryDelete,
        [null, _rawPath, recursive]).then((response) {
      if (_isErrorResponse(response)) {
        throw _exceptionOrErrorFromResponse(response, "Deletion failed");
      }
      return this;
    });
  }

  void _deleteSync({bool recursive: false}) {
    var result = _deleteNative(_Namespace._namespace, _rawPath, recursive);
    if (result is OSError) {
      throw new FileSystemException("Deletion failed", path, result);
    }
  }

  Future<Directory> rename(String newPath) {
    return _File._dispatchWithNamespace(
        _IOService.directoryRename, [null, _rawPath, newPath]).then((response) {
      if (_isErrorResponse(response)) {
        throw _exceptionOrErrorFromResponse(response, "Rename failed");
      }
      return new Directory(newPath);
    });
  }

  Directory renameSync(String newPath) {
    if (newPath is! String) {
      throw new ArgumentError();
    }
    var result = _rename(_Namespace._namespace, _rawPath, newPath);
    if (result is OSError) {
      throw new FileSystemException("Rename failed", path, result);
    }
    return new Directory(newPath);
  }

  Stream<FileSystemEntity> list(
      {bool recursive: false, bool followLinks: true}) {
    return new _AsyncDirectoryLister(
            // FIXME(bkonyi): here we're using `path` directly, which might cause issues
            // if it is not UTF-8 encoded.
            FileSystemEntity._toUtf8Array(
                FileSystemEntity._ensureTrailingPathSeparators(path)),
            recursive,
            followLinks)
        .stream;
  }

  List<FileSystemEntity> listSync(
      {bool recursive: false, bool followLinks: true}) {
    if (recursive is! bool || followLinks is! bool) {
      throw new ArgumentError();
    }
    var result = <FileSystemEntity>[];
    _fillWithDirectoryListing(
        _Namespace._namespace,
        result,
        // FIXME(bkonyi): here we're using `path` directly, which might cause issues
        // if it is not UTF-8 encoded.
        FileSystemEntity
            ._toUtf8Array(FileSystemEntity._ensureTrailingPathSeparators(path)),
        recursive,
        followLinks);
    return result;
  }

  String toString() => "Directory: '$path'";

  bool _isErrorResponse(response) =>
      response is List && response[0] != _successResponse;

  _exceptionOrErrorFromResponse(response, String message) {
    assert(_isErrorResponse(response));
    switch (response[_errorResponseErrorType]) {
      case _illegalArgumentResponse:
        return new ArgumentError();
      case _osErrorResponse:
        var err = new OSError(response[_osErrorResponseMessage],
            response[_osErrorResponseErrorCode]);
        return new FileSystemException(message, path, err);
      default:
        return new Exception("Unknown error");
    }
  }
}

abstract class _AsyncDirectoryListerOps {
  external factory _AsyncDirectoryListerOps(int pointer);

  int getPointer();
}

class _AsyncDirectoryLister {
  static const int listFile = 0;
  static const int listDirectory = 1;
  static const int listLink = 2;
  static const int listError = 3;
  static const int listDone = 4;

  static const int responseType = 0;
  static const int responsePath = 1;
  static const int responseComplete = 1;
  static const int responseError = 2;

  final Uint8List rawPath;
  final bool recursive;
  final bool followLinks;

  StreamController<FileSystemEntity> controller;
  bool canceled = false;
  bool nextRunning = false;
  bool closed = false;
  _AsyncDirectoryListerOps _ops;
  Completer closeCompleter = new Completer();

  _AsyncDirectoryLister(this.rawPath, this.recursive, this.followLinks) {
    controller = new StreamController<FileSystemEntity>(
        onListen: onListen, onResume: onResume, onCancel: onCancel, sync: true);
  }

  // WARNING:
  // Calling this function will increase the reference count on the native
  // object that implements the async directory lister operations. It should
  // only be called to pass the pointer to the IO Service, which will decrement
  // the reference count when it is finished with it.
  int _pointer() {
    return (_ops == null) ? null : _ops.getPointer();
  }

  Stream<FileSystemEntity> get stream => controller.stream;

  void onListen() {
    _File._dispatchWithNamespace(_IOService.directoryListStart,
        [null, rawPath, recursive, followLinks]).then((response) {
      if (response is int) {
        _ops = new _AsyncDirectoryListerOps(response);
        next();
      } else if (response is Error) {
        controller.addError(response, response.stackTrace);
        close();
      } else {
        error(response);
        close();
      }
    });
  }

  void onResume() {
    if (!nextRunning) {
      next();
    }
  }

  Future onCancel() {
    canceled = true;
    // If we are active, but not requesting, close.
    if (!nextRunning) {
      close();
    }

    return closeCompleter.future;
  }

  void next() {
    if (canceled) {
      close();
      return;
    }
    if (controller.isPaused || nextRunning) {
      return;
    }
    var pointer = _pointer();
    if (pointer == null) {
      return;
    }
    nextRunning = true;
    _IOService
        ._dispatch(_IOService.directoryListNext, [pointer]).then((result) {
      nextRunning = false;
      if (result is List) {
        next();
        assert(result.length % 2 == 0);
        for (int i = 0; i < result.length; i++) {
          assert(i % 2 == 0);
          switch (result[i++]) {
            case listFile:
              controller.add(new File.fromRawPath(result[i]));
              break;
            case listDirectory:
              controller.add(new Directory.fromRawPath(result[i]));
              break;
            case listLink:
              controller.add(new Link.fromRawPath(result[i]));
              break;
            case listError:
              error(result[i]);
              break;
            case listDone:
              canceled = true;
              return;
          }
        }
      } else {
        controller.addError(new FileSystemException("Internal error"));
      }
    });
  }

  void _cleanup() {
    controller.close();
    closeCompleter.complete();
    _ops = null;
  }

  void close() {
    if (closed) {
      return;
    }
    if (nextRunning) {
      return;
    }
    closed = true;

    var pointer = _pointer();
    if (pointer == null) {
      _cleanup();
    } else {
      _IOService._dispatch(
          _IOService.directoryListStop, [pointer]).whenComplete(_cleanup);
    }
  }

  void error(message) {
    var errorType = message[responseError][_errorResponseErrorType];
    if (errorType == _illegalArgumentResponse) {
      controller.addError(new ArgumentError());
    } else if (errorType == _osErrorResponse) {
      var responseErrorInfo = message[responseError];
      var err = new OSError(responseErrorInfo[_osErrorResponseMessage],
          responseErrorInfo[_osErrorResponseErrorCode]);
      var errorPath = message[responsePath];
      if (errorPath == null) {
        errorPath = utf8.decode(rawPath, allowMalformed: true);
      } else if (errorPath is Uint8List) {
        errorPath = utf8.decode(message[responsePath], allowMalformed: true);
      }
      controller.addError(
          new FileSystemException("Directory listing failed", errorPath, err));
    } else {
      controller.addError(new FileSystemException("Internal error"));
    }
  }
}
