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

// TODO(floitsch) - Document - Issue 13097
const HtmlEscape HTML_ESCAPE = const HtmlEscape();

class HtmlEscapeMode {
  final String _name;
  final bool escapeLtGt;
  final bool escapeQuot;
  final bool escapeApos;
  final bool escapeSlash;

  // TODO(floitsch) - Document - Issue 13097
  static const HtmlEscapeMode UNKNOWN =
    const HtmlEscapeMode._('unknown', true, true, true, true);

  // TODO(floitsch) - Document - Issue 13097
  static const HtmlEscapeMode ATTRIBUTE =
    const HtmlEscapeMode._('attribute', false, true, false, false);

  // TODO(floitsch) - Document - Issue 13097
  static const HtmlEscapeMode ELEMENT =
    const HtmlEscapeMode._('element', true, false, false, true);

  // TODO(floitsch) - Document - Issue 13097
  const HtmlEscapeMode._(this._name, this.escapeLtGt, this.escapeQuot,
    this.escapeApos, this.escapeSlash);

  String toString() => _name;
}

  // TODO(floitsch) - Document - Issue 13097
class HtmlEscape extends Converter<String, String> {

  // TODO(floitsch) - Document - Issue 13097
  final HtmlEscapeMode mode;

  // TODO(floitsch) - Document - Issue 13097
  const HtmlEscape([this.mode = HtmlEscapeMode.UNKNOWN]);

  String convert(String text) {
    var val = _convert(text, 0, text.length);
    return val == null ? text : val;
  }

  String _convert(String text, int start, int end) {
    StringBuffer result = null;
    for (int i = start; i < end; i++) {
      var ch = text[i];
      String replace = null;
      switch (ch) {
        case '&': replace = '&amp;'; break;
        case '\u00A0'/*NO-BREAK SPACE*/: replace = '&nbsp;'; break;
        case '"': if (mode.escapeQuot) replace = '&quot;'; break;
        case "'": if (mode.escapeApos) replace = '&#x27;'; break;
        case '<': if (mode.escapeLtGt) replace = '&lt;'; break;
        case '>': if (mode.escapeLtGt) replace = '&gt;'; break;
        case '/': if (mode.escapeSlash) replace = '&#x2F;'; break;
      }
      if (replace != null) {
        if (result == null) result = new StringBuffer(text.substring(start, i));
        result.write(replace);
      } else if (result != null) {
        result.write(ch);
      }
    }

    return result != null ? result.toString() : null;
  }

  StringConversionSink startChunkedConversion(
    ChunkedConversionSink<String> sink) {

    if (sink is! StringConversionSink) {
      sink = new StringConversionSink.from(sink);
    }
    return new _HtmlEscapeSink(this, sink);
  }
}

class _HtmlEscapeSink extends StringConversionSinkBase {
  final HtmlEscape _escape;
  final StringConversionSink _sink;

  _HtmlEscapeSink(this._escape, this._sink);

  void addSlice(String chunk, int start, int end, bool isLast) {
    var val = _escape._convert(chunk, start, end);
    if(val == null) {
      _sink.addSlice(chunk, start, end, isLast);
    } else {
      _sink.add(val);
      if (isLast) _sink.close();
    }
  }

  void close() => _sink.close();
}
