// Copyright 2014 The Flutter Authors. 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:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  test('Element diagnostics json includes widgetRuntimeType', () async {
    final Element element = _TestElement();

    final Map<String, Object> json = element.toDiagnosticsNode().toJsonMap(const DiagnosticsSerializationDelegate());
    expect(json['widgetRuntimeType'], 'Placeholder');
    expect(json['stateful'], isFalse);
  });

  test('StatefulElement diganostics are stateful', () {
    final Element element = StatefulElement(const Tooltip(message: 'foo'));

    final Map<String, Object> json = element.toDiagnosticsNode().toJsonMap(const DiagnosticsSerializationDelegate());
    expect(json['widgetRuntimeType'], 'Tooltip');
    expect(json['stateful'], isTrue);
  });

  group('Serialization', () {
    final TestTree testTree = TestTree(
      properties: <DiagnosticsNode>[
        StringProperty('stringProperty1', 'value1', quoted: false),
        DoubleProperty('doubleProperty1', 42.5),
        DoubleProperty('roundedProperty', 1.0 / 3.0),
        StringProperty('DO_NOT_SHOW', 'DO_NOT_SHOW', level: DiagnosticLevel.hidden, quoted: false),
        DiagnosticsProperty<Object>('DO_NOT_SHOW_NULL', null, defaultValue: null),
        DiagnosticsProperty<Object>('nullProperty', null),
        StringProperty('node_type', '<root node>', showName: false, quoted: false),
      ],
      children: <TestTree>[
        TestTree(name: 'node A'),
        TestTree(
          name: 'node B',
          properties: <DiagnosticsNode>[
            StringProperty('p1', 'v1', quoted: false),
            StringProperty('p2', 'v2', quoted: false),
          ],
          children: <TestTree>[
            TestTree(name: 'node B1'),
            TestTree(
              name: 'node B2',
              properties: <DiagnosticsNode>[StringProperty('property1', 'value1', quoted: false)],
            ),
            TestTree(
              name: 'node B3',
              properties: <DiagnosticsNode>[
                StringProperty('node_type', '<leaf node>', showName: false, quoted: false),
                IntProperty('foo', 42),
              ],
            ),
          ],
        ),
        TestTree(
          name: 'node C',
          properties: <DiagnosticsNode>[
            StringProperty('foo', 'multi\nline\nvalue!', quoted: false),
          ],
        ),
      ],
    );

    test('default', () {
      final Map<String, Object> result = testTree.toDiagnosticsNode().toJsonMap(const DiagnosticsSerializationDelegate());
      expect(result.containsKey('properties'), isFalse);
      expect(result.containsKey('children'), isFalse);
    });

    test('subtreeDepth 1', () {
      final Map<String, Object> result = testTree.toDiagnosticsNode().toJsonMap(const DiagnosticsSerializationDelegate(subtreeDepth: 1));
      expect(result.containsKey('properties'), isFalse);
      final List<Map<String, Object>> children = result['children'] as List<Map<String, Object>>;
      expect(children[0].containsKey('children'), isFalse);
      expect(children[1].containsKey('children'), isFalse);
      expect(children[2].containsKey('children'), isFalse);
    });

    test('subtreeDepth 5', () {
      final Map<String, Object> result = testTree.toDiagnosticsNode().toJsonMap(const DiagnosticsSerializationDelegate(subtreeDepth: 5));
      expect(result.containsKey('properties'), isFalse);
      final List<Map<String, Object>> children = result['children'] as List<Map<String, Object>>;
      expect(children[0]['children'], hasLength(0));
      expect(children[1]['children'], hasLength(3));
      expect(children[2]['children'], hasLength(0));
    });

    test('includeProperties', () {
      final Map<String, Object> result = testTree.toDiagnosticsNode().toJsonMap(const DiagnosticsSerializationDelegate(includeProperties: true));
      expect(result.containsKey('children'), isFalse);
      expect(result['properties'], hasLength(7));
    });

    test('includeProperties with subtreedepth 1', () {
      final Map<String, Object> result = testTree.toDiagnosticsNode().toJsonMap(const DiagnosticsSerializationDelegate(
        includeProperties: true,
        subtreeDepth: 1,
      ));
      expect(result['properties'], hasLength(7));
      final List<Map<String, Object>> children = result['children'] as List<Map<String, Object>>;
      expect(children, hasLength(3));
      expect(children[0]['properties'], hasLength(0));
      expect(children[1]['properties'], hasLength(2));
      expect(children[2]['properties'], hasLength(1));
    });

    test('additionalNodeProperties', () {
      final Map<String, Object> result = testTree.toDiagnosticsNode().toJsonMap(const TestDiagnosticsSerializationDelegate(
        includeProperties: true,
        subtreeDepth: 1,
        additionalNodePropertiesMap: <String, Object>{
          'foo': true,
        },
      ));
      expect(result['foo'], isTrue);
      final List<Map<String, Object>> properties = result['properties'] as List<Map<String, Object>>;
      expect(properties, hasLength(7));
      expect(properties.every((Map<String, Object> property) => property['foo'] == true), isTrue);

      final List<Map<String, Object>> children = result['children'] as List<Map<String, Object>>;
      expect(children, hasLength(3));
      expect(children.every((Map<String, Object> child) => child['foo'] == true), isTrue);
    });

    test('filterProperties - sublist', () {
      final Map<String, Object> result = testTree.toDiagnosticsNode().toJsonMap(TestDiagnosticsSerializationDelegate(
          includeProperties: true,
          propertyFilter: (List<DiagnosticsNode> nodes, DiagnosticsNode owner) {
            return nodes.whereType<StringProperty>().toList();
          },
      ));
      final List<Map<String, Object>> properties = result['properties'] as List<Map<String, Object>>;
      expect(properties, hasLength(3));
      expect(properties.every((Map<String, Object> property) => property['type'] == 'StringProperty'), isTrue);
    });

    test('filterProperties - replace', () {
      bool replaced = false;
      final Map<String, Object> result = testTree.toDiagnosticsNode().toJsonMap(TestDiagnosticsSerializationDelegate(
          includeProperties: true,
          propertyFilter: (List<DiagnosticsNode> nodes, DiagnosticsNode owner) {
            if (replaced) {
              return nodes;
            }
            replaced = true;
            return <DiagnosticsNode>[
              StringProperty('foo', 'bar'),
            ];
          },
      ));
      final List<Map<String, Object>> properties = result['properties'] as List<Map<String, Object>>;
      expect(properties, hasLength(1));
      expect(properties.single['name'], 'foo');
    });

    test('filterChildren - sublist', () {
      final Map<String, Object> result = testTree.toDiagnosticsNode().toJsonMap(TestDiagnosticsSerializationDelegate(
          subtreeDepth: 1,
          childFilter: (List<DiagnosticsNode> nodes, DiagnosticsNode owner) {
            return nodes.where((DiagnosticsNode node) => node.getProperties().isEmpty).toList();
          },
      ));
      final List<Map<String, Object>> children = result['children'] as List<Map<String, Object>>;
      expect(children, hasLength(1));
    });

    test('filterChildren - replace', () {
      final Map<String, Object> result = testTree.toDiagnosticsNode().toJsonMap(TestDiagnosticsSerializationDelegate(
          subtreeDepth: 1,
          childFilter: (List<DiagnosticsNode> nodes, DiagnosticsNode owner) {
            return nodes.expand((DiagnosticsNode node) => node.getChildren()).toList();
          },
      ));
      final List<Map<String, Object>> children = result['children'] as List<Map<String, Object>>;
      expect(children, hasLength(3));
      expect(children.first['name'], 'child node B1');
    });

    test('nodeTruncator', () {
      final Map<String, Object> result = testTree.toDiagnosticsNode().toJsonMap(TestDiagnosticsSerializationDelegate(
          subtreeDepth: 5,
          includeProperties: true,
          nodeTruncator: (List<DiagnosticsNode> nodes, DiagnosticsNode owner) {
            return nodes.take(2).toList();
          },
      ));
      final List<Map<String, Object>> children = result['children'] as List<Map<String, Object>>;
      expect(children, hasLength(3));
      expect(children.last['truncated'], isTrue);

      final List<Map<String, Object>> properties = result['properties'] as List<Map<String, Object>>;
      expect(properties, hasLength(3));
      expect(properties.last['truncated'], isTrue);
    });

    test('delegateForAddingNodes', () {
      final Map<String, Object> result = testTree.toDiagnosticsNode().toJsonMap(TestDiagnosticsSerializationDelegate(
          subtreeDepth: 5,
          includeProperties: true,
          nodeDelegator: (DiagnosticsNode node, DiagnosticsSerializationDelegate delegate) {
            return delegate.copyWith(includeProperties: false);
          },
      ));
      final List<Map<String, Object>> properties = result['properties'] as List<Map<String, Object>>;
      expect(properties, hasLength(7));
      expect(properties.every((Map<String, Object> property) => !property.containsKey('properties')), isTrue);

      final List<Map<String, Object>> children = result['children'] as List<Map<String, Object>>;
      expect(children, hasLength(3));
      expect(children.every((Map<String, Object> child) => !child.containsKey('properties')), isTrue);
    });
  });
}

class _TestElement extends Element {
  _TestElement() : super(const Placeholder());

  @override
  void performRebuild() {
    // Intentionally left empty.
  }

  @override
  bool get debugDoingBuild => throw UnimplementedError();
}

class TestTree extends Object with DiagnosticableTreeMixin {
  TestTree({
    this.name,
    this.style,
    this.children = const <TestTree>[],
    this.properties = const <DiagnosticsNode>[],
  });

  final String name;
  final List<TestTree> children;
  final List<DiagnosticsNode> properties;
  final DiagnosticsTreeStyle style;

  @override
  List<DiagnosticsNode> debugDescribeChildren() => <DiagnosticsNode>[
    for (final TestTree child in children)
      child.toDiagnosticsNode(
        name: 'child ${child.name}',
        style: child.style,
      ),
  ];

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    if (style != null)
      properties.defaultDiagnosticsTreeStyle = style;

    this.properties.forEach(properties.add);
  }
}

class TestDiagnosticsSerializationDelegate implements DiagnosticsSerializationDelegate {
  const TestDiagnosticsSerializationDelegate({
    this.includeProperties = false,
    this.subtreeDepth = 0,
    this.additionalNodePropertiesMap = const <String, Object>{},
    this.childFilter,
    this.propertyFilter,
    this.nodeTruncator,
    this.nodeDelegator,
  });

  final Map<String, Object> additionalNodePropertiesMap;
  final List<DiagnosticsNode> Function(List<DiagnosticsNode> nodes, DiagnosticsNode owner) childFilter;
  final List<DiagnosticsNode> Function(List<DiagnosticsNode> nodes, DiagnosticsNode owner) propertyFilter;
  final List<DiagnosticsNode> Function(List<DiagnosticsNode> nodes, DiagnosticsNode owner) nodeTruncator;
  final DiagnosticsSerializationDelegate Function(DiagnosticsNode node, TestDiagnosticsSerializationDelegate delegate) nodeDelegator;

  @override
  Map<String, Object> additionalNodeProperties(DiagnosticsNode node) {
    return additionalNodePropertiesMap;
  }

  @override
  DiagnosticsSerializationDelegate delegateForNode(DiagnosticsNode node) {
    if (nodeDelegator != null) {
      return nodeDelegator(node, this);
    }
    return subtreeDepth > 0 ? copyWith(subtreeDepth: subtreeDepth - 1) : this;
  }

  @override
  bool get expandPropertyValues => false;

  @override
  List<DiagnosticsNode> filterChildren(List<DiagnosticsNode> nodes, DiagnosticsNode owner) {
    return childFilter != null ? childFilter(nodes, owner) : nodes;
  }

  @override
  List<DiagnosticsNode> filterProperties(List<DiagnosticsNode> nodes, DiagnosticsNode owner) {
    return propertyFilter != null ? propertyFilter(nodes, owner) : nodes;
  }

  @override
  final bool includeProperties;

  @override
  final int subtreeDepth;

  @override
  List<DiagnosticsNode> truncateNodesList(List<DiagnosticsNode> nodes, DiagnosticsNode owner) {
    return nodeTruncator != null ? nodeTruncator(nodes, owner) : nodes;
  }

  @override
  DiagnosticsSerializationDelegate copyWith({int subtreeDepth, bool includeProperties}) {
    return TestDiagnosticsSerializationDelegate(
      includeProperties: includeProperties ?? this.includeProperties,
      subtreeDepth: subtreeDepth ?? this.subtreeDepth,
      additionalNodePropertiesMap: additionalNodePropertiesMap,
      childFilter: childFilter,
      propertyFilter: propertyFilter,
      nodeTruncator: nodeTruncator,
      nodeDelegator: nodeDelegator,
    );
  }
}
