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

import 'package:flutter_driver/driver_extension.dart';

import 'windows.dart';

void drawHelloWorld(ui.FlutterView view) {
  final ui.ParagraphStyle style = ui.ParagraphStyle();
  final ui.ParagraphBuilder paragraphBuilder = ui.ParagraphBuilder(style)
    ..addText('Hello world');
  final ui.Paragraph paragraph = paragraphBuilder.build();

  paragraph.layout(const ui.ParagraphConstraints(width: 100.0));

  final ui.PictureRecorder recorder = ui.PictureRecorder();
  final ui.Canvas canvas = ui.Canvas(recorder);

  canvas.drawParagraph(paragraph, ui.Offset.zero);

  final ui.Picture picture = recorder.endRecording();
  final ui.SceneBuilder sceneBuilder = ui.SceneBuilder()
    ..addPicture(ui.Offset.zero, picture)
    ..pop();

  view.render(sceneBuilder.build());
}

Future<void> _waitUntilWindowVisible() async {
  while (!await isWindowVisible()) {
    await Future<void>.delayed(const Duration(milliseconds: 100));
  }
}

void _expectVisible(bool current, bool expect, Completer<String> completer, int frameCount) {
  if (current != expect) {
    try {
      throw 'Window should be ${expect ? 'visible' : 'hidden'} on frame $frameCount';
    } catch (e) {
      if (!completer.isCompleted) {
        completer.completeError(e);
      }
      rethrow;
    }
  }
}

void main() async {
  // TODO(goderbauer): Create a window if embedder doesn't provide an implicit view to draw into.
  assert(ui.PlatformDispatcher.instance.implicitView != null);
  final ui.FlutterView view = ui.PlatformDispatcher.instance.implicitView!;

  // Create a completer to send the window visibility result back to the
  // integration test.
  final Completer<String> visibilityCompleter = Completer<String>();
  enableFlutterDriverExtension(handler: (String? message) async {
    if (message == 'verifyWindowVisibility') {
      return visibilityCompleter.future;
    } else if (message == 'verifyTheme') {
      final bool app = await isAppDarkModeEnabled();
      final bool system = await isSystemDarkModeEnabled();

      return (app == system)
        ? 'success'
        : 'error: app dark mode ($app) does not match system dark mode ($system)';
    } else if (message == 'verifyStringConversion') {
      // Use a test string that contains code points that fit in both 8 and 16 bits.
      // The code points are passed a list of integers through the method channel,
      // which will use the UTF16 to UTF8 utility function to convert them to a
      // std::string, which should equate to the original expected string.
      const String expected = 'ABCℵ';
      final Int32List codePoints = Int32List.fromList(expected.codeUnits);
      final String converted = await testStringConversion(codePoints);
      return (converted == expected)
        ? 'success'
        : 'error: conversion of UTF16 string to UTF8 failed, expected "${expected.codeUnits}" but got "${converted.codeUnits}"';
    }

    throw 'Unrecognized message: $message';
  });

  try {
    if (await isWindowVisible()) {
      throw 'Window should be hidden at startup';
    }

    int frameCount = 0;
    ui.PlatformDispatcher.instance.onBeginFrame = (Duration duration) {
      // Our goal is to verify that it's `drawHelloWorld` that makes the window
      // appear, not anything else. This requires checking the visibility right
      // before drawing, but since `isWindowVisible` has to be async, and
      // `FlutterView.render` (in `drawHelloWorld`) forbids async before it,
      // this can not be done during a single onBeginFrame. However, we can
      // verify in separate frames to indirectly prove it, by ensuring that
      // no other mechanism can affect isWindowVisible in the first frame at all.
      frameCount += 1;
      switch (frameCount) {
        // The 1st frame: render nothing, just verify that the window is hidden.
        case 1:
          isWindowVisible().then((bool visible) {
            _expectVisible(visible, false, visibilityCompleter, frameCount);
            ui.PlatformDispatcher.instance.scheduleFrame();
          });
        // The 2nd frame: render, which makes the window appear.
        case 2:
          drawHelloWorld(view);
          _waitUntilWindowVisible().then((_) {
            if (!visibilityCompleter.isCompleted) {
              visibilityCompleter.complete('success');
            }
          });
        // Others, in case requested to render.
        default:
          drawHelloWorld(view);
      }
    };
  } catch (e) {
    visibilityCompleter.completeError(e);
    rethrow;
  }
  ui.PlatformDispatcher.instance.scheduleFrame();
}
