// Copyright 2018 The Fuchsia 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:fidl/fidl.dart' hide Service;
import 'package:fidl_fidl_examples_echo/fidl_async.dart';
import 'package:fidl_fuchsia_io/fidl_async.dart' as io_fidl;
import 'package:fuchsia_vfs/vfs.dart';
import 'package:test/test.dart';
import 'package:zircon/zircon.dart';

void main() {
  var unsupportedFlags = [
    io_fidl.openFlagDescribe,
    io_fidl.openRightAdmin,
    io_fidl.openFlagCreate,
    io_fidl.openFlagCreateIfAbsent,
    io_fidl.openFlagDirectory,
    io_fidl.openFlagTruncate,
    io_fidl.openFlagNoRemote,
    io_fidl.openFlagNodeReference,
  ];

  group('service tests:', () {
    test('connect to service fails for bad flags', () async {
      for (var unsupportedFlag in unsupportedFlags) {
        var fs = _FsWithEchoService();
        EchoProxy echoProxy = EchoProxy();
        await fs.dirProxy.open(unsupportedFlag, 0, Echo.$serviceName,
            InterfaceRequest(echoProxy.ctrl.request().passChannel()));

        // as we passed invalid flag, other side will fail to connect and close
        // our request channel, test that.
        echoProxy.ctrl.whenClosed.asStream().listen(expectAsync1((_) {}));
      }
    });

    test('connect to service fails for bad flags and check status', () async {
      for (var unsupportedFlag in unsupportedFlags) {
        _EchoImpl echo = new _EchoImpl();
        Service<Echo> service = Service.withConnector(echo.bind);
        EchoProxy echoProxy = EchoProxy();
        var expectedStatus = ZX.ERR_NOT_SUPPORTED;
        if (unsupportedFlag == io_fidl.openFlagDirectory) {
          expectedStatus = ZX.ERR_NOT_DIR;
        }
        expect(
            service.connect(unsupportedFlag, 0,
                InterfaceRequest(echoProxy.ctrl.request().passChannel())),
            expectedStatus);
      }
    });

    test('connect to service fails for openFlagDescribe', () async {
      var fs = _FsWithEchoService();

      var echoProxy = io_fidl.NodeProxy();
      await fs.dirProxy.open(io_fidl.openFlagDescribe, 0, Echo.$serviceName,
          echoProxy.ctrl.request());
      echoProxy.onOpen.listen(expectAsync1((response) {
        expect(response.s, ZX.ERR_NOT_SUPPORTED);
        expect(response.info, isNull);
      }));
    });

    test('connect to service fails for invalid modes', () async {
      var fs = _FsWithEchoService();
      var invalidModes = [
        io_fidl.modeTypeBlockDevice,
        io_fidl.modeTypeDirectory,
        io_fidl.modeTypeFile,
        io_fidl.modeTypeMask,
        io_fidl.modeTypeSocket
      ];
      for (var mode in invalidModes) {
        var echoProxy = io_fidl.NodeProxy();
        await fs.dirProxy.open(io_fidl.openFlagDescribe, mode,
            Echo.$serviceName, echoProxy.ctrl.request());

        echoProxy.onOpen.listen(expectAsync1((response) {
          expect(response.s, ZX.ERR_INVALID_ARGS);
          expect(response.info, isNull);
        }));
      }
    });

    test('connect to service fails for openFlagDirectory', () async {
      var fs = _FsWithEchoService();
      var nodeProxy = io_fidl.NodeProxy();
      await fs.dirProxy.open(
          io_fidl.openFlagDirectory | io_fidl.openFlagDescribe,
          0,
          Echo.$serviceName,
          nodeProxy.ctrl.request());

      nodeProxy.onOpen.listen(expectAsync1((response) {
        expect(response.s, ZX.ERR_NOT_DIR);
        expect(response.info, isNull);
      }));
    });

    test('connect to service passes with valid flags', () async {
      var supportedFlags = [
        0,
        io_fidl.openRightReadable,
        io_fidl.openRightWritable
      ];
      for (var supportedFlag in supportedFlags) {
        var fs = _FsWithEchoService();
        // connect to service
        var echoProxy = EchoProxy();

        await fs.dirProxy.open(supportedFlag, 0, Echo.$serviceName,
            InterfaceRequest(echoProxy.ctrl.request().passChannel()));
        String str = 'my message';
        var got = await echoProxy.echoString(str);
        expect(got, str);
      }
    });

    test('connect to service passes with valid modes', () async {
      var supportedModes = [
        io_fidl.modeProtectionMask,
        io_fidl.modeTypeService
      ];
      for (var supportedMode in supportedModes) {
        var fs = _FsWithEchoService();
        // connect to service
        var echoProxy = EchoProxy();

        await fs.dirProxy.open(0, supportedMode, Echo.$serviceName,
            InterfaceRequest(echoProxy.ctrl.request().passChannel()));
        String str = 'my message';
        var got = await echoProxy.echoString(str);
        expect(got, str);
      }
    });
  });
}

class _FsWithEchoService {
  final io_fidl.DirectoryProxy dirProxy = io_fidl.DirectoryProxy();
  final PseudoDir _dir = PseudoDir();
  _EchoImpl echo = new _EchoImpl();

  _FsWithEchoService() {
    Service<Echo> service = Service.withConnector(echo.bind);
    var status = _dir.connect(
        0, 0, InterfaceRequest(dirProxy.ctrl.request().passChannel()));
    expect(status, ZX.OK);
    _dir.addNode(Echo.$serviceName, service);
  }
}

class _EchoImpl extends Echo {
  final EchoBinding _binding = new EchoBinding();

  void bind(InterfaceRequest<Echo> request) {
    _binding.bind(this, request);
  }

  @override
  Future<String> echoString(String value) async {
    return value;
  }
}
