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

import 'package:fidl/fidl.dart';
import 'package:fidl_fuchsia_io/fidl_async.dart';
import 'package:fuchsia_vfs/vfs.dart';
import 'package:test/test.dart';
import 'package:zircon/zircon.dart';

void main() {
  InterfaceRequest<Node> _getNodeInterfaceRequest(FileProxy proxy) {
    return InterfaceRequest<Node>(proxy.ctrl.request().passChannel());
  }

  _ReadOnlyFile _createVmoFile(String str, openRights,
      [VmoSharingMode mode = VmoSharingMode.shareDuplicate]) {
    final SizedVmo sizedVmo =
        SizedVmo.fromUint8List(Uint8List.fromList(str.codeUnits));

    _ReadOnlyFile file = _ReadOnlyFile()
      ..vmoFile = VmoFile.readOnly(Vmo(sizedVmo.handle), mode)
      ..proxy = FileProxy();
    expect(
        file.vmoFile
            .connect(openRights, 0, _getNodeInterfaceRequest(file.proxy)),
        ZX.OK);
    return file;
  }

  Future<void> _assertRead(FileProxy proxy, int bufSize, String expectedStr,
      {expectedStatus = ZX.OK}) async {
    var readResponse = await proxy.read(bufSize);
    expect(readResponse.s, expectedStatus);
    expect(String.fromCharCodes(readResponse.data), expectedStr);
  }

  Future<void> _assertDescribeFile(FileProxy proxy) async {
    var response = await proxy.describe();
    expect(response.file, isNotNull);
  }

  Future<void> _assertDescribeVmo(FileProxy proxy, String expectedStr) async {
    var response = await proxy.describe();
    expect(response.vmofile, isNotNull);
    expect(response.vmofile.vmo.isValid, isTrue);
    final Uint8List value = response.vmofile.vmo.map();
    expect(String.fromCharCodes(value.sublist(0, expectedStr.length)),
        expectedStr);
  }

  group('vmo file:', () {
    test('onOpen event on success', () async {
      var file =
          _createVmoFile('test_str', openRightReadable | openFlagDescribe);

      await file.proxy.onOpen.first.then((response) {
        expect(response.s, ZX.OK);
        expect(response.info, isNotNull);
      }).catchError((err) async {
        fail(err.toString());
      });
    });

    test('onOpen with describe flag', () async {
      var file =
          _createVmoFile('test_str', openRightReadable | openFlagDescribe);

      await file.proxy.onOpen.first.then((response) {
        expect(response.s, ZX.OK);
        expect(response.info, isNotNull);
        expect(response.info.vmofile, isNotNull);
      }).catchError((err) async {
        fail(err.toString());
      });
    });

    test('read file', () async {
      var str = 'test_str';
      var file = _createVmoFile(str, openRightReadable);
      await _assertRead(file.proxy, str.length, str);
    });

    test('describe duplicate', () async {
      var str = 'test_str';
      var file = _createVmoFile(str, openRightReadable);
      await _assertDescribeVmo(file.proxy, str);
    });

    test('describe no sharing', () async {
      var str = 'test_str';
      var file =
          _createVmoFile(str, openRightReadable, VmoSharingMode.noSharing);
      await _assertDescribeFile(file.proxy);
    });
  });
}

class _ReadOnlyFile {
  VmoFile vmoFile;
  FileProxy proxy;
}
