// Copyright (c) 2013, 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;

/// The current system encoding.
///
/// This us used for converting from bytes to/from String when
/// communicating on stdin, stdout and stderr.
///
/// On Windows this will use the currently active code page for the
/// conversion. On all other systems it will always use UTF-8.
const SystemEncoding SYSTEM_ENCODING = const SystemEncoding();

/**
 * The system encoding is the current code page on Windows and UTF-8 on
 * Linux and Mac.
 */
class SystemEncoding extends Encoding {
  const SystemEncoding();

  String get name => 'system';

  List<int> encode(String input) => encoder.convert(input);
  String decode(List<int> encoded) => decoder.convert(encoded);

  Converter<String, List<int>> get encoder {
    if (Platform.operatingSystem == "windows") {
      return const _WindowsCodePageEncoder();
    } else {
      return const Utf8Encoder();
    }
  }

  Converter<List<int>, String> get decoder {
    if (Platform.operatingSystem == "windows") {
      return const _WindowsCodePageDecoder();
    } else {
      return const Utf8Decoder();
    }
  }
}

class _WindowsCodePageEncoder extends Converter<String, List<int>>
    implements ChunkedConverter<String, List<int>, String, List<int>> {
  const _WindowsCodePageEncoder();

  List<int> convert(String input) {
    List<int> encoded = _encodeString(input);
    if (encoded == null) {
      throw new FormatException("Invalid character for encoding");
    }
    return encoded;
  }

  /**
   * Starts a chunked conversion.
   */
  StringConversionSink startChunkedConversion(Sink<List<int>> sink) {
    return new _WindowsCodePageEncoderSink(sink);
  }

  external static List<int> _encodeString(String string);
}

class _WindowsCodePageEncoderSink extends StringConversionSinkBase {
  // TODO(floitsch): provide more efficient conversions when the input is
  // not a String.

  final Sink<List<int>> _sink;

  _WindowsCodePageEncoderSink(this._sink);

  void close() {
    _sink.close();
  }

  void add(String string) {
    List<int> encoded = _WindowsCodePageEncoder._encodeString(string);
    if (encoded == null) {
      throw new FormatException("Invalid character for encoding");
    }
    _sink.add(encoded);
  }

  void addSlice(String source, int start, int end, bool isLast) {
    if (start != 0 || end != source.length) {
      source = source.substring(start, end);
    }
    add(source);
    if (isLast) close();
  }
}

class _WindowsCodePageDecoder extends Converter<List<int>, String>
    implements ChunkedConverter<List<int>, String, List<int>, String> {
  const _WindowsCodePageDecoder();

  String convert(List<int> input) {
    return _decodeBytes(input);
  }

  /**
   * Starts a chunked conversion.
   */
  ByteConversionSink startChunkedConversion(Sink<String> sink) {
    return new _WindowsCodePageDecoderSink(sink);
  }

  external static String _decodeBytes(List<int> bytes);
}

class _WindowsCodePageDecoderSink extends ByteConversionSinkBase {
  // TODO(floitsch): provide more efficient conversions when the input is
  // a slice.

  final Sink<String> _sink;

  _WindowsCodePageDecoderSink(this._sink);

  void close() {
    _sink.close();
  }

  void add(List<int> bytes) {
    _sink.add(_WindowsCodePageDecoder._decodeBytes(bytes));
  }
}
