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

import "package:expect/expect.dart";
import 'dart:convert';

var asciiStrings = [
  "pure ascii",
  "\x00 with control characters \n",
  "\x01 edge cases \x7f",
];

var nonAsciiStrings = [
  "\x80 edge case first",
  "Edge case ASCII \u{80}",
  "Edge case byte \u{ff}",
  "Edge case super-BMP \u{10000}",
];

void main() {
  // Build longer versions of the example strings.
  for (int i = 0, n = asciiStrings.length; i < n; i++) {
    var string = asciiStrings[i];
    while (string.length < 1024) {
      string += string;
    }
    asciiStrings.add(string);
  }
  for (int i = 0, n = nonAsciiStrings.length; i < n; i++) {
    var string = nonAsciiStrings[i];
    while (string.length < 1024) {
      string += string;
    }
    nonAsciiStrings.add(string);
  }
  testDirectConversions();
  testChunkedConversions();
}

void testDirectConversions() {
  for (var codec in [ascii, new AsciiCodec()]) {
    for (var asciiString in asciiStrings) {
      List<int> bytes = codec.encoder.convert(asciiString);
      Expect.listEquals(asciiString.codeUnits.toList(), bytes, asciiString);
      String roundTripString = codec.decoder.convert(bytes);
      Expect.equals(asciiString, roundTripString);
      roundTripString = codec.decode(bytes);
      Expect.equals(asciiString, roundTripString);
    }

    for (var nonAsciiString in nonAsciiStrings) {
      Expect.throws(
        () {
          print(codec.encoder.convert(nonAsciiString));
        },
        (_) => true,
        nonAsciiString,
      );
    }

    var encode = codec.encoder.convert;
    Expect.listEquals([0x42, 0x43, 0x44], encode("ABCDE", 1, 4));
    Expect.listEquals([0x42, 0x43, 0x44, 0x45], encode("ABCDE", 1));
    Expect.listEquals([0x42, 0x43, 0x44], encode("\xffBCD\xff", 1, 4));
    Expect.throws(() {
      encode("\xffBCD\xff", 0, 4);
    });
    Expect.throws(() {
      encode("\xffBCD\xff", 1);
    });
    Expect.throws(() {
      encode("\xffBCD\xff", 1, 5);
    });
    Expect.throws(() {
      encode("\xffBCD\xff", -1, 4);
    });
    Expect.throws(() {
      encode("\xffBCD\xff", 1, -1);
    });
    Expect.throws(() {
      encode("\xffBCD\xff", 3, 2);
    });

    var decode = codec.decoder.convert;
    Expect.equals("BCD", decode([0x41, 0x42, 0x43, 0x44, 0x45], 1, 4));
    Expect.equals("BCDE", decode([0x41, 0x42, 0x43, 0x44, 0x45], 1));
    Expect.equals("BCD", decode([0xFF, 0x42, 0x43, 0x44, 0xFF], 1, 4));
    Expect.throws(() {
      decode([0xFF, 0x42, 0x43, 0x44, 0xFF], 0, 4);
    });
    Expect.throws(() {
      decode([0xFF, 0x42, 0x43, 0x44, 0xFF], 1);
    });
    Expect.throws(() {
      decode([0xFF, 0x42, 0x43, 0x44, 0xFF], 1, 5);
    });
    Expect.throws(() {
      decode([0xFF, 0x42, 0x43, 0x44, 0xFF], -1, 4);
    });
    Expect.throws(() {
      decode([0xFF, 0x42, 0x43, 0x44, 0xFF], 1, -1);
    });
    Expect.throws(() {
      decode([0xFF, 0x42, 0x43, 0x44, 0xFF], 3, 2);
    });
  }

  var allowInvalidCodec = new AsciiCodec(allowInvalid: true);
  var invalidBytes = [0, 1, 0xff, 0xdead, 0];
  String decoded = allowInvalidCodec.decode(invalidBytes);
  Expect.equals("\x00\x01\uFFFD\uFFFD\x00", decoded);
  decoded = allowInvalidCodec.decoder.convert(invalidBytes);
  Expect.equals("\x00\x01\uFFFD\uFFFD\x00", decoded);
  decoded = ascii.decode(invalidBytes, allowInvalid: true);
  Expect.equals("\x00\x01\uFFFD\uFFFD\x00", decoded);
}

List<int> encode(
  String str,
  int chunkSize,
  Converter<String, List<int>> converter,
) {
  List<int> bytes = <int>[];
  var byteSink = new ByteConversionSink.withCallback(bytes.addAll);
  var stringConversionSink = converter.startChunkedConversion(byteSink);
  for (int i = 0; i < str.length; i += chunkSize) {
    if (i + chunkSize <= str.length) {
      stringConversionSink.add(str.substring(i, i + chunkSize));
    } else {
      stringConversionSink.add(str.substring(i));
    }
  }
  stringConversionSink.close();
  return bytes;
}

String decode(
  List<int> bytes,
  int chunkSize,
  Converter<List<int>, String> converter,
) {
  StringBuffer buf = new StringBuffer();
  var stringSink = new StringConversionSink.fromStringSink(buf);
  var byteConversionSink = converter.startChunkedConversion(stringSink);
  for (int i = 0; i < bytes.length; i += chunkSize) {
    if (i + chunkSize <= bytes.length) {
      byteConversionSink.add(bytes.sublist(i, i + chunkSize));
    } else {
      byteConversionSink.add(bytes.sublist(i));
    }
  }
  byteConversionSink.close();
  return buf.toString();
}

void testChunkedConversions() {
  // Check encoding.
  for (var converter in [
    ascii.encoder,
    new AsciiCodec().encoder,
    new AsciiEncoder(),
  ]) {
    for (int chunkSize in [1, 2, 5, 50]) {
      for (var asciiString in asciiStrings) {
        var units = asciiString.codeUnits.toList();
        List bytes = encode(asciiString, chunkSize, converter);
        Expect.listEquals(units, bytes);
      }
      for (var nonAsciiString in nonAsciiStrings) {
        Expect.throws(() {
          encode(nonAsciiString, chunkSize, converter);
        });
      }
    }
  }
  // Check decoding.
  for (var converter in [
    ascii.decoder,
    new AsciiCodec().decoder,
    new AsciiDecoder(),
  ]) {
    for (int chunkSize in [1, 2, 5, 50]) {
      for (var asciiString in asciiStrings) {
        var units = asciiString.codeUnits.toList();
        Expect.equals(asciiString, decode(units, chunkSize, converter));
      }
      for (var nonAsciiString in nonAsciiStrings) {
        var units = nonAsciiString.codeUnits.toList();
        Expect.throws(() {
          decode(units, chunkSize, converter);
        });
      }
    }
  }
}
