// 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 'dart:typed_data';

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()
      : super('Motion Event Tests', const ValueKey<String>('MotionEventsListTile'));

  @override
  Widget build(BuildContext context) {
    return 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 {
  @override
  State createState() => MotionEventsBodyState();
}

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

  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(
                child: const Text('RECORD'),
                onPressed: listenToFlutterViewEvents,
              ),
            ),
            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')) {
      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) {
    Scaffold.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>.sync(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>.sync(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);

  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());
  }
}
