// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// A data structure for holding a cache of lines, and receiving incremental updates
// based on deltas from xi-core.

import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';

/// One line in the editor view, with cursor and style information.
class Line {
  /// The text of the line
  final TextSpan text;

  /// A list of cursor locations (at utf-16 offset)
  final List<int> cursor;

  /// The style info, in triple format (start, end, styleId), where
  /// start and end are utf-16 offsets. Note that this is similar to
  /// the xi protocol triple format, but with absolute rather than
  /// relative offsets, and utf-16 rather than utf-8.
  final List<int> styles;

  /// Constructor
  Line(this.text, this.cursor, this.styles);

  /// Constructor, from json data (xi-core update protocol format)
  Line.fromJson(Map<String, dynamic> json, TextStyle style)
      : text = new TextSpan(text: json['text'], style: style),
        cursor = _transformCursor(json['text'], json) ?? <int>[],
        styles = _transformStyles(json['text'], json) ?? <int>[];

  /// Update cursor and styles for a line, retaining text, using json
  /// from the xi-core "update" op
  Line updateFromJson(Map<String, dynamic> json) => new Line(
        text,
        _transformCursor(text.text, json) ?? cursor,
        _transformStyles(text.text, json) ?? styles,
      );

  /// Return the utf-16 offset closest to the given horizontal position.
  // TODO: should conversion to utf-8 offset happen here or be caller's
  // responsibility?
  int getIndexForHorizontal(double horizontal) {
    TextPainter textPainter =
        new TextPainter(text: text, textDirection: TextDirection.ltr)..layout();
    Offset offset = new Offset(horizontal, 0.0);
    TextPosition pos = textPainter.getPositionForOffset(offset);
    return pos.offset;
  }

  @override
  String toString() {
    return '"$text" $cursor $styles';
  }
}

/// A cache containing lines of text
class LineCache {
  /// Creates a line cache.
  LineCache(this.style);

  /// The style for rendering the text.
  TextStyle style;

  // TODO: optimization for larger documents (run-lengths of invalid lines)
  // note: line is nullable, indicating an invalid line
  List<Line> _lines = <Line>[];

  /// Apply an update, in the json format of the xi-core update protocol
  void applyUpdate(List<Map<String, dynamic>> ops) {
    List<Line> newLines = <Line>[];
    int oldIx = 0;
    for (Map<String, dynamic> op in ops) {
      int n = op['n'];
      switch (op['op']) {
        case 'ins':
          for (Map<String, dynamic> line in op['lines']) {
            newLines.add(new Line.fromJson(line, style));
          }
          break;
        case 'invalidate':
          for (int i = 0; i < n; i++) {
            newLines.add(null);
          }
          break;
        case 'copy':
          newLines.addAll(_lines.getRange(oldIx, oldIx + n));
          oldIx += n;
          break;
        case 'update':
          for (Map<String, dynamic> line in op['lines']) {
            Line oldLine = _lines[oldIx++];
            if (oldLine == null) {
              newLines.add(null);
            } else {
              newLines.add(oldLine.updateFromJson(line));
            }
          }
          break;
        case 'skip':
          oldIx += n;
          break;
        default:
          print('unknown update op $op');
          break;
      }
    }
    _lines = newLines;
  }

  /// The height, in other words the number of visible lines.
  int get height => _lines.length;

  /// Get a line. Returns null if line is invalid.
  Line getLine(int ix) {
    return ix < height ? _lines[ix] : null;
  }
}

/// Convert a UTF-8 offset within a string to the corresponding UTF-16 offset
int _utf8ToUtf16Offset(String s, int utf8Offset) {
  int result = 0;
  int utf8Ix = 0;
  while (utf8Ix < utf8Offset) {
    int codeUnit = s.codeUnitAt(result);
    if (codeUnit < 0x80) {
      utf8Ix += 1;
    } else if (codeUnit < 0x800) {
      utf8Ix += 2;
    } else if (codeUnit >= 0xDC00 && codeUnit < 0xE000) {
      // We count the leading surrogate as 3, trailing as 1, total 4
      utf8Ix += 1;
    } else {
      utf8Ix += 3;
    }
    result++;
  }
  return result;
}

// Transform a list of utf-8 offsets to utf-16 offsets
List<int> _transformCursor(String s, Map<String, dynamic> json) {
  List<dynamic> cursorList = json['cursor'];
  List<int> cursor = cursorList?.cast();
  return cursor
      ?.map((int offset) => _utf8ToUtf16Offset(s, offset))
      ?.toList();
}

// Convert style triples from utf-8 to utf-16 and relative to absolute offsets.
List<int> _transformStyles(String s, Map<String, dynamic> json) {
  List<dynamic> stylesList = json['styles'];
  List<int> styles = stylesList?.cast();
  if (styles == null) {
    return null;
  }
  List<int> result = <int>[];
  int ix = 0;
  for (int i = 0; i < styles.length; i += 3) {
    int start = ix + styles[i];
    int end = start + styles[i + 1];
    int styleId = styles[i + 2];
    result
      ..add(_utf8ToUtf16Offset(s, start))
      ..add(_utf8ToUtf16Offset(s, end))
      ..add(styleId);
    ix = end;
  }
  return result;
}
