// Copyright (c) 2016, 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.

library sourcemap.html_parts;

import 'sourcemap_html_helper.dart';

class Annotation {
  final id;
  final int codeOffset;
  final String title;
  final data;

  Annotation(this.id, this.codeOffset, this.title, {this.data});
}

typedef bool AnnotationFilter(Annotation annotation);
typedef AnnotationData AnnotationDataFunction(
    Iterable<Annotation> annotations,
    {bool forSpan});
typedef LineData LineDataFunction(lineAnnotation);

bool includeAllAnnotation(Annotation annotation) => true;

class LineData {
  final String lineClass;
  final String lineNumberClass;

  const LineData({
    this.lineClass: 'line',
    this.lineNumberClass: 'lineNumber'});
}

class AnnotationData {
  final String tag;
  final Map<String, String> properties;

  const AnnotationData({
    this.tag: 'a',
    this.properties: const <String, String>{}});

  int get hashCode => tag.hashCode * 13 + properties.hashCode * 19;

  bool operator ==(other) {
    if (identical(this, other)) return true;
    if (other is! AnnotationData) return false;
    return tag == other.tag &&
           properties.length == other.properties.length &&
           properties.keys.every((k) => properties[k] == other.properties[k]);
  }
}

AnnotationDataFunction createAnnotationDataFunction(
    {CssColorScheme colorScheme: const SingleColorScheme(),
     ElementScheme elementScheme: const ElementScheme()}) {
  return (Iterable<Annotation> annotations, {bool forSpan}) {
    return getAnnotationDataFromSchemes(
        annotations,
        forSpan: forSpan,
        colorScheme: colorScheme,
        elementScheme: elementScheme);
  };
}

LineData getDefaultLineData(data) => const LineData();

AnnotationData getAnnotationDataFromSchemes(
    Iterable<Annotation> annotations,
    {bool forSpan,
     CssColorScheme colorScheme: const SingleColorScheme(),
     ElementScheme elementScheme: const ElementScheme()}) {
  if (colorScheme.showLocationAsSpan != forSpan) return null;
  Map<String, String> data = <String, String>{};
  var id;
  if (annotations.length == 1) {
    Annotation annotation = annotations.single;
    if (annotation != null) {
      id = annotation.id;
      data['style'] = colorScheme.singleLocationToCssColor(id);
      data['title'] = annotation.title;
    }
  } else {
    id = annotations.first.id;
    List ids = [];
    for (Annotation annotation in annotations) {
      ids.add(annotation.id);
    }
    data['style'] = colorScheme.multiLocationToCssColor(ids);
    data['title'] = annotations.map((l) => l.title).join(',');
  }
  if (id != null) {
    Set ids = annotations.map((l) => l.id).toSet();
    data['tag'] = 'a';
    data['name'] = elementScheme.getName(id, ids);
    data['href'] = elementScheme.getHref(id, ids);
    data['onclick'] = elementScheme.onClick(id, ids);
    data['onmouseover'] = elementScheme.onMouseOver(id, ids);
    data['onmouseout'] = elementScheme.onMouseOut(id, ids);
    return new AnnotationData(
        properties: data);
  }
  return null;
}

class HtmlPrintContext {
  final int lineNoWidth;
  final bool usePre;
  final AnnotationFilter includeAnnotation;
  final AnnotationDataFunction getAnnotationData;
  final LineDataFunction getLineData;

  HtmlPrintContext({
    this.lineNoWidth,
    this.usePre: true,
    this.includeAnnotation: includeAllAnnotation,
    this.getAnnotationData: getAnnotationDataFromSchemes,
    this.getLineData: getDefaultLineData});

  HtmlPrintContext from({
      int lineNoWidth,
      bool usePre,
      AnnotationFilter includeAnnotation,
      AnnotationDataFunction getAnnotationData,
      LineDataFunction getLineData}) {
    return new HtmlPrintContext(
        lineNoWidth: lineNoWidth ?? this.lineNoWidth,
        usePre: usePre ?? this.usePre,
        includeAnnotation: includeAnnotation ?? this.includeAnnotation,
        getAnnotationData: getAnnotationData ?? this.getAnnotationData,
        getLineData: getLineData ?? this.getLineData);
  }
}

enum HtmlPartKind {
  CODE,
  LINE,
  CONST,
  NEWLINE,
  TEXT,
  TAG,
  LINE_NUMBER,
}

abstract class HtmlPart {
  void printHtmlOn(StringBuffer buffer, HtmlPrintContext context);

  HtmlPartKind get kind;

  toJson(JsonStrategy strategy);

  static HtmlPart fromJson(json, JsonStrategy strategy) {
    if (json is String) {
      return new ConstHtmlPart(json);
    } else {
      switch (HtmlPartKind.values[json['kind']]) {
        case HtmlPartKind.LINE:
          return HtmlLine.fromJson(json, strategy);
        case HtmlPartKind.CODE:
          return CodeLine.fromJson(json, strategy);
        case HtmlPartKind.CONST:
          return ConstHtmlPart.fromJson(json, strategy);
        case HtmlPartKind.NEWLINE:
          return const NewLine();
        case HtmlPartKind.TEXT:
          return HtmlText.fromJson(json, strategy);
        case HtmlPartKind.TAG:
          return TagPart.fromJson(json, strategy);
        case HtmlPartKind.LINE_NUMBER:
          return LineNumber.fromJson(json, strategy);
      }
    }
  }
}

class ConstHtmlPart implements HtmlPart {
  final String html;

  const ConstHtmlPart(this.html);

  HtmlPartKind get kind => HtmlPartKind.CONST;

  @override
  void printHtmlOn(StringBuffer buffer, HtmlPrintContext context) {
    buffer.write(html);
  }

  toJson(JsonStrategy strategy) {
    return {'kind': kind.index, 'html': html};
  }

  static ConstHtmlPart fromJson(Map json, JsonStrategy strategy) {
    return new ConstHtmlPart(json['html']);
  }
}

class NewLine implements HtmlPart {
  const NewLine();

  HtmlPartKind get kind => HtmlPartKind.NEWLINE;

  void printHtmlOn(StringBuffer buffer, HtmlPrintContext context) {
    if (context.usePre) {
      buffer.write('\n');
    } else {
      buffer.write('<br/>');
    }
  }

  toJson(JsonStrategy strategy) {
    return {'kind': kind.index};
  }
}

class HtmlText implements HtmlPart {
  final String text;

  const HtmlText(this.text);

  HtmlPartKind get kind => HtmlPartKind.TEXT;

  void printHtmlOn(StringBuffer buffer, HtmlPrintContext context) {
    String escaped = escape(text);
    buffer.write(escaped);
  }

  toJson(JsonStrategy strategy) {
    return {'kind': kind.index, 'text': text};
  }

  static HtmlText fromJson(Map json, JsonStrategy strategy) {
    return new HtmlText(json['text']);
  }
}

class TagPart implements HtmlPart {
  final String tag;
  final Map<String, String> properties;
  final List<HtmlPart> content;

  TagPart(
    this.tag,
    {this.properties: const <String, String>{},
     this.content: const <HtmlPart>[]});

  HtmlPartKind get kind => HtmlPartKind.TAG;

  @override
  void printHtmlOn(StringBuffer buffer, HtmlPrintContext context) {
    buffer.write('<$tag');
    properties.forEach((String key, String value) {
      if (value != null) {
        buffer.write(' $key="${value}"');
      }
    });
    buffer.write('>');
    for (HtmlPart child in content) {
      child.printHtmlOn(buffer, context);
    }
    buffer.write('</$tag>');
  }

  toJson(JsonStrategy strategy) {
    return {
      'kind': kind.index,
      'tag': tag,
      'properties': properties,
      'content': content.map((p) => p.toJson(strategy)).toList()};
  }

  static TagPart fromJson(Map json, JsonStrategy strategy) {
    return new TagPart(
        json['tag'],
        properties: json['properties'],
        content: json['content'].map(HtmlPart.fromJson).toList());
  }
}

class HtmlLine implements HtmlPart {
  final List<HtmlPart> htmlParts = <HtmlPart>[];

  HtmlPartKind get kind => HtmlPartKind.LINE;

  @override
  void printHtmlOn(StringBuffer htmlBuffer, HtmlPrintContext context) {
    for (HtmlPart part in htmlParts) {
      part.printHtmlOn(htmlBuffer, context);
    }
  }

  Map toJson(JsonStrategy strategy) {
    return {
      'kind': kind.index,
      'html': htmlParts.map((p) => p.toJson(strategy)).toList(),
    };
  }

  static HtmlLine fromJson(Map json, JsonStrategy strategy) {
    HtmlLine line = new HtmlLine();
    json['html']
        .forEach((part) => line.htmlParts
        .add(HtmlPart.fromJson(part, strategy)));
    return line;
  }
}

class CodePart {
  final List<Annotation> annotations;
  final String subsequentCode;

  CodePart(this.annotations, this.subsequentCode);

  void printHtmlOn(StringBuffer buffer, HtmlPrintContext context) {
    Iterable<Annotation> included =
        annotations.where(context.includeAnnotation);

    List<HtmlPart> htmlParts = <HtmlPart>[];
    if (included.isNotEmpty) {
      AnnotationData annotationData =
          context.getAnnotationData(included, forSpan: false);
      AnnotationData annotationDataForSpan =
          context.getAnnotationData(included, forSpan: true);

      String head = subsequentCode;
      String tail = '';
      if (subsequentCode.length > 1) {
        head = subsequentCode.substring(0, 1);
        tail = subsequentCode.substring(1);
      }

      void addForSpan(AnnotationData data) {
        htmlParts.add(new TagPart(
            data.tag,
            properties: data.properties,
            content: [new HtmlText(subsequentCode)]));
      }

      if (annotationData != null &&
          annotationDataForSpan != null) {
        htmlParts.add(new TagPart(
            annotationDataForSpan.tag,
            properties: annotationDataForSpan.properties,
            content: [
              new TagPart(
                  annotationData.tag,
                  properties: annotationData.properties,
                  content: [new HtmlText(head)]),
              new HtmlText(tail)]));
      } else if (annotationDataForSpan != null) {
        htmlParts.add(new TagPart(
            annotationDataForSpan.tag,
            properties: annotationDataForSpan.properties,
            content: [new HtmlText(subsequentCode)]));
      } else if (annotationData != null) {
        htmlParts.add(new TagPart(
            annotationData.tag,
            properties: annotationData.properties,
            content: [new HtmlText(head)]));
        htmlParts.add(new HtmlText(tail));
      } else {
        htmlParts.add(new HtmlText(subsequentCode));
      }
    } else {
      htmlParts.add(new HtmlText(subsequentCode));
    }

    for (HtmlPart part in htmlParts) {
      part.printHtmlOn(buffer, context);
    }
  }

  Map toJson(JsonStrategy strategy) {
    return {
      'annotations':
        annotations.map((a) => strategy.encodeAnnotation(a)).toList(),
      'subsequentCode': subsequentCode,
    };
  }

  static CodePart fromJson(Map json, JsonStrategy strategy) {
    return new CodePart(
        json['annotations'].map((j) => strategy.decodeAnnotation(j)).toList(),
        json['subsequentCode']);
  }
}

class LineNumber extends HtmlPart {
  final int lineNo;
  final lineAnnotation;

  LineNumber(this.lineNo, this.lineAnnotation);

  HtmlPartKind get kind => HtmlPartKind.LINE_NUMBER;

  @override
  toJson(JsonStrategy strategy) {
    return {
      'kind': kind.index,
      'lineNo': lineNo,
      'lineAnnotation': strategy.encodeLineAnnotation(lineAnnotation),
    };
  }

  static LineNumber fromJson(Map json, JsonStrategy strategy) {
    return new LineNumber(
        json['lineNo'],
        strategy.decodeLineAnnotation(json['lineAnnotation']));
  }

  @override
  void printHtmlOn(StringBuffer buffer, HtmlPrintContext context) {
    buffer.write(lineNumber(
        lineNo,
        width: context.lineNoWidth,
        useNbsp: !context.usePre,
        className: context.getLineData(lineAnnotation).lineNumberClass));
  }
}

class CodeLine extends HtmlPart {
  final Uri uri;
  final int lineNo;
  final int offset;
  final StringBuffer codeBuffer = new StringBuffer();
  final List<CodePart> codeParts = <CodePart>[];
  final List<Annotation> annotations = <Annotation>[];
  var lineAnnotation;
  String _code;

  CodeLine(this.lineNo, this.offset, {this.uri});

  HtmlPartKind get kind => HtmlPartKind.CODE;

  String get code {
    if (_code == null) {
      _code = codeBuffer.toString();
    }
    return _code;
  }

  @override
  void printHtmlOn(StringBuffer htmlBuffer, HtmlPrintContext context) {
    if (context.usePre) {
      LineData lineData = context.getLineData(lineAnnotation);
      htmlBuffer.write('<p class="${lineData.lineClass}">');
    }
    new LineNumber(lineNo, lineAnnotation).printHtmlOn(htmlBuffer, context);
    for (CodePart part in codeParts) {
      part.printHtmlOn(htmlBuffer, context);
    }
    const NewLine().printHtmlOn(htmlBuffer, context);
    if (context.usePre) {
      htmlBuffer.write('</p>');
    }
  }

  Map toJson(JsonStrategy strategy) {
    return {
      'kind': kind.index,
      'lineNo': lineNo,
      'offset': offset,
      'code': code,
      'parts': codeParts.map((p) => p.toJson(strategy)).toList(),
      'annotations':
        annotations.map((a) => strategy.encodeAnnotation(a)).toList(),
      'lineAnnotation': lineAnnotation != null
          ? strategy.encodeLineAnnotation(lineAnnotation) : null,
    };
  }

  static CodeLine fromJson(Map json, JsonStrategy strategy) {
    CodeLine line = new CodeLine(
        json['lineNo'],
        json['offset'],
        uri: json['uri'] != null ? Uri.parse(json['uri']) : null);
    line.codeBuffer.write(json['code']);
    json['parts']
        .forEach((part) => line.codeParts
        .add(CodePart.fromJson(part, strategy)));
    json['annotations']
        .forEach((a) => line.annotations
        .add(strategy.decodeAnnotation(a)));
    line.lineAnnotation = json['lineAnnotation'] != null
        ? strategy.decodeLineAnnotation(json['lineAnnotation']) : null;
    return line;
  }
}

class JsonStrategy {
  const JsonStrategy();

  Map encodeAnnotation(Annotation annotation) {
    return {
      'id': annotation.id,
      'codeOffset': annotation.codeOffset,
      'title': annotation.title,
      'data': annotation.data,
    };
  }

  Annotation decodeAnnotation(Map json) {
    return new Annotation(
        json['id'],
        json['codeOffset'],
        json['title'],
        data: json['data']);
  }


  encodeLineAnnotation(lineAnnotation) => lineAnnotation;

  decodeLineAnnotation(json) => json;
}
