// 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);
  }
}
