// 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();
  /**
   * 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 '=' charcacter.
   * 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 _packageRoot();
  external static String _version();

  static String executable = _executable();
  static String packageRoot = _packageRoot();

  // Cache the OS environemnt. This can be an OSError instance if
  // retrieving the environment failed.
  static var _environmentCache;

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

  // This script singleton is written to by the embedder if applicable.
  static void set _nativeScript(String path) {
    if (path.startsWith('http:') ||
        path.startsWith('https:') ||
        path.startsWith('package:') ||
        path.startsWith('dart:') ||
        path.startsWith('file:')) {
      script = Uri.parse(path);
    } else {
      script = Uri.base.resolveUri(new Uri.file(path));
    }
  }

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

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

  static Map<String, String> get environment {
    if (_environmentCache == null) {
      var env = _environment();
      if (env is !OSError) {
        var isWindows = operatingSystem == 'windows';
        var result = isWindows ? new _CaseInsensitiveStringMap() : new Map();
        for (var str in env) {
          // 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 = str.indexOf('=');
          if (equalsIndex > 0) {
            result[str.substring(0, equalsIndex)] =
                str.substring(equalsIndex + 1);
          }
        }
        _environmentCache = new 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> implements Map<String, V> {
  final Map<String, V> _map = new Map<String, V>();

  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;
  String toString() => _map.toString();
}
