// Copyright (c) 2020, 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.
//
// This test is Windows-only.

// @dart = 2.9

import 'dart:io';

import "package:expect/expect.dart";

const maxPath = 260;
const maxDirectoryPath = maxPath - 12;
String longName = '${'x' * 248}';

Directory createLongPathDir(Directory tmp) {
  if (tmp.path.length <= maxDirectoryPath) {
    var path = tmp.path;
    path += '\\${'t' * 248}';
    var dir = Directory(path);
    dir.createSync(recursive: true);
    // Test the rename() of directory
    dir = dir.renameSync(tmp.path + '\\$longName');
    Expect.isTrue(dir.existsSync());
    Expect.isFalse(Directory(path).existsSync());
    return dir;
  } else {
    return tmp;
  }
}

void testCreate(String dir) {
  final path = '${dir}\\a_long_path_filename';
  Expect.isTrue(path.length > maxPath);
  final file = File(path);
  file.createSync();
  Expect.isTrue(file.existsSync());
  file.deleteSync();
}

void testCopy(String dir) {
  final src = '${dir}\\a_long_path_filename_1';
  final dest = '${dir}\\a_long_path_filename_2';
  Expect.isTrue(src.length > maxPath);
  final file1 = File(src);
  file1.createSync();

  final file2 = file1.copySync(dest);
  Expect.isTrue(file2.existsSync());
  file1.deleteSync();
  file2.deleteSync();
}

void testRename(String dir) {
  final path = '${dir}\\a_long_path_filename';
  Expect.isTrue(path.length > maxPath);
  final file = File(path);
  file.createSync();
  Expect.isTrue(file.existsSync());

  final renamedFile = file.renameSync('${path}_copy');

  Expect.isFalse(file.existsSync());
  Expect.isTrue(renamedFile.existsSync());
  renamedFile.deleteSync();
}

void testReadWrite(String dir) {
  final path = '${dir}\\a_long_path_filename';
  Expect.isTrue(path.length > maxPath);
  final file = File(path);

  final content = "testReadWrite";
  file.writeAsStringSync(content);
  Expect.isTrue(file.existsSync());

  int length = file.lengthSync();
  Expect.equals(content.length, length);

  final string = file.readAsStringSync();
  Expect.equals(content, string);
  file.deleteSync();
}

void testOpen(String dir) {
  final path = '${dir}\\a_long_path_filename';
  Expect.isTrue(path.length > maxPath);
  final file = File(path);
  file.createSync();
  final access = file.openSync();
  access.closeSync();
}

void testFileStat(String dir) {
  final path = '${dir}\\a_long_path_filename';
  Expect.isTrue(path.length > maxPath);
  final file = File(path);
  file.createSync();
  final stat = FileStat.statSync(file.path);

  final dateTime = DateTime.utc(2020);

  file.setLastModifiedSync(dateTime);
  Expect.notEquals(
      stat.modified.toString(), file.lastModifiedSync().toString());

  file.setLastAccessedSync(dateTime);
  Expect.notEquals(
      stat.accessed.toString(), file.lastAccessedSync().toString());
}

void testCreateLinkToDir(String dir) {
  final path = '${dir}\\a_long_path_linkname';
  Expect.isTrue(path.length > maxPath);
  var target = '$dir\\a_long_path_target';
  final link = Link(path)..createSync(target);

  final dest = Directory(target)..createSync();
  Expect.isTrue(dest.existsSync());

  Expect.isTrue(link.existsSync());
  Expect.isTrue(link.targetSync().contains('a_long_path_target'));

  // Rename link
  var renamedLink = link.renameSync('${dir}\\a_renamed_long_path_link');
  Expect.isTrue(renamedLink.existsSync());
  Expect.isFalse(link.existsSync());
  Expect.isTrue(renamedLink.targetSync().contains('a_long_path_target'));

  // Update link target
  target = '$dir\\an_updated_target';
  final renamedDest = Directory(target)..createSync();
  renamedLink.updateSync(target);
  Expect.isTrue(renamedLink.targetSync().contains('an_updated_target'));

  dest.deleteSync();
  renamedDest.deleteSync();
  renamedLink.deleteSync();
}

void testCreateLinkToFile(String dir) {
  final path = '${dir}\\a_long_path_linkname';
  Expect.isTrue(path.length > maxPath);
  var target = '$dir\\a_long_path_target';
  final link = Link(path)..createSync(target);

  final dest = File(target)..createSync();
  Expect.isTrue(dest.existsSync());

  Expect.isTrue(link.existsSync());
  Expect.isTrue(link.targetSync().contains('a_long_path_target'));
  Expect.isTrue(link.resolveSymbolicLinksSync().contains('a_long_path_target'));

  // Rename link
  var renamedLink = link.renameSync('${dir}\\a_renamed_long_path_link');
  Expect.isTrue(renamedLink.existsSync());
  Expect.isFalse(link.existsSync());
  Expect.isTrue(renamedLink.targetSync().contains('a_long_path_target'));

  // Update link target
  target = '$dir\\an_updated_target';
  final renamedDest = File(target)..createSync();
  renamedLink.updateSync(target);
  Expect.isTrue(renamedLink.targetSync().contains('an_updated_target'));

  dest.deleteSync();
  renamedDest.deleteSync();
  renamedLink.deleteSync();
}

testNormalLinkToLongPath(String short, String long) {
  var target = File('$long\\file_target')..createSync();
  final link = Link('$short\\link')..createSync(target.path);
  Expect.isTrue(target.path.length > maxPath);
  Expect.isTrue(link.resolveSymbolicLinksSync().length > maxPath);
  Expect.isTrue(link.path.length < maxPath);
  Expect.isTrue(link.resolveSymbolicLinksSync().contains('file_target'));

  Expect.isTrue(link.existsSync());
  Expect.equals(target.path, link.targetSync());

  var targetDir = Directory('$long\\dir_target')..createSync();
  link.updateSync(targetDir.path);
  Expect.equals(targetDir.path, link.targetSync());

  link.deleteSync();
  target.deleteSync();
  targetDir.deleteSync();
}

testLongPathLinkToNormal(String short, String long) {
  var target = File('$short\\file_target')..createSync();
  final link = Link('$long\\link')..createSync(target.path);

  Expect.isTrue(target.path.length < maxPath);
  Expect.isTrue(link.path.length > maxPath);
  Expect.isTrue(link.resolveSymbolicLinksSync().contains('file_target'));

  Expect.isTrue(link.existsSync());
  Expect.equals(target.path, link.targetSync());

  var targetDir = Directory('$short\\dir_target')..createSync();
  link.updateSync(targetDir.path);
  Expect.equals(targetDir.path, link.targetSync());

  link.deleteSync();
  target.deleteSync();
  targetDir.deleteSync();
}

testDirectorySetCurrent(String dir) {
  // This tests setting a long path directory to current directory.
  // This will fail.
  Expect.isTrue(dir.length > maxPath);
  Expect.throws<FileSystemException>(() {
    Directory.current = dir;
  }, (e) => e.toString().contains('extension is too long'));
}

void main() {
  if (!Platform.isWindows) {
    return;
  }
  final tmp = Directory.systemTemp.createTempSync('dart-file-long-path');
  final oldCurrent = Directory.current;
  Directory.current = tmp;
  try {
    String dir = createLongPathDir(tmp).path;
    testDirectorySetCurrent(dir);
    for (final path in [dir, ".\\$longName", ".\\$longName\\..\\$longName"]) {
      testCreate(path);
      testCopy(path);
      testRename(path);
      testReadWrite(path);
      testOpen(path);
      testFileStat(path);
      testCreateLinkToDir(path);
      testCreateLinkToFile(path);
    }

    testNormalLinkToLongPath(tmp.path, dir);
    testLongPathLinkToNormal(tmp.path, dir);
  } finally {
    // Reset the current Directory.
    Directory.current = oldCurrent;
    tmp.deleteSync(recursive: true);
  }
}
