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

library test.physical_file_system;

import 'dart:async';
import 'dart:io' as io;

import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:path/path.dart';
import 'package:unittest/unittest.dart';
import 'package:watcher/watcher.dart';


var _isFile = new isInstanceOf<File>();
var _isFolder = new isInstanceOf<Folder>();


main() {
  groupSep = ' | ';

  group('PhysicalResourceProvider', () {
      io.Directory tempDirectory;
      String tempPath;

      setUp(() {
        tempDirectory = io.Directory.systemTemp.createTempSync('test_resource');
        tempPath = tempDirectory.absolute.path;
      });

      tearDown(() {
        tempDirectory.deleteSync(recursive: true);
      });

      group('Watch', () {

        Future delayed(computation()) {
          // Give the tests 1 second to detect the changes. While it may only
          // take up to a few hundred ms, a whole second gives a good margin
          // for when running tests.
          return new Future.delayed(
              new Duration(seconds: 1), computation);
        }

        watchingFolder(String path, test(List<WatchEvent> changesReceived)) {
          // Delay before we start watching the folder.  This is necessary
          // because on MacOS, file modifications that occur just before we
          // start watching are sometimes misclassified as happening just after
          // we start watching.
          return delayed(() {
            Folder folder = PhysicalResourceProvider.INSTANCE.getResource(path);
            var changesReceived = <WatchEvent>[];
            var subscription = folder.changes.listen(changesReceived.add);
            // Delay running the rest of the test to allow folder.changes to
            // take a snapshot of the current directory state.  Otherwise it
            // won't be able to reliably distinguish new files from modified
            // ones.
            return delayed(() => test(changesReceived)).whenComplete(() {
              subscription.cancel();
            });
          });
        }

        test('create file', () => watchingFolder(tempPath, (changesReceived) {
          expect(changesReceived, hasLength(0));
          var path = join(tempPath, 'foo');
          new io.File(path).writeAsStringSync('contents');
          return delayed(() {
            expect(changesReceived, hasLength(1));
            expect(changesReceived[0].type, equals(ChangeType.ADD));
            expect(changesReceived[0].path, equals(path));
          });
        }));

        test('modify file', () {
          var path = join(tempPath, 'foo');
          var file = new io.File(path);
          file.writeAsStringSync('contents 1');
          return watchingFolder(tempPath, (changesReceived) {
            expect(changesReceived, hasLength(0));
            file.writeAsStringSync('contents 2');
            return delayed(() {
              expect(changesReceived, hasLength(1));
              expect(changesReceived[0].type, equals(ChangeType.MODIFY));
              expect(changesReceived[0].path, equals(path));
            });
          });
        });

        test('modify file in subdir', () {
          var subdirPath = join(tempPath, 'foo');
          new io.Directory(subdirPath).createSync();
          var path = join(tempPath, 'bar');
          var file = new io.File(path);
          file.writeAsStringSync('contents 1');
          return watchingFolder(tempPath, (changesReceived) {
            expect(changesReceived, hasLength(0));
            file.writeAsStringSync('contents 2');
            return delayed(() {
              expect(changesReceived, hasLength(1));
              expect(changesReceived[0].type, equals(ChangeType.MODIFY));
              expect(changesReceived[0].path, equals(path));
            });
          });
        });

        test('delete file', () {
          var path = join(tempPath, 'foo');
          var file = new io.File(path);
          file.writeAsStringSync('contents 1');
          return watchingFolder(tempPath, (changesReceived) {
            expect(changesReceived, hasLength(0));
            file.deleteSync();
            return delayed(() {
              expect(changesReceived, hasLength(1));
              expect(changesReceived[0].type, equals(ChangeType.REMOVE));
              expect(changesReceived[0].path, equals(path));
            });
          });
        });
      });

      group('File', () {
        String path;
        File file;

        setUp(() {
          path = join(tempPath, 'file.txt');
          file = PhysicalResourceProvider.INSTANCE.getResource(path);
        });

        test('createSource', () {
          new io.File(path).writeAsStringSync('contents');
          Source source = file.createSource();
          expect(source.uriKind, UriKind.FILE_URI);
          expect(source.exists(), isTrue);
          expect(source.contents.data, 'contents');
        });

        group('exists', () {
          test('false', () {
            expect(file.exists, isFalse);
          });

          test('true', () {
            new io.File(path).writeAsStringSync('contents');
            expect(file.exists, isTrue);
          });
        });

        test('fullName', () {
          expect(file.path, path);
        });

        test('hashCode', () {
          new io.File(path).writeAsStringSync('contents');
          File file2 = PhysicalResourceProvider.INSTANCE.getResource(path);
          expect(file.hashCode, equals(file2.hashCode));
        });

        test('equality: same path', () {
          new io.File(path).writeAsStringSync('contents');
          File file2 = PhysicalResourceProvider.INSTANCE.getResource(path);
          expect(file == file2, isTrue);
        });

        test('equality: different paths', () {
          String path2 = join(tempPath, 'file2.txt');
          File file2 = PhysicalResourceProvider.INSTANCE.getResource(path2);
          expect(file == file2, isFalse);
        });

        test('shortName', () {
          expect(file.shortName, 'file.txt');
        });

        test('toString', () {
          expect(file.toString(), path);
        });

        test('parent', () {
          Resource parent = file.parent;
          expect(parent, new isInstanceOf<Folder>());
          expect(parent.path, equals(tempPath));
        });
      });

      group('Folder', () {
        String path;
        Folder folder;

        setUp(() {
          path = join(tempPath, 'folder');
          new io.Directory(path).createSync();
          folder = PhysicalResourceProvider.INSTANCE.getResource(path);
        });

        test('hashCode', () {
          Folder folder2 = PhysicalResourceProvider.INSTANCE.getResource(path);
          expect(folder.hashCode, equals(folder2.hashCode));
        });

        test('equality: same path', () {
          Folder folder2 = PhysicalResourceProvider.INSTANCE.getResource(path);
          expect(folder == folder2, isTrue);
        });

        test('equality: different paths', () {
          String path2 = join(tempPath, 'folder2');
          new io.Directory(path2).createSync();
          Folder folder2 = PhysicalResourceProvider.INSTANCE.getResource(path2);
          expect(folder == folder2, isFalse);
        });

        test('contains', () {
          expect(folder.contains(join(path, 'aaa.txt')), isTrue);
          expect(folder.contains(join(path, 'aaa', 'bbb.txt')), isTrue);
          expect(folder.contains(join(tempPath, 'baz.txt')), isFalse);
          expect(folder.contains(path), isFalse);
        });

        group('getChild', () {
          test('does not exist', () {
            var child = folder.getChild('no-such-resource');
            expect(child, isNotNull);
            expect(child.exists, isFalse);
          });

          test('file', () {
            new io.File(join(path, 'myFile')).createSync();
            var child = folder.getChild('myFile');
            expect(child, _isFile);
            expect(child.exists, isTrue);
          });

          test('folder', () {
            new io.Directory(join(path, 'myFolder')).createSync();
            var child = folder.getChild('myFolder');
            expect(child, _isFolder);
            expect(child.exists, isTrue);
          });
        });

        test('getChildren', () {
          // create 2 files and 1 folder
          new io.File(join(path, 'a.txt')).createSync();
          new io.Directory(join(path, 'bFolder')).createSync();
          new io.File(join(path, 'c.txt')).createSync();
          // prepare 3 children
          List<Resource> children = folder.getChildren();
          expect(children, hasLength(3));
          children.sort((a, b) => a.shortName.compareTo(b.shortName));
          // check that each child exists
          children.forEach((child) {
            expect(child.exists, true);
          });
          // check names
          expect(children[0].shortName, 'a.txt');
          expect(children[1].shortName, 'bFolder');
          expect(children[2].shortName, 'c.txt');
          // check types
          expect(children[0], _isFile);
          expect(children[1], _isFolder);
          expect(children[2], _isFile);
        });

        test('parent', () {
          Resource parent = folder.parent;
          expect(parent, new isInstanceOf<Folder>());
          expect(parent.path, equals(tempPath));

          // Since the OS is in control of where tempPath is, we don't know how
          // far it should be from the root.  So just verify that each call to
          // parent results in a a folder with a shorter path, and that we
          // reach the root eventually.
          while (true) {
            Resource grandParent = parent.parent;
            if (grandParent == null) {
              break;
            }
            expect(grandParent, new isInstanceOf<Folder>());
            expect(grandParent.path.length, lessThan(parent.path.length));
            parent = grandParent;
          }
        });

        test('canonicalizePath', () {
          String path2 = join(tempPath, 'folder2');
          String path3 = join(tempPath, 'folder3');
          expect(folder.canonicalizePath('baz'), equals(join(path, 'baz')));
          expect(folder.canonicalizePath(path2), equals(path2));
          expect(folder.canonicalizePath(join('..', 'folder2')), equals(path2));
          expect(folder.canonicalizePath(join(path2, '..', 'folder3')), equals(path3));
          expect(folder.canonicalizePath(join('.', 'baz')), equals(join(path, 'baz')));
          expect(folder.canonicalizePath(join(path2, '.', 'baz')), equals(join(path2, 'baz')));
        });
      });
    });
}
