// 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.

/// This is a helper library to make working with io easier.
library;

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

import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:path/path.dart' as p show Context;

const Encoding utf8AllowMalformed = Utf8Codec(allowMalformed: true);

extension PathExtensions on p.Context {
  /// Returns a canonicalized path including the home directory in place of
  /// tilde references.
  String canonicalizeWithTilde(String originalPath) =>
      canonicalize(resolveTildePath(originalPath));

  /// Return a resolved path including the home directory in place of tilde
  /// references.
  String resolveTildePath(String originalPath) {
    if (!originalPath.startsWith('~/')) {
      return originalPath;
    }

    String homeDir;

    if (io.Platform.isWindows) {
      homeDir = absolute(io.Platform.environment['USERPROFILE'] ?? '\'');
    } else {
      homeDir = absolute(io.Platform.environment['HOME'] ?? '/');
    }

    return join(homeDir, originalPath.substring(2));
  }
}

extension ResourceProviderExtensions on ResourceProvider {
  Folder createSystemTemp(String prefix) {
    if (this is PhysicalResourceProvider) {
      return getFolder(io.Directory.systemTemp.createTempSync(prefix).path);
    } else {
      return getFolder(pathContext.join('${pathContext.separator}tmp', prefix))
        ..create();
    }
  }

  String get resolvedExecutable {
    if (this is PhysicalResourceProvider) {
      return io.Platform.resolvedExecutable;
    } else {
      throw UnimplementedError('resolvedExecutable not implemented');
    }
  }

  bool isExecutable(File file) {
    if (this is PhysicalResourceProvider) {
      var mode = io.File(file.path).statSync().mode;
      return (0x1 & ((mode >> 6) | (mode >> 3) | mode)) != 0;
    } else {
      throw UnimplementedError('isExecutable not implemented');
    }
  }

  bool isNotFound(File file) {
    if (this is PhysicalResourceProvider) {
      return io.File(file.path).statSync().type ==
          io.FileSystemEntityType.notFound;
    } else {
      return !file.exists;
    }
  }

  String readAsMalformedAllowedStringSync(File file) {
    if (this is PhysicalResourceProvider) {
      return io.File(file.path).readAsStringSync(encoding: utf8AllowMalformed);
    } else {
      return file.readAsStringSync();
    }
  }
}

/// Converts `.` and `:` into `-`, adding a ".html" extension.
///
/// For example:
///
/// * dart.dartdoc => dart_dartdoc.html
/// * dart:core => dart_core.html
String getFileNameFor(String name) =>
    '${name.replaceAll(_libraryNameRegExp, '-')}.html';

final _libraryNameRegExp = RegExp('[.:]');

typedef TaskQueueClosure<T> = Future<T> Function();

void _defaultOnComplete() {}

class _TaskQueueItem<T> {
  _TaskQueueItem(this._closure, this._completer,
      {this.onComplete = _defaultOnComplete});

  final TaskQueueClosure<T> _closure;
  final Completer<T> _completer;
  void Function() onComplete;

  Future<void> run() async {
    try {
      _completer.complete(await _closure());
    } catch (e) {
      _completer.completeError(e);
    } finally {
      onComplete.call();
    }
  }
}

/// A task queue of Futures to be completed in parallel, throttling
/// the number of simultaneous tasks.
///
/// The tasks return results of type T.
class TaskQueue<T extends Object> {
  /// Creates a task queue with a maximum number of simultaneous jobs.
  /// The [maxJobs] parameter defaults to the number of CPU cores on the
  /// system.
  TaskQueue({int? maxJobs})
      : maxJobs = maxJobs ?? io.Platform.numberOfProcessors;

  /// The maximum number of jobs that this queue will run simultaneously.
  final int maxJobs;

  final Queue<_TaskQueueItem<T>> _pendingTasks = Queue<_TaskQueueItem<T>>();
  final Set<_TaskQueueItem<T>> _activeTasks = <_TaskQueueItem<T>>{};
  final Set<Completer<void>> _completeListeners = <Completer<void>>{};

  /// Returns a future that completes when all tasks in the [TaskQueue] are
  /// complete.
  Future<void> get tasksComplete {
    // In case this is called when there are no tasks, we want it to
    // signal complete immediately.
    if (_activeTasks.isEmpty && _pendingTasks.isEmpty) {
      return Future<void>.value();
    }
    final completer = Completer<void>();
    _completeListeners.add(completer);
    return completer.future;
  }

  /// Adds a single closure to the task queue, returning a future that
  /// completes when the task completes.
  Future<T> add(TaskQueueClosure<T> task) {
    final completer = Completer<T>();
    _pendingTasks.add(_TaskQueueItem<T>(task, completer));
    if (_activeTasks.length < maxJobs) {
      _processTask();
    }
    return completer.future;
  }

  // Process a single task.
  void _processTask() {
    if (_pendingTasks.isNotEmpty && _activeTasks.length <= maxJobs) {
      final item = _pendingTasks.removeFirst();
      _activeTasks.add(item);
      item.onComplete = () {
        _activeTasks.remove(item);
        _processTask();
      };
      item.run();
    } else {
      _checkForCompletion();
    }
  }

  void _checkForCompletion() {
    if (_activeTasks.isEmpty && _pendingTasks.isEmpty) {
      for (final completer in _completeListeners) {
        if (!completer.isCompleted) {
          completer.complete();
        }
      }
      _completeListeners.clear();
    }
  }
}
