// Copyright (c) 2022, 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.

@JS()
library;

import 'dart:async';
import 'dart:convert';
// TODO: https://github.com/dart-lang/webdev/issues/2508
// ignore: deprecated_member_use
import 'dart:js_util';

import 'package:dwds/data/data_types.dart';
import 'package:dwds/data/debug_info.dart';
// TODO: https://github.com/dart-lang/webdev/issues/2508
// ignore: deprecated_member_use
import 'package:js/js.dart';

import 'chrome_api.dart';
import 'logger.dart';
import 'utils.dart';

enum StorageObject {
  debugInfo,
  devToolsOpener,
  devToolsUri,
  encodedUri,
  isAuthenticated,
  multipleAppsDetected;

  Persistence get persistence => switch (this) {
    StorageObject.debugInfo => Persistence.sessionOnly,
    StorageObject.devToolsOpener => Persistence.acrossSessions,
    StorageObject.devToolsUri => Persistence.sessionOnly,
    StorageObject.encodedUri => Persistence.sessionOnly,
    StorageObject.isAuthenticated => Persistence.sessionOnly,
    StorageObject.multipleAppsDetected => Persistence.sessionOnly,
  };
}

enum Persistence { sessionOnly, acrossSessions }

Future<bool> setStorageObject<T>({
  required StorageObject type,
  required T value,
  int? tabId,
  void Function()? callback,
}) {
  final storageKey = _createStorageKey(type, tabId);
  final json = _serialize(value);
  final storageObj = <String, String>{storageKey: json};
  final completer = Completer<bool>();
  final storageArea = _getStorageArea(type.persistence);
  storageArea.set(
    jsify(storageObj),
    allowInterop(() {
      if (callback != null) {
        callback();
      }
      debugLog('Set: $json', prefix: storageKey);
      completer.complete(true);
    }),
  );
  return completer.future;
}

String _serialize<T>(T value) {
  return switch (value) {
    final String v => v,
    final DebugInfo v => jsonEncode(v),
    final ConnectFailure v => jsonEncode(v),
    final DebugStateChange v => jsonEncode(v),
    final DevToolsOpener v => jsonEncode(v),
    final DevToolsUrl v => jsonEncode(v),
    _ => throw UnsupportedError('Unknown type for serialization: $T'),
  };
}

Future<T?> fetchStorageObject<T>({required StorageObject type, int? tabId}) {
  final storageKey = _createStorageKey(type, tabId);
  final completer = Completer<T?>();
  final storageArea = _getStorageArea(type.persistence);
  storageArea.get(
    [storageKey],
    allowInterop((Object? storageObj) {
      if (storageObj == null) {
        debugWarn('Does not exist.', prefix: storageKey);
        completer.complete(null);
        return;
      }
      final json = getProperty(storageObj, storageKey) as String?;
      if (json == null) {
        debugWarn('Does not exist.', prefix: storageKey);
        completer.complete(null);
      } else {
        debugLog('Fetched: $json', prefix: storageKey);
        completer.complete(_deserialize<T>(json));
      }
    }),
  );
  return completer.future;
}

T _deserialize<T>(String json) {
  if (T == String) return json as T;
  final decoded = jsonDecode(json);
  return switch (decoded) {
    ['DebugInfo', ...] => DebugInfo.fromJson(decoded) as T,
    ['ConnectFailure', ...] => ConnectFailure.fromJson(decoded) as T,
    ['DebugStateChange', ...] => DebugStateChange.fromJson(decoded) as T,
    ['DevToolsOpener', ...] => DevToolsOpener.fromJson(decoded) as T,
    ['DevToolsUrl', ...] => DevToolsUrl.fromJson(decoded) as T,
    _ => throw UnsupportedError('Unknown type for deserialization: $T'),
  };
}

Future<List<T>> fetchAllStorageObjectsOfType<T>({required StorageObject type}) {
  final completer = Completer<List<T>>();
  final storageArea = _getStorageArea(type.persistence);
  storageArea.get(
    null,
    allowInterop((Object? storageContents) {
      if (storageContents == null) {
        debugWarn('No storage objects of type exist.', prefix: type.name);
        completer.complete([]);
        return;
      }
      final allKeys = List<String>.from(objectKeys(storageContents));
      final storageKeys = allKeys.where((key) => key.contains(type.name));
      final result = <T>[];
      for (final key in storageKeys) {
        final json = getProperty(storageContents, key) as String?;
        if (json != null) {
          result.add(_deserialize<T>(json));
        }
      }
      completer.complete(result);
    }),
  );
  return completer.future;
}

Future<bool> removeStorageObject({required StorageObject type, int? tabId}) {
  final storageKey = _createStorageKey(type, tabId);
  final completer = Completer<bool>();
  final storageArea = _getStorageArea(type.persistence);
  storageArea.remove(
    [storageKey],
    allowInterop(() {
      debugLog('Removed object.', prefix: storageKey);
      completer.complete(true);
    }),
  );
  return completer.future;
}

void interceptStorageChange<T>({
  required Object storageObj,
  required StorageObject expectedType,
  required void Function(T? storageObj) changeHandler,
  int? tabId,
}) {
  try {
    final expectedStorageKey = _createStorageKey(expectedType, tabId);
    final isExpected = hasProperty(storageObj, expectedStorageKey);
    if (!isExpected) return;

    final objProp = getProperty(storageObj, expectedStorageKey);
    final json = getProperty(objProp, 'newValue') as String?;
    final decodedObj = json != null ? _deserialize<T>(json) : null;
    debugLog('Intercepted $expectedStorageKey change: $json');
    return changeHandler(decodedObj);
  } catch (error) {
    debugError(
      'Error intercepting storage object with type $expectedType: $error',
    );
  }
}

StorageArea _getStorageArea(Persistence persistence) {
  // MV2 extensions don't have access to session storage:
  if (!isMV3) return chrome.storage.local;

  return switch (persistence) {
    Persistence.acrossSessions => chrome.storage.local,
    Persistence.sessionOnly => chrome.storage.session,
  };
}

String _createStorageKey(StorageObject type, int? tabId) {
  if (tabId == null) return type.name;
  return '$tabId-${type.name}';
}
