// 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 'dart:async';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_driver/driver_extension.dart';
import 'package:path_provider/path_provider.dart';

import 'motion_event_diff.dart';
import 'page.dart';

MethodChannel channel = const MethodChannel('android_views_integration');

const String kEventsFileName = 'touchEvents';

class MotionEventsPage extends PageWidget {
  const MotionEventsPage({Key? key})
      : super('Motion Event Tests', const ValueKey<String>('MotionEventsListTile'), key: key);

  @override
  Widget build(BuildContext context) {
    return const MotionEventsBody();
  }
}

/// Wraps a flutter driver [DataHandler] with one that waits until a delegate is set.
///
/// This allows the driver test to call [FlutterDriver.requestData] before the handler was
/// set by the app in which case the requestData call will only complete once the app is ready
/// for it.
class FutureDataHandler {
  final Completer<DataHandler> handlerCompleter = Completer<DataHandler>();

  Future<String> handleMessage(String? message) async {
    final DataHandler handler = await handlerCompleter.future;
    return handler(message);
  }
}

FutureDataHandler driverDataHandler = FutureDataHandler();

class MotionEventsBody extends StatefulWidget {
  const MotionEventsBody({Key? key}) : super(key: key);

  @override
  State createState() => MotionEventsBodyState();
}

class MotionEventsBodyState extends State<MotionEventsBody> {
  static const int kEventsBufferSize = 1000;

  late MethodChannel viewChannel;

  /// The list of motion events that were passed to the FlutterView.
  List<Map<String, dynamic>> flutterViewEvents = <Map<String, dynamic>>[];

  /// The list of motion events that were passed to the embedded view.
  List<Map<String, dynamic>> embeddedViewEvents = <Map<String, dynamic>>[];

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        SizedBox(
          height: 300.0,
          child: AndroidView(
              key: const ValueKey<String>('PlatformView'),
              viewType: 'simple_view',
              onPlatformViewCreated: onPlatformViewCreated),
        ),
        Expanded(
          child: ListView.builder(
            itemBuilder: buildEventTile,
            itemCount: flutterViewEvents.length,
          ),
        ),
        Row(
          children: <Widget>[
            Expanded(
              child: ElevatedButton(
                onPressed: listenToFlutterViewEvents,
                child: const Text('RECORD'),
              ),
            ),
            Expanded(
              child: ElevatedButton(
                child: const Text('CLEAR'),
                onPressed: () {
                  setState(() {
                    flutterViewEvents.clear();
                    embeddedViewEvents.clear();
                  });
                },
              ),
            ),
            Expanded(
              child: ElevatedButton(
                child: const Text('SAVE'),
                onPressed: () {
                  const StandardMessageCodec codec = StandardMessageCodec();
                  saveRecordedEvents(
                    codec.encodeMessage(flutterViewEvents)!, context);
                },
              ),
            ),
            Expanded(
              child: ElevatedButton(
                key: const ValueKey<String>('play'),
                child: const Text('PLAY FILE'),
                onPressed: () { playEventsFile(); },
              ),
            ),
            Expanded(
              child: ElevatedButton(
                key: const ValueKey<String>('back'),
                child: const Text('BACK'),
                onPressed: () { Navigator.pop(context); },
              ),
            ),
          ],
        ),
      ],
    );
  }

  Future<String> playEventsFile() async {
    const StandardMessageCodec codec = StandardMessageCodec();
    try {
      final ByteData data = await rootBundle.load('packages/assets_for_android_views/assets/touchEvents');
      final List<dynamic> unTypedRecordedEvents = codec.decodeMessage(data) as List<dynamic>;
      final List<Map<String, dynamic>> recordedEvents = unTypedRecordedEvents
          .cast<Map<dynamic, dynamic>>()
          .map<Map<String, dynamic>>((Map<dynamic, dynamic> e) =>e.cast<String, dynamic>())
          .toList();
      await channel.invokeMethod<void>('pipeFlutterViewEvents');
      await viewChannel.invokeMethod<void>('pipeTouchEvents');
      print('replaying ${recordedEvents.length} motion events');
      for (final Map<String, dynamic> event in recordedEvents.reversed) {
        await channel.invokeMethod<void>('synthesizeEvent', event);
      }

      await channel.invokeMethod<void>('stopFlutterViewEvents');
      await viewChannel.invokeMethod<void>('stopTouchEvents');

      if (flutterViewEvents.length != embeddedViewEvents.length)
        return 'Synthesized ${flutterViewEvents.length} events but the embedded view received ${embeddedViewEvents.length} events';

      final StringBuffer diff = StringBuffer();
      for (int i = 0; i < flutterViewEvents.length; ++i) {
        final String currentDiff = diffMotionEvents(flutterViewEvents[i], embeddedViewEvents[i]);
        if (currentDiff.isEmpty)
          continue;
        if (diff.isNotEmpty)
          diff.write(', ');
        diff.write(currentDiff);
      }
      return diff.toString();
    } catch(e) {
      return e.toString();
    }
  }

  @override
  void initState() {
    super.initState();
    channel.setMethodCallHandler(onMethodChannelCall);
  }

  Future<void> saveRecordedEvents(ByteData data, BuildContext context) async {
    if (await channel.invokeMethod<bool>('getStoragePermission') == true) {
      showMessage(
          context, 'External storage permissions are required to save events');
      return;
    }
    try {
      final Directory? outDir = await getExternalStorageDirectory();
      // This test only runs on Android so we can assume path separator is '/'.
      final File file = File('${outDir?.path}/$kEventsFileName');
      await file.writeAsBytes(data.buffer.asUint8List(0, data.lengthInBytes), flush: true);
      showMessage(context, 'Saved original events to ${file.path}');
    } catch (e) {
      showMessage(context, 'Failed saving ${e.toString()}');
    }
  }

  void showMessage(BuildContext context, String message) {
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(
      content: Text(message),
      duration: const Duration(seconds: 3),
    ));
  }

  void onPlatformViewCreated(int id) {
    viewChannel = MethodChannel('simple_view/$id');
    viewChannel.setMethodCallHandler(onViewMethodChannelCall);
    driverDataHandler.handlerCompleter.complete(handleDriverMessage);
  }

  void listenToFlutterViewEvents() {
    channel.invokeMethod<void>('pipeFlutterViewEvents');
    viewChannel.invokeMethod<void>('pipeTouchEvents');
    Timer(const Duration(seconds: 3), () {
      channel.invokeMethod<void>('stopFlutterViewEvents');
      viewChannel.invokeMethod<void>('stopTouchEvents');
    });
  }

  Future<String> handleDriverMessage(String? message) async {
    switch (message) {
      case 'run test':
        return playEventsFile();
    }
    return 'unknown message: "$message"';
  }

  Future<dynamic> onMethodChannelCall(MethodCall call) {
    switch (call.method) {
      case 'onTouch':
        final Map<dynamic, dynamic> map = call.arguments as Map<dynamic, dynamic>;
        flutterViewEvents.insert(0, map.cast<String, dynamic>());
        if (flutterViewEvents.length > kEventsBufferSize)
          flutterViewEvents.removeLast();
        setState(() {});
        break;
    }
    return Future<dynamic>.value(null);
  }

  Future<dynamic> onViewMethodChannelCall(MethodCall call) {
    switch (call.method) {
      case 'onTouch':
        final Map<dynamic, dynamic> map = call.arguments as Map<dynamic, dynamic>;
        embeddedViewEvents.insert(0, map.cast<String, dynamic>());
        if (embeddedViewEvents.length > kEventsBufferSize)
          embeddedViewEvents.removeLast();
        setState(() {});
        break;
    }
    return Future<dynamic>.value(null);
  }

  Widget buildEventTile(BuildContext context, int index) {
    if (embeddedViewEvents.length > index)
      return TouchEventDiff(
          flutterViewEvents[index], embeddedViewEvents[index]);
    return Text(
        'Unmatched event, action: ${flutterViewEvents[index]['action']}');
  }
}

class TouchEventDiff extends StatelessWidget {
  const TouchEventDiff(this.originalEvent, this.synthesizedEvent, {Key? key}) : super(key: key);

  final Map<String, dynamic> originalEvent;
  final Map<String, dynamic> synthesizedEvent;

  @override
  Widget build(BuildContext context) {

    Color color;
    final String diff = diffMotionEvents(originalEvent, synthesizedEvent);
    String msg;
    final int action = synthesizedEvent['action'] as int;
    final String actionName = getActionName(getActionMasked(action), action);
    if (diff.isEmpty) {
      color = Colors.green;
      msg = 'Matched event (action $actionName)';
    } else {
      color = Colors.red;
      msg = '[$actionName] $diff';
    }
    return GestureDetector(
      onLongPress: () {
        print('expected:');
        prettyPrintEvent(originalEvent);
        print('\nactual:');
        prettyPrintEvent(synthesizedEvent);
      },
      child: Container(
        color: color,
        margin: const EdgeInsets.only(bottom: 2.0),
        child: Text(msg),
      ),
    );
  }

  void prettyPrintEvent(Map<String, dynamic> event) {
    final StringBuffer buffer = StringBuffer();
    final int action = event['action'] as int;
    final int maskedAction = getActionMasked(action);
    final String actionName = getActionName(maskedAction, action);

    buffer.write('$actionName ');
    if (maskedAction == 5 || maskedAction == 6) {
     buffer.write('pointer: ${getPointerIdx(action)} ');
    }

    final List<Map<dynamic, dynamic>> coords = (event['pointerCoords'] as List<dynamic>).cast<Map<dynamic, dynamic>>();
    for (int i = 0; i < coords.length; i++) {
      buffer.write('p$i x: ${coords[i]['x']} y: ${coords[i]['y']}, pressure: ${coords[i]['pressure']} ');
    }
    print(buffer.toString());
  }
}
