// Copyright (c) 2013, 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.

import "package:expect/expect.dart";
import "package:path/path.dart";
import "dart:async";
import "dart:io";
import "dart:isolate";

// Test the dart:io Link class.

testCreateSync() {
  String base = new Directory('').createTempSync().path;
  String link = join(base, 'link');
  String target = join(base, 'target');
  new Directory(target).createSync();
  new Link(link).createSync(target);

  Expect.equals(FileSystemEntityType.DIRECTORY,
                FileSystemEntity.typeSync(link));
  Expect.equals(FileSystemEntityType.DIRECTORY,
                FileSystemEntity.typeSync(target));
  Expect.equals(FileSystemEntityType.LINK,
                FileSystemEntity.typeSync(link, followLinks: false));
  Expect.equals(FileSystemEntityType.DIRECTORY,
                FileSystemEntity.typeSync(target, followLinks: false));
  Expect.isTrue(FileSystemEntity.isLinkSync(link));
  Expect.isFalse(FileSystemEntity.isLinkSync(target));
  Expect.isTrue(new Directory(link).existsSync());
  Expect.isTrue(new Directory(target).existsSync());
  Expect.isTrue(new Link(link).existsSync());
  Expect.isFalse(new Link(target).existsSync());
  Expect.equals(target, new Link(link).targetSync());
  Expect.throws(() => new Link(target).targetSync());

  String createdThroughLink = join(base, 'link', 'createdThroughLink');
  String createdDirectly = join(base, 'target', 'createdDirectly');
  new Directory(createdThroughLink).createSync();
  new Directory(createdDirectly).createSync();
  Expect.isTrue(new Directory(createdThroughLink).existsSync());
  Expect.isTrue(new Directory(createdDirectly).existsSync());
  Expect.isTrue(new Directory(join(base, 'link', 'createdDirectly'))
                .existsSync());
  Expect.isTrue(new Directory(join(base, 'target', 'createdThroughLink'))
                .existsSync());
  Expect.equals(FileSystemEntityType.DIRECTORY,
                FileSystemEntity.typeSync(createdThroughLink,
                                          followLinks: false));
  Expect.equals(FileSystemEntityType.DIRECTORY,
                FileSystemEntity.typeSync(createdDirectly, followLinks: false));

  // Test FileSystemEntity.identical on files, directories, and links,
  // reached by different paths.
  Expect.isTrue(FileSystemEntity.identicalSync(createdDirectly,
                                               createdDirectly));
  Expect.isFalse(FileSystemEntity.identicalSync(createdDirectly,
                                                createdThroughLink));
  Expect.isTrue(FileSystemEntity.identicalSync(createdDirectly,
      join(base, 'link', 'createdDirectly')));
  Expect.isTrue(FileSystemEntity.identicalSync(createdThroughLink,
      join(base, 'target', 'createdThroughLink')));

  Expect.isFalse(FileSystemEntity.identicalSync(target, link));
  Expect.isTrue(FileSystemEntity.identicalSync(link, link));
  Expect.isTrue(FileSystemEntity.identicalSync(target, target));
  Expect.isTrue(FileSystemEntity.identicalSync(target,
                                               new Link(link).targetSync()));
  String absolutePath = new File(".").fullPathSync();
  Expect.isTrue(FileSystemEntity.identicalSync(".", absolutePath));

  String createdFile = join(base, 'target', 'createdFile');
  new File(createdFile).createSync();
  Expect.isTrue(FileSystemEntity.identicalSync(createdFile, createdFile));
  Expect.isFalse(FileSystemEntity.identicalSync(createdFile, createdDirectly));
  Expect.isTrue(FileSystemEntity.identicalSync(createdFile,
      join(base, 'link', 'createdFile')));
  Expect.throws(() => FileSystemEntity.identicalSync(createdFile,
      join(base, 'link', 'does_not_exist')));

  var baseDir = new Directory(base);

  Map makeExpected(bool recursive, bool followLinks) {
    Map expected = new Map();
    expected['target'] = 'Directory';
    expected['link'] = followLinks ? 'Directory' : 'Link';
    if (recursive) {
      expected[join('target', 'createdDirectly')] = 'Directory';
      expected[join('target', 'createdThroughLink')] = 'Directory';
      expected[join('target', 'createdFile')] = 'File';
      if (followLinks) {
        expected[join('link', 'createdDirectly')] = 'Directory';
        expected[join('link', 'createdThroughLink')] = 'Directory';
        expected[join('link', 'createdFile')] = 'File';
      }
    }
    return expected;
  }

  void checkEntity(FileSystemEntity x, Map expected) {
    String ending = relative(x.path, from:base);
    Expect.isNotNull(expected[ending]);
    Expect.isTrue(x.toString().startsWith(expected[ending]));
    expected[ending] = 'Found';
  }

  List futures = [];
  for (bool recursive in [true, false]) {
    for (bool followLinks in [true, false]) {
      Map expected = makeExpected(recursive, followLinks);
      for (var x in baseDir.listSync(recursive: recursive,
                                     followLinks: followLinks)) {
        checkEntity(x, expected);
      }
      for (var v in expected.values) {
        Expect.equals('Found', v);
      }
      expected = makeExpected(recursive, followLinks);
      // We use Stream.reduce to run a function on each entry, and return
      // a future that completes when done.
      var f = new Completer();
      futures.add(f.future);
      baseDir.list(recursive: recursive, followLinks: followLinks).listen(
          (entity) {
            checkEntity(entity, expected);
          },
          onDone: () {
            for (var v in expected.values) {
              Expect.equals('Found', v);
            }
            f.complete(null);
          });
    }
  }
  Future.wait(futures).then((_) {
    new Directory(target).deleteSync(recursive: true);
    for (bool recursive in [true, false]) {
      for (bool followLinks in [true, false]) {
        var result = baseDir.listSync(recursive: recursive,
                                      followLinks: followLinks);
        Expect.equals(1, result.length);
        Expect.isTrue(result[0] is Link);
      }
    }
    baseDir.deleteSync(recursive: true);
  });
}

testCreateLoopingLink() {
  String base = new Directory('').createTempSync().path;
  new Directory(join(base, 'a', 'b', 'c')).create(recursive: true)
    .then((_) =>
        new Link(join(base, 'a', 'b', 'c', 'd')).create(join(base, 'a', 'b')))
    .then((_) =>
        new Link(join(base, 'a', 'b', 'c', 'e')).create(join(base, 'a')))
    .then((_) =>
        new Directory(join(base, 'a'))
        .list(recursive: true, followLinks: false)
        .last)
    .then((_) =>
        // This directory listing must terminate, even though it contains loops.
        new Directory(join(base, 'a'))
        .list(recursive: true, followLinks: true)
        .last)
    .then((_) =>
        // This directory listing must terminate, even though it contains loops.
        new Directory(join(base, 'a', 'b', 'c'))
        .list(recursive: true, followLinks: true)
        .last)
    .then((_) =>
        new Directory(base).delete(recursive: true));
}

testRenameSync() {
  testRename(String base, String target) {
    Link link1 = new Link(join(base, 'c'))..createSync(target);
    Expect.isTrue(link1.existsSync());
    Link link2 = link1.renameSync(join(base, 'd'));
    Expect.isFalse(link1.existsSync());
    Expect.isTrue(link2.existsSync());
    link2.deleteSync();
    Expect.isFalse(link2.existsSync());
  }

  Directory baseDir = new Directory('').createTempSync();
  String base = baseDir.path;
  Directory dir = new Directory(join(base, 'a'))..createSync();
  File file = new File(join(base, 'b'))..createSync();

  testRename(base, file.path);
  testRename(base, dir.path);

  baseDir.deleteSync(recursive: true);
}

void testLinkErrorSync() {
  Expect.throws(() =>
      new Link('some-dir-that-doent exist/some link file/bla/fisk').createSync(
          'bla bla bla/b lalal/blfir/sdfred/es'),
      (e) => e is LinkException);
}

main() {
  testCreateSync();
  testCreateLoopingLink();
  testRenameSync();
  testLinkErrorSync();
}
