// 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 _localHostname();
  external static _executable();
  external static _environment();
  external static List<String> _executableArguments();
  external static String _packageRoot();
  external static String _version();

  static int get numberOfProcessors => _numberOfProcessors();
  static String get pathSeparator => _pathSeparator();
  static String get operatingSystem => _operatingSystem();
  static Uri script = _script();
  static Uri _script() {
    // The embedder (Dart executable) creates the Platform._nativeScript field.
    var s = Platform._nativeScript;
    if (s.startsWith('http:') ||
        s.startsWith('https:') ||
        s.startsWith('file:')) {
      return Uri.parse(s);
    } else {
      return Uri.base.resolveUri(new Uri.file(s));
    }
  }

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

  static String executable = _executable();
  static String packageRoot = _packageRoot();
  static List<String> get executableArguments => _executableArguments();

  static Map<String, String> get environment {
    var env = _environment();
    if (env is OSError) {
      throw env;
    } else {
      var isWindows = operatingSystem == 'windows';
      var result = isWindows ? new _CaseInsensitiveStringMap() : new Map();
      for (var str in env) {
        // When running on Windows through cmd.exe there are strange
        // environment variables that are used to record the current
        // working directory for each drive and the exit code for the
        // last command. As an example: '=A:=A:\subdir' records the
        // current working directory on the 'A' drive.  In order to
        // handle these correctly we search for a second occurrence of
        // of '=' in the string if the first occurrence is at index 0.
        var equalsIndex = str.indexOf('=');
        if (equalsIndex == 0) {
          equalsIndex = str.indexOf('=', 1);
        }
        assert(equalsIndex != -1);
        result[str.substring(0, equalsIndex)] = str.substring(equalsIndex + 1);
      }
      return result;
    }
  }

  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> implements Map<String, V> {
  _CaseInsensitiveStringMap() : _map = new Map<String, V>();

  _CaseInsensitiveStringMap.from(Map<String, V> other)
      : _map = new Map<String, V>() {
    other.forEach((String key, V value) {
      _map[key.toUpperCase()] = value;
    });
  }

  bool containsKey(String key) => _map.containsKey(key.toUpperCase());
  bool containsValue(Object value) => _map.containsValue(value);
  V operator [](String key) => _map[key.toUpperCase()];
  void operator []=(String key, V value) {
    _map[key.toUpperCase()] = value;
  }
  V putIfAbsent(String key, V ifAbsent()) {
    _map.putIfAbsent(key.toUpperCase(), ifAbsent);
  }
  addAll(Map other) {
    other.forEach((key, value) => this[key.toUpperCase()] = value);
  }
  V remove(String key) => _map.remove(key.toUpperCase());
  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;

  Map<String, V> _map;
}
