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

part of "dart:io";

class _Platform {
  external static int _numberOfProcessors();
  external static String _pathSeparator();
  external static String _operatingSystem();
  external static _operatingSystemVersion();
  external static _localHostname();
  external static _executable();
  external static _resolvedExecutable();

  /// Retrieve the entries of the process environment.
  ///
  /// The result is an [Iterable] of strings, where each string represents
  /// an environment entry.
  ///
  /// Environment entries should be strings containing
  /// a non-empty name and a value separated by a '=' character.
  /// The name does not contain a '=' character,
  /// so the name is everything up to the first '=' character.
  /// Values are everything after the first '=' character.
  /// A value may contain further '=' characters, and it may be empty.
  ///
  /// Returns an [OSError] if retrieving the environment fails.
  external static _environment();
  external static List<String> _executableArguments();
  external static String? _packageConfig();
  external static String _version();
  external static String _localeName();
  external static Uri _script();

  @pragma("vm:shared")
  static String executable = _executable();
  @pragma("vm:shared")
  static String resolvedExecutable = _resolvedExecutable();
  @pragma("vm:shared")
  static String? packageConfig = _packageConfig();

  @pragma("vm:entry-point")
  static String Function()? _localeClosure;
  static String localeName() {
    final result = (_localeClosure == null) ? _localeName() : _localeClosure!();
    if (result is OSError) {
      throw result;
    }
    return result;
  }

  // Cache the OS environment. This can be an OSError instance if
  // retrieving the environment failed.
  static var /*OSError?|Map<String,String>?*/ _environmentCache;

  static int get numberOfProcessors => _numberOfProcessors();
  static String get pathSeparator => _pathSeparator();
  static String get operatingSystem => _operatingSystem();
  static Uri get script => _script();

  static String? _cachedOSVersion;
  static String get operatingSystemVersion {
    if (_cachedOSVersion == null) {
      var result = _operatingSystemVersion();
      if (result is OSError) {
        throw result;
      }
      _cachedOSVersion = result;
    }
    return _cachedOSVersion!;
  }

  static String get localHostname {
    var result = _localHostname();
    if (result is OSError) {
      throw result;
    }
    return result;
  }

  static List<String> get executableArguments => _executableArguments();

  static Map<String, String> get environment {
    if (_environmentCache == null) {
      var env = _environment();
      if (env is Iterable<Object?>) {
        var result = Platform.isWindows
            ? _CaseInsensitiveStringMap<String>()
            : Map<String, String>();
        for (var environmentEntry in env) {
          if (environmentEntry == null) {
            continue;
          }
          // TODO(kallentu): [_environment()] emits Iterable<dynamic> which is
          // why the cast and check is needed. Every element is a String,
          // however, so refactor [_environment()] at some point to emit
          // Iterable<String>s instead.
          var text = environmentEntry as String;
          // The Strings returned by [_environment()] are expected to be
          // valid environment entries, but exceptions have been seen
          // (e.g., an entry of just '=' has been seen on OS/X).
          // Invalid entries (lines without a '=' or with an empty name)
          // are discarded.
          var equalsIndex = text.indexOf('=');
          if (equalsIndex > 0) {
            result[text.substring(0, equalsIndex)] = text.substring(
              equalsIndex + 1,
            );
          }
        }
        _environmentCache = UnmodifiableMapView<String, String>(result);
      } else {
        _environmentCache = env;
      }
    }

    if (_environmentCache is OSError) {
      throw _environmentCache;
    } else {
      return _environmentCache!;
    }
  }

  static String get version => _version();
}

// Environment variables are case-insensitive on Windows. In order
// to reflect that we use a case-insensitive string map on Windows.
class _CaseInsensitiveStringMap<V> extends MapBase<String, V> {
  final Map<String, V> _map = Map<String, V>();

  bool containsKey(Object? key) =>
      key is String && _map.containsKey(key.toUpperCase());
  bool containsValue(Object? value) => _map.containsValue(value);
  V? operator [](Object? key) => key is String ? _map[key.toUpperCase()] : null;
  void operator []=(String key, V value) {
    _map[key.toUpperCase()] = value;
  }

  V putIfAbsent(String key, V ifAbsent()) {
    return _map.putIfAbsent(key.toUpperCase(), ifAbsent);
  }

  void addAll(Map<String, V> other) {
    other.forEach((key, value) => this[key.toUpperCase()] = value);
  }

  V? remove(Object? key) =>
      key is String ? _map.remove(key.toUpperCase()) : null;

  void clear() {
    _map.clear();
  }

  void forEach(void f(String key, V value)) {
    _map.forEach(f);
  }

  Iterable<String> get keys => _map.keys;
  Iterable<V> get values => _map.values;
  int get length => _map.length;
  bool get isEmpty => _map.isEmpty;
  bool get isNotEmpty => _map.isNotEmpty;

  Iterable<MapEntry<String, V>> get entries => _map.entries;

  Map<K2, V2> map<K2, V2>(MapEntry<K2, V2> transform(String key, V value)) =>
      _map.map(transform);

  V update(String key, V update(V value), {V ifAbsent()?}) =>
      _map.update(key.toUpperCase(), update, ifAbsent: ifAbsent);

  void updateAll(V update(String key, V value)) {
    _map.updateAll(update);
  }

  void removeWhere(bool test(String key, V value)) {
    _map.removeWhere(test);
  }

  String toString() => _map.toString();
}
