// Copyright 2014 The Flutter Authors. 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:archive/archive.dart';
import 'package:file/file.dart';
import 'package:meta/meta.dart';
import 'package:process/process.dart';

import '../globals.dart' as globals;
import 'file_system.dart';
import 'io.dart';
import 'logger.dart';
import 'platform.dart';
import 'process.dart';

abstract class OperatingSystemUtils {
  factory OperatingSystemUtils({
    @required FileSystem fileSystem,
    @required Logger logger,
    @required Platform platform,
    @required ProcessManager processManager,
  }) {
    if (platform.isWindows) {
      return _WindowsUtils(
        fileSystem: fileSystem,
        logger: logger,
        platform: platform,
        processManager: processManager,
      );
    } else {
      return _PosixUtils(
        fileSystem: fileSystem,
        logger: logger,
        platform: platform,
        processManager: processManager,
      );
    }
  }

  OperatingSystemUtils._private({
    @required FileSystem fileSystem,
    @required Logger logger,
    @required Platform platform,
    @required ProcessManager processManager,
  }) : _fileSystem = fileSystem,
       _logger = logger,
       _platform = platform,
       _processManager = processManager,
       _processUtils = ProcessUtils(
        logger: logger,
        processManager: processManager,
      );

  @visibleForTesting
  static final GZipCodec gzipLevel1 = GZipCodec(level: 1);

  final FileSystem _fileSystem;
  final Logger _logger;
  final Platform _platform;
  final ProcessManager _processManager;
  final ProcessUtils _processUtils;

  /// Make the given file executable. This may be a no-op on some platforms.
  void makeExecutable(File file);

  /// Updates the specified file system [entity] to have the file mode
  /// bits set to the value defined by [mode], which can be specified in octal
  /// (e.g. `644`) or symbolically (e.g. `u+x`).
  ///
  /// On operating systems that do not support file mode bits, this will be a
  /// no-op.
  void chmod(FileSystemEntity entity, String mode);

  /// Return the path (with symlinks resolved) to the given executable, or null
  /// if `which` was not able to locate the binary.
  File which(String execName) {
    final List<File> result = _which(execName);
    if (result == null || result.isEmpty) {
      return null;
    }
    return result.first;
  }

  /// Return a list of all paths to `execName` found on the system. Uses the
  /// PATH environment variable.
  List<File> whichAll(String execName) => _which(execName, all: true);

  /// Return the File representing a new pipe.
  File makePipe(String path);

  void zip(Directory data, File zipFile);

  void unzip(File file, Directory targetDirectory);

  /// Returns true if the ZIP is not corrupt.
  bool verifyZip(File file);

  void unpack(File gzippedTarFile, Directory targetDirectory);

  /// Returns true if the gzip is not corrupt (does not check tar).
  bool verifyGzip(File gzippedFile);

  /// Compresses a stream using gzip level 1 (faster but larger).
  Stream<List<int>> gzipLevel1Stream(Stream<List<int>> stream) {
    return stream.cast<List<int>>().transform<List<int>>(gzipLevel1.encoder);
  }

  /// Returns a pretty name string for the current operating system.
  ///
  /// If available, the detailed version of the OS is included.
  String get name {
    const Map<String, String> osNames = <String, String>{
      'macos': 'Mac OS',
      'linux': 'Linux',
      'windows': 'Windows',
    };
    final String osName = _platform.operatingSystem;
    return osNames.containsKey(osName) ? osNames[osName] : osName;
  }

  List<File> _which(String execName, { bool all = false });

  /// Returns the separator between items in the PATH environment variable.
  String get pathVarSeparator;

  /// Returns an unused network port.
  ///
  /// Returns 0 if an unused port cannot be found.
  ///
  /// The port returned by this function may become used before it is bound by
  /// its intended user.
  Future<int> findFreePort({bool ipv6 = false}) async {
    int port = 0;
    ServerSocket serverSocket;
    final InternetAddress loopback =
        ipv6 ? InternetAddress.loopbackIPv6 : InternetAddress.loopbackIPv4;
    try {
      serverSocket = await ServerSocket.bind(loopback, 0);
      port = serverSocket.port;
    } on SocketException catch (e) {
      // If ipv4 loopback bind fails, try ipv6.
      if (!ipv6) {
        return findFreePort(ipv6: true);
      }
      _logger.printTrace('findFreePort failed: $e');
    } on Exception catch (e) {
      // Failures are signaled by a return value of 0 from this function.
      _logger.printTrace('findFreePort failed: $e');
    } finally {
      if (serverSocket != null) {
        await serverSocket.close();
      }
    }
    return port;
  }
}

class _PosixUtils extends OperatingSystemUtils {
  _PosixUtils({
    @required FileSystem fileSystem,
    @required Logger logger,
    @required Platform platform,
    @required ProcessManager processManager,
  }) : super._private(
    fileSystem: fileSystem,
    logger: logger,
    platform: platform,
    processManager: processManager,
  );

  @override
  void makeExecutable(File file) {
    chmod(file, 'a+x');
  }

  @override
  void chmod(FileSystemEntity entity, String mode) {
    try {
      final ProcessResult result = _processManager.runSync(
        <String>['chmod', mode, entity.path],
      );
      if (result.exitCode != 0) {
        _logger.printTrace(
          'Error trying to run chmod on ${entity.absolute.path}'
          '\nstdout: ${result.stdout}'
          '\nstderr: ${result.stderr}',
        );
      }
    } on ProcessException catch (error) {
      _logger.printTrace(
        'Error trying to run chmod on ${entity.absolute.path}: $error',
      );
    }
  }

  @override
  List<File> _which(String execName, { bool all = false }) {
    final List<String> command = <String>[
      'which',
      if (all) '-a',
      execName,
    ];
    final ProcessResult result = _processManager.runSync(command);
    if (result.exitCode != 0) {
      return const <File>[];
    }
    final String stdout = result.stdout as String;
    return stdout.trim().split('\n').map<File>(
      (String path) => _fileSystem.file(path.trim()),
    ).toList();
  }

  @override
  void zip(Directory data, File zipFile) {
    _processUtils.runSync(
      <String>['zip', '-r', '-q', zipFile.path, '.'],
      workingDirectory: data.path,
      throwOnError: true,
    );
  }

  // unzip -o -q zipfile -d dest
  @override
  void unzip(File file, Directory targetDirectory) {
    _processUtils.runSync(
      <String>['unzip', '-o', '-q', file.path, '-d', targetDirectory.path],
      throwOnError: true,
      verboseExceptions: true,
    );
  }

  @override
  bool verifyZip(File zipFile) =>
    _processUtils.exitsHappySync(<String>['unzip', '-t', '-qq', zipFile.path]);

  // tar -xzf tarball -C dest
  @override
  void unpack(File gzippedTarFile, Directory targetDirectory) {
    _processUtils.runSync(
      <String>['tar', '-xzf', gzippedTarFile.path, '-C', targetDirectory.path],
      throwOnError: true,
    );
  }

  @override
  bool verifyGzip(File gzippedFile) =>
    _processUtils.exitsHappySync(<String>['gzip', '-t', gzippedFile.path]);

  @override
  File makePipe(String path) {
    _processUtils.runSync(
      <String>['mkfifo', path],
      throwOnError: true,
    );
    return _fileSystem.file(path);
  }

  String _name;

  @override
  String get name {
    if (_name == null) {
      if (_platform.isMacOS) {
        final List<RunResult> results = <RunResult>[
          _processUtils.runSync(<String>['sw_vers', '-productName']),
          _processUtils.runSync(<String>['sw_vers', '-productVersion']),
          _processUtils.runSync(<String>['sw_vers', '-buildVersion']),
        ];
        if (results.every((RunResult result) => result.exitCode == 0)) {
          _name = '${results[0].stdout.trim()} ${results[1].stdout
              .trim()} ${results[2].stdout.trim()}';
        }
      }
      _name ??= super.name;
    }
    return _name;
  }

  @override
  String get pathVarSeparator => ':';
}

class _WindowsUtils extends OperatingSystemUtils {
  _WindowsUtils({
    @required FileSystem fileSystem,
    @required Logger logger,
    @required Platform platform,
    @required ProcessManager processManager,
  }) : super._private(
    fileSystem: fileSystem,
    logger: logger,
    platform: platform,
    processManager: processManager,
  );

  @override
  void makeExecutable(File file) {}

  @override
  void chmod(FileSystemEntity entity, String mode) {}

  @override
  List<File> _which(String execName, { bool all = false }) {
    // `where` always returns all matches, not just the first one.
    final ProcessResult result = _processManager.runSync(<String>['where', execName]);
    if (result.exitCode != 0) {
      return const <File>[];
    }
    final List<String> lines = (result.stdout as String).trim().split('\n');
    if (all) {
      return lines.map<File>((String path) => _fileSystem.file(path.trim())).toList();
    }
    return <File>[_fileSystem.file(lines.first.trim())];
  }

  @override
  void zip(Directory data, File zipFile) {
    final Archive archive = Archive();
    for (final FileSystemEntity entity in data.listSync(recursive: true)) {
      if (entity is! File) {
        continue;
      }
      final File file = entity as File;
      final String path = file.fileSystem.path.relative(file.path, from: data.path);
      final List<int> bytes = file.readAsBytesSync();
      archive.addFile(ArchiveFile(path, bytes.length, bytes));
    }
    zipFile.writeAsBytesSync(ZipEncoder().encode(archive), flush: true);
  }

  @override
  void unzip(File file, Directory targetDirectory) {
    final Archive archive = ZipDecoder().decodeBytes(file.readAsBytesSync());
    _unpackArchive(archive, targetDirectory);
  }

  @override
  bool verifyZip(File zipFile) {
    try {
      ZipDecoder().decodeBytes(zipFile.readAsBytesSync(), verify: true);
    } on FileSystemException catch (_) {
      return false;
    } on ArchiveException catch (_) {
      return false;
    }
    return true;
  }

  @override
  void unpack(File gzippedTarFile, Directory targetDirectory) {
    final Archive archive = TarDecoder().decodeBytes(
      GZipDecoder().decodeBytes(gzippedTarFile.readAsBytesSync()),
    );
    _unpackArchive(archive, targetDirectory);
  }

  @override
  bool verifyGzip(File gzipFile) {
    try {
      GZipDecoder().decodeBytes(gzipFile.readAsBytesSync(), verify: true);
    } on FileSystemException catch (_) {
      return false;
    } on ArchiveException catch (_) {
      return false;
    } on RangeError catch (_) {
      return false;
    }
    return true;
  }

  void _unpackArchive(Archive archive, Directory targetDirectory) {
    for (final ArchiveFile archiveFile in archive.files) {
      // The archive package doesn't correctly set isFile.
      if (!archiveFile.isFile || archiveFile.name.endsWith('/')) {
        continue;
      }

      final File destFile = _fileSystem.file(_fileSystem.path.join(
        targetDirectory.path,
        archiveFile.name,
      ));
      if (!destFile.parent.existsSync()) {
        destFile.parent.createSync(recursive: true);
      }
      destFile.writeAsBytesSync(archiveFile.content as List<int>);
    }
  }

  @override
  File makePipe(String path) {
    throw UnsupportedError('makePipe is not implemented on Windows.');
  }

  String _name;

  @override
  String get name {
    if (_name == null) {
      final ProcessResult result = _processManager.runSync(
          <String>['ver'], runInShell: true);
      if (result.exitCode == 0) {
        _name = (result.stdout as String).trim();
      } else {
        _name = super.name;
      }
    }
    return _name;
  }

  @override
  String get pathVarSeparator => ';';
}

/// Find and return the project root directory relative to the specified
/// directory or the current working directory if none specified.
/// Return null if the project root could not be found
/// or if the project root is the flutter repository root.
String findProjectRoot([ String directory ]) {
  const String kProjectRootSentinel = 'pubspec.yaml';
  directory ??= globals.fs.currentDirectory.path;
  while (true) {
    if (globals.fs.isFileSync(globals.fs.path.join(directory, kProjectRootSentinel))) {
      return directory;
    }
    final String parent = globals.fs.path.dirname(directory);
    if (directory == parent) {
      return null;
    }
    directory = parent;
  }
}
