import 'dart:async'; import 'package:guru_app/financial/igc/igc_manager.dart'; import 'package:guru_app/financial/product/product_model.dart'; import 'package:guru_app/inventory/inventory_manager.dart'; import 'manifest.dart'; /// Created by Haoyi on 2022/8/21 // typedef DetailsDistributor = Future Function(Details, TransactionMethod, String scene); typedef DetailsDistributor = Future> Function( Details, TransactionMethod, String scene); typedef ManifestBuilder = Future Function(TransactionIntent); class ManifestManager { ManifestManager._() { observableDeliveredManifest = deliveredManifestStream.stream.asBroadcastStream(); } final StreamController deliveredManifestStream = StreamController(); static final ManifestManager instance = ManifestManager._(); late Stream observableDeliveredManifest; final Map distributors = { DetailsReservedType.igc: _deliverIgcDetails }; final List builders = []; static Future> _deliverIgcDetails( Details details, TransactionMethod method, String scene) async { if (details.amount > 0) { await IgcManager.instance.accumulate(details.amount, method, scene: scene); } return []; } static Future> _deliverDefaultDetails( Details details, TransactionMethod method, String scene) async { if (details.amount > 0) { return [StockItem.fromDetails(details)]; } return []; } // static Future _deliverDetails( // Details details, TransactionMethod method, String scene) async { // final stock = StockItem.fromDetails(details); // if (stock.amount > 0) { // await InventoryManager.instance.acquire([stock], method, scene); // } // return false; // } void addDistributor(String type, DetailsDistributor distributor) { distributors[type] = distributor; } void addBuilder(ManifestBuilder builder) { builders.add(builder); } void addBuilders(List builders) { this.builders.addAll(builders); } Future _acquire(List items, TransactionMethod method, Manifest manifest) async { if (items.isNotEmpty) { String specific = ""; switch (method) { case TransactionMethod.iap: specific = manifest.contentId; break; case TransactionMethod.igc: specific = "coin"; break; case TransactionMethod.igb: specific = manifest.barterId; break; default: specific = manifest.scene; break; } await InventoryManager.instance.acquire(items, method, specific, scene: manifest.scene); } } Future> deliverStockItems( List items, Manifest manifest, TransactionMethod method) async { final List unsold = []; for (var item in items) { if (item.sku == DetailsReservedType.igc) { await distributors[DetailsReservedType.igc] ?.call(Details.define(DetailsReservedType.igc, item.amount), method, manifest.scene); continue; } unsold.add(item); } return unsold; } Future deliver(Manifest manifest, TransactionMethod method) async { bool result = false; final List unsold = []; for (var details in manifest.details) { final items = await distributors[details.type]?.call(details, method, manifest.scene) ?? await _deliverDefaultDetails(details, method, manifest.scene); final unsoldItems = await deliverStockItems(items, manifest, method); unsold.addAll(unsoldItems); result |= unsoldItems.isEmpty; } if (unsold.isNotEmpty) { await _acquire(unsold, method, manifest); } deliveredManifestStream.add(manifest); return result; } Future createManifest(TransactionIntent intent) async { for (var builder in builders) { final manifest = await builder(intent); if (manifest != null) { return manifest; } } return Manifest.empty; } Manifest createIgcManifest(int igc, {String? category, String scene = ""}) { final details =
[]; details.add(Details.define(DetailsReservedType.igc, igc)); final extras = {ExtraReservedField.scene: scene}; return Manifest(category ?? DetailsReservedType.igc, extras: extras, details: details); } // Manifest createIgbManifest(int igc, {String? category, String scene = ""}) { // final details =
[]; // details.add(Details.define(DetailsReservedType.igc, igc)); // // final extras = {ExtraReservedField.scene: scene}; // return Manifest(category ?? DetailsReservedType.igc, extras: extras, details: details); // } }