// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library IndexedDB4Test;

import 'package:expect/legacy/async_minitest.dart'; // ignore: deprecated_member_use
import 'dart:async';
import 'dart:html' as html;
import 'dart:indexed_db';

// Test for KeyRange and Cursor.

const String DB_NAME = 'Test4';
const String STORE_NAME = 'TEST';
const int VERSION = 1;

Future<Database> createAndOpenDb() {
  return html.window.indexedDB!.deleteDatabase(DB_NAME).then((_) {
    return html.window.indexedDB!.open(
      DB_NAME,
      version: VERSION,
      onUpgradeNeeded: (e) {
        var db = e.target.result;
        db.createObjectStore(STORE_NAME);
      },
    );
  });
}

Future<Database> writeItems(Database db) {
  Future<Object?> write(index) {
    var transaction = db.transaction(STORE_NAME, 'readwrite');
    return transaction.objectStore(STORE_NAME).put({
          'content': 'Item $index',
        }, index)
        as Future<Object?>;
  }

  var future = write(0);
  for (var i = 1; i < 100; ++i) {
    future = future.then((_) => write(i));
  }

  // Chain on the DB so we return it at the end.
  return future.then((_) => db);
}

Future<Database> setupDb() {
  return createAndOpenDb().then(writeItems);
}

testRange(db, range, expectedFirst, expectedLast) {
  Transaction txn = db.transaction(STORE_NAME, 'readonly');
  ObjectStore objectStore = txn.objectStore(STORE_NAME);
  var cursors = objectStore
      .openCursor(range: range, autoAdvance: true)
      .asBroadcastStream();

  int lastKey = 0;
  cursors.listen((cursor) {
    lastKey = cursor.key as int;
    var value = cursor.value;
    expect(value['content'], 'Item ${cursor.key}');
  });

  if (expectedFirst != null) {
    cursors.first.then((cursor) {
      expect(cursor.key, expectedFirst);
    });
  }
  if (expectedLast != null) {
    cursors.last.then((cursor) {
      expect(lastKey, expectedLast);
    });
  }

  return cursors.length.then((length) {
    if (expectedFirst == null) {
      expect(length, 0);
    } else {
      expect(length, expectedLast - expectedFirst + 1);
    }
  });
}

main() async {
  // Don't bother with these tests if it's unsupported.
  // Support is tested in indexeddb_1_test
  if (IdbFactory.supported) {
    var db = await setupDb();
    test('only1', () => testRange(db, new KeyRange.only(55), 55, 55));
    test('only2', () => testRange(db, new KeyRange.only(100), null, null));
    test('only3', () => testRange(db, new KeyRange.only(-1), null, null));

    test('lower1', () => testRange(db, new KeyRange.lowerBound(40), 40, 99));
    // OPTIONALS lower2() => testRange(db, new KeyRange.lowerBound(40, open: true), 41, 99);
    test(
      'lower2',
      () => testRange(db, new KeyRange.lowerBound(40, true), 41, 99),
    );
    // OPTIONALS lower3() => testRange(db, new KeyRange.lowerBound(40, open: false), 40, 99);
    test(
      'lower3',
      () => testRange(db, new KeyRange.lowerBound(40, false), 40, 99),
    );

    test('upper1', () => testRange(db, new KeyRange.upperBound(40), 0, 40));
    // OPTIONALS upper2() => testRange(db, new KeyRange.upperBound(40, open: true), 0, 39);
    test(
      'upper2',
      () => testRange(db, new KeyRange.upperBound(40, true), 0, 39),
    );
    // upper3() => testRange(db, new KeyRange.upperBound(40, open: false), 0, 40);
    test(
      'upper3',
      () => testRange(db, new KeyRange.upperBound(40, false), 0, 40),
    );

    test('bound1', () => testRange(db, new KeyRange.bound(20, 30), 20, 30));

    test('bound2', () => testRange(db, new KeyRange.bound(-100, 200), 0, 99));

    bound3() =>
        // OPTIONALS testRange(db, new KeyRange.bound(20, 30, upperOpen: true),
        testRange(db, new KeyRange.bound(20, 30, false, true), 20, 29);

    bound4() =>
        // OPTIONALS testRange(db, new KeyRange.bound(20, 30, lowerOpen: true),
        testRange(db, new KeyRange.bound(20, 30, true), 21, 30);

    bound5() =>
        // OPTIONALS testRange(db, new KeyRange.bound(20, 30, lowerOpen: true, upperOpen: true),
        testRange(db, new KeyRange.bound(20, 30, true, true), 21, 29);
  }
}
