// 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 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/convert.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/ios/devices.dart';
import 'package:flutter_tools/src/ios/mac.dart';
import 'package:mockito/mockito.dart';
import 'package:vm_service/vm_service.dart';

import '../../src/common.dart';
import '../../src/context.dart';
import '../../src/testbed.dart';

void main() {
  FakeProcessManager processManager;
  MockArtifacts artifacts;
  FakeCache fakeCache;
  BufferLogger logger;

  setUp(() {
    processManager = FakeProcessManager.list(<FakeCommand>[]);
    fakeCache = FakeCache();
    artifacts = MockArtifacts();
    logger = BufferLogger.test();
    when(artifacts.getArtifactPath(Artifact.idevicesyslog, platform: TargetPlatform.ios))
      .thenReturn('idevice-syslog');
  });

  testWithoutContext('decodeSyslog decodes a syslog-encoded line', () {
    final String decoded = decodeSyslog(
      r'I \M-b\M^]\M-$\M-o\M-8\M^O syslog \M-B\M-/\'
      r'134_(\M-c\M^C\M^D)_/\M-B\M-/ \M-l\M^F\240!');

    expect(decoded, r'I ❤️ syslog ¯\_(ツ)_/¯ 솠!');
  });

  testWithoutContext('decodeSyslog passes through un-decodeable lines as-is', () {
    final String decoded = decodeSyslog(r'I \M-b\M^O syslog!');

    expect(decoded, r'I \M-b\M^O syslog!');
  });

  testWithoutContext('IOSDeviceLogReader suppresses non-Flutter lines from output with syslog', () async {
    processManager.addCommand(
      const FakeCommand(
        command: <String>[
          'idevice-syslog', '-u', '1234',
        ],
        stdout: '''
Runner(Flutter)[297] <Notice>: A is for ari
Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt MobileGestaltSupport.m:153: pid 123 (Runner) does not have sandbox access for frZQaeyWLUvLjeuEK43hmg and IS NOT appropriately entitled
Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt MobileGestalt.c:550: no access to InverseDeviceID (see <rdar://problem/11744455>)
Runner(Flutter)[297] <Notice>: I is for ichigo
Runner(UIKit)[297] <Notice>: E is for enpitsu"
'''
      ),
    );
    final DeviceLogReader logReader = IOSDeviceLogReader.test(
      iMobileDevice: IMobileDevice(
        artifacts: artifacts,
        processManager: processManager,
        cache: fakeCache,
        logger: logger,
      ),
    );
    final List<String> lines = await logReader.logLines.toList();

    expect(lines, <String>['A is for ari', 'I is for ichigo']);
  });

  testWithoutContext('IOSDeviceLogReader includes multi-line Flutter logs in the output with syslog', () async {
    processManager.addCommand(
      const FakeCommand(
        command: <String>[
          'idevice-syslog', '-u', '1234',
        ],
        stdout: '''
Runner(Flutter)[297] <Notice>: This is a multi-line message,
  with another Flutter message following it.
Runner(Flutter)[297] <Notice>: This is a multi-line message,
  with a non-Flutter log message following it.
Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt
'''
      ),
    );
    final DeviceLogReader logReader = IOSDeviceLogReader.test(
      iMobileDevice: IMobileDevice(
        artifacts: artifacts,
        processManager: processManager,
        cache: fakeCache,
        logger: logger,
      ),
    );
    final List<String> lines = await logReader.logLines.toList();

    expect(lines, <String>[
      'This is a multi-line message,',
      '  with another Flutter message following it.',
      'This is a multi-line message,',
      '  with a non-Flutter log message following it.',
    ]);
  });

  testWithoutContext('includes multi-line Flutter logs in the output', () async {
    processManager.addCommand(
      const FakeCommand(
        command: <String>[
          'idevice-syslog', '-u', '1234',
        ],
        stdout: '''
Runner(Flutter)[297] <Notice>: This is a multi-line message,
  with another Flutter message following it.
Runner(Flutter)[297] <Notice>: This is a multi-line message,
  with a non-Flutter log message following it.
Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt
''',
      ),
    );

    final DeviceLogReader logReader = IOSDeviceLogReader.test(
      iMobileDevice: IMobileDevice(
        artifacts: artifacts,
        processManager: processManager,
        cache: fakeCache,
        logger: logger,
      ),
    );
    final List<String> lines = await logReader.logLines.toList();

    expect(lines, <String>[
      'This is a multi-line message,',
      '  with another Flutter message following it.',
      'This is a multi-line message,',
      '  with a non-Flutter log message following it.',
    ]);
  });

  testWithoutContext('IOSDeviceLogReader can listen to VM Service logs', () async {
    final MockVmService vmService = MockVmService();
    final DeviceLogReader logReader = IOSDeviceLogReader.test(
      useSyslog: false,
      iMobileDevice: IMobileDevice(
        artifacts: artifacts,
        processManager: processManager,
        cache: fakeCache,
        logger: logger,
      ),
    );
    final StreamController<Event> stdoutController = StreamController<Event>();
    final StreamController<Event> stderController = StreamController<Event>();
    final Completer<Success> stdoutCompleter = Completer<Success>();
    final Completer<Success> stderrCompleter = Completer<Success>();
    when(vmService.streamListen('Stdout')).thenAnswer((Invocation invocation) {
      return stdoutCompleter.future;
    });
    when(vmService.streamListen('Stderr')).thenAnswer((Invocation invocation) {
      return stderrCompleter.future;
    });
    when(vmService.onStdoutEvent).thenAnswer((Invocation invocation) {
      return stdoutController.stream;
    });
    when(vmService.onStderrEvent).thenAnswer((Invocation invocation) {
      return stderController.stream;
    });
    logReader.connectedVMService = vmService;

    stdoutCompleter.complete(Success());
    stderrCompleter.complete(Success());
    stdoutController.add(Event(
      kind: 'Stdout',
      timestamp: 0,
      bytes: base64.encode(utf8.encode('  This is a message ')),
    ));
    stderController.add(Event(
      kind: 'Stderr',
      timestamp: 0,
      bytes: base64.encode(utf8.encode('  And this is an error ')),
    ));

    // Wait for stream listeners to fire.
    await expectLater(logReader.logLines, emitsInAnyOrder(<Matcher>[
      equals('  This is a message '),
      equals('  And this is an error '),
    ]));
  });
}

class MockArtifacts extends Mock implements Artifacts {}
class MockVmService extends Mock implements VmService {}
