// 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 "dart:async";
import "dart:io";

import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";
import "package:path/path.dart";

// Test the dart:io Link class.

class FutureExpect {
  static Future isTrue(Future<bool> result) =>
      result.then((value) => Expect.isTrue(value));
  static Future isFalse(Future<bool> result) =>
      result.then((value) => Expect.isFalse(value));
  static Future equals(expected, Future result) =>
      result.then((value) => Expect.equals(expected, value));
  static Future listEquals(expected, Future result) =>
      result.then((value) => Expect.listEquals(expected, value));
  static Future throws(Future result) => result.then((value) {
        throw new ExpectException(
            "FutureExpect.throws received $value instead of an exception");
      }, onError: (_) => null);
}

Future testCreate() {
  return Directory.systemTemp.createTemp('dart_link_async').then((baseDir) {
    if (isRelative(baseDir.path)) {
      Expect.fail(
          'Link tests expect absolute paths to system temporary directories. '
          'A relative path in TMPDIR gives relative paths to them.');
    }
    String base = baseDir.path;
    String link = join(base, 'link');
    String target = join(base, 'target');
    return new Directory(target)
        .create()
        .then((_) => new Link(link).create(target))
        .then((_) => FutureExpect.equals(
            FileSystemEntityType.directory, FileSystemEntity.type(link)))
        .then((_) => FutureExpect.equals(
            FileSystemEntityType.directory, FileSystemEntity.type(target)))
        .then((_) => FutureExpect.equals(FileSystemEntityType.link,
            FileSystemEntity.type(link, followLinks: false)))
        .then((_) => FutureExpect.equals(FileSystemEntityType.directory,
            FileSystemEntity.type(target, followLinks: false)))
        .then((_) => FutureExpect.isTrue(FileSystemEntity.isLink(link)))
        .then((_) => FutureExpect.isFalse(FileSystemEntity.isLink(target)))
        .then((_) => FutureExpect.isTrue(new Directory(link).exists()))
        .then((_) => FutureExpect.isTrue(new Directory(target).exists()))
        .then((_) => FutureExpect.isTrue(new Link(link).exists()))
        .then((_) => FutureExpect.isFalse(new Link(target).exists()))
        .then((_) => FutureExpect.equals(target, new Link(link).target()))
        .then((_) => FutureExpect.throws(new Link(target).target()))
        .then((_) {
      String createdThroughLink = join(base, 'link', 'createdThroughLink');
      String createdDirectly = join(base, 'target', 'createdDirectly');
      String createdFile = join(base, 'link', 'createdFile');
      return new Directory(createdThroughLink)
          .create()
          .then((_) => new Directory(createdDirectly).create())
          .then((_) => new File(createdFile).create())
          .then((_) =>
              FutureExpect.isTrue(new Directory(createdThroughLink).exists()))
          .then((_) =>
              FutureExpect.isTrue(new Directory(createdDirectly).exists()))
          .then((_) => FutureExpect.isTrue(
              new Directory(join(base, 'link', 'createdDirectly')).exists()))
          .then((_) => FutureExpect.isTrue(
              new Directory(join(base, 'target', 'createdThroughLink'))
                  .exists()))
          .then((_) => FutureExpect.equals(FileSystemEntityType.directory,
              FileSystemEntity.type(createdThroughLink, followLinks: false)))
          .then((_) => FutureExpect.equals(FileSystemEntityType.directory,
              FileSystemEntity.type(createdDirectly, followLinks: false)))

          // Test FileSystemEntity.identical on files, directories, and links,
          // reached by different paths.
          .then((_) => FutureExpect.isTrue(FileSystemEntity.identical(createdDirectly, createdDirectly)))
          .then((_) => FutureExpect.isFalse(FileSystemEntity.identical(createdDirectly, createdThroughLink)))
          .then((_) => FutureExpect.isTrue(FileSystemEntity.identical(createdDirectly, join(base, 'link', 'createdDirectly'))))
          .then((_) => FutureExpect.isTrue(FileSystemEntity.identical(createdThroughLink, join(base, 'target', 'createdThroughLink'))))
          .then((_) => FutureExpect.isFalse(FileSystemEntity.identical(target, link)))
          .then((_) => FutureExpect.isTrue(FileSystemEntity.identical(link, link)))
          .then((_) => FutureExpect.isTrue(FileSystemEntity.identical(target, target)))
          .then((_) => new Link(link).target())
          .then((linkTarget) => FutureExpect.isTrue(FileSystemEntity.identical(target, linkTarget)))
          .then((_) => new File(".").resolveSymbolicLinks())
          .then((fullCurrentDir) => FutureExpect.isTrue(FileSystemEntity.identical(".", fullCurrentDir)))
          .then((_) => FutureExpect.isTrue(FileSystemEntity.identical(createdFile, createdFile)))
          .then((_) => FutureExpect.isFalse(FileSystemEntity.identical(createdFile, createdDirectly)))
          .then((_) => FutureExpect.isTrue(FileSystemEntity.identical(createdFile, join(base, 'link', 'createdFile'))))
          .then((_) => FutureExpect.throws(FileSystemEntity.identical(createdFile, join(base, 'link', 'does_not_exist'))))
          .then((_) => testDirectoryListing(base, baseDir))
          .then((_) => new Directory(target).delete(recursive: true))
          .then((_) {
        var futures = <Future>[];
        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);
            futures.add(FutureExpect.isTrue(baseDir
                .list(recursive: recursive, followLinks: followLinks)
                .single
                .then((element) => element is Link)));
          }
        }
        return Future.wait(futures);
      }).then((_) => baseDir.delete(recursive: true));
    });
  });
}

Future testCreateLoopingLink(_) {
  return Directory.systemTemp
      .createTemp('dart_link_async')
      .then((dir) => dir.path)
      .then((String base) => 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)
          // This directory listing must terminate, even though it contains loops.
          .then((_) => new Directory(join(base, 'a'))
              .list(recursive: true, followLinks: true)
              .last)
          // This directory listing must terminate, even though it contains loops.
          .then((_) => new Directory(join(base, 'a', 'b', 'c'))
              .list(recursive: true, followLinks: true)
              .last)
          .then((_) => new Directory(base).delete(recursive: true))
          .then((_) => FutureExpect.isFalse(new Directory(base).exists())));
}

Future testRename(_) {
  Future testRename(String base, String target) {
    Link link1;
    Link link2;
    return new Link(join(base, 'c')).create(target).then((link) {
      link1 = link;
      Expect.isTrue(link1.existsSync());
      return link1.rename(join(base, 'd'));
    }).then((link) {
      link2 = link;
      Expect.isFalse(link1.existsSync());
      Expect.isTrue(link2.existsSync());
      return link2.delete();
    }).then((_) => Expect.isFalse(link2.existsSync()));
  }

  Future testUpdate(String base, String target1, String target2) {
    Link link1;
    return new Link(join(base, 'c')).create(target1).then((link) {
      link1 = link;
      Expect.isTrue(link1.existsSync());
      return link1.update(target2);
    }).then((Link link) {
      Expect.isTrue(link1.existsSync());
      Expect.isTrue(link.existsSync());
      return FutureExpect
          .equals(target2, link.target())
          .then((_) => FutureExpect.equals(target2, link1.target()))
          .then((_) => link.delete());
    }).then((_) => Expect.isFalse(link1.existsSync()));
  }

  return Directory.systemTemp.createTemp('dart_link_async').then((baseDir) {
    String base = baseDir.path;
    var targetsFutures = <Future>[];
    targetsFutures.add(new Directory(join(base, 'a')).create());
    if (Platform.isWindows) {
      // Currently only links to directories are supported on Windows.
      targetsFutures.add(new Directory(join(base, 'b')).create());
    } else {
      targetsFutures.add(new File(join(base, 'b')).create());
    }
    return Future.wait(targetsFutures).then((targets) {
      return testRename(base, targets[0].path)
          .then((_) => testRename(base, targets[1].path))
          .then((_) => testUpdate(base, targets[0].path, targets[1].path))
          .then((_) => baseDir.delete(recursive: true));
    });
  });
}

Future testDirectoryListing(String base, Directory baseDir) {
  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';
  }

  var futures = <Future>[];
  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);
      futures.add(baseDir
          .list(recursive: recursive, followLinks: followLinks)
          .forEach((entity) => checkEntity(entity, expected))
          .then((_) {
        for (var v in expected.values) {
          Expect.equals('Found', v);
        }
      }));
    }
  }
  return Future.wait(futures);
}

Future checkExists(String filePath) =>
    new File(filePath).exists().then(Expect.isTrue);

Future testRelativeLinks(_) {
  return Directory.systemTemp
      .createTemp('dart_link_async')
      .then((tempDirectory) {
    String temp = tempDirectory.path;
    String oldWorkingDirectory = Directory.current.path;
    // Make directories and files to test links.
    return new Directory(join(temp, 'dir1', 'dir2'))
        .create(recursive: true)
        .then((_) => new File(join(temp, 'dir1', 'file1')).create())
        .then((_) => new File(join(temp, 'dir1', 'dir2', 'file2')).create())
        // Make links whose path and/or target is given by a relative path.
        .then((_) => new Link(join(temp, 'dir1', 'link1_2')).create('dir2'))
        .then((_) => Directory.current = temp)
        .then((_) => new Link('link0_2').create(join('dir1', 'dir2')))
        .then((_) => new Link(join('dir1', 'link1_0')).create('..'))
        .then((_) => Directory.current = 'dir1')
        .then((_) => new Link(join('..', 'link0_1')).create('dir1'))
        .then(
            (_) => new Link(join('dir2', 'link2_1')).create(join(temp, 'dir1')))
        .then((_) => new Link(join(temp, 'dir1', 'dir2', 'link2_0'))
            .create(join('..', '..')))
        // Test that the links go to the right targets.
        .then((_) => checkExists(join('..', 'link0_1', 'file1')))
        .then((_) => checkExists(join('..', 'link0_2', 'file2')))
        .then((_) => checkExists(join('link1_0', 'dir1', 'file1')))
        .then((_) => checkExists(join('link1_2', 'file2')))
        .then((_) => checkExists(join('dir2', 'link2_0', 'dir1', 'file1')))
        .then((_) => checkExists(join('dir2', 'link2_1', 'file1')))
        // Clean up
        .whenComplete(() => Directory.current = oldWorkingDirectory)
        .whenComplete(() => tempDirectory.delete(recursive: true));
  });
}

main() {
  asyncStart();
  testCreate()
      .then(testCreateLoopingLink)
      .then(testRename)
      .then(testRelativeLinks)
      .then((_) => asyncEnd());
}
