import 'package:flutter/material.dart';
import 'package:oc_front/core/services/enum_service.dart';
import 'package:oc_front/models/abstract.dart';
import 'package:oc_front/models/resources/resources.dart';

class StorageItem extends AbstractItem<StoragePricing, StoragePartnership, StorageInstance, StorageItem> {
  StorageItem({
    this.acronym,
    this.typeEnum,
  }): super();  

 @override String get topic => "storage";
  // special attributes
  String? acronym;
  int? typeEnum;

  @override deserialize(dynamic data) {
    try { data = data as Map<String, dynamic>;
    } catch (e) { return StorageItem(); }   
    var w = StorageItem(
      acronym: data.containsKey("acronym") && data["acronym"] != null ? data["acronym"] : null,
      typeEnum: data.containsKey("storage_type") && data["storage_type"] != null ? EnumService.get("storage/type", data["storage_type"]) : null,
    );
    w.mapFromJSON(data, StorageInstance());
    if (w.logo != null) { // get image dimensions
      var image = Image.network(w.logo!);
      image.image
        .resolve(const ImageConfiguration())
        .addListener(
            ImageStreamListener(
                (ImageInfo info, bool _) {
                  w.width = info.image.width.toDouble();
                  w.height = info.image.height.toDouble();
                }));
    }
    return w;
  }

  @override
  Map<String, dynamic> infos() {
    return {
      "acronym": acronym,
      "storage_type": EnumService.enums["storage/type"] != null 
        && EnumService.enums["storage/type"]!["$typeEnum"] != null ? 
        EnumService.enums["storage/type"]!["$typeEnum"] : typeEnum,
    };
  }

  @override Map<String, dynamic> serialize() {
    var obj = infos();
    obj.addAll(toJSON());
    return obj;
  }
}

class StorageInstance extends AbstractInstance<StoragePricing, StoragePartnership> {
  String? source;
  bool local = false;
  String? securityLevel;
  int? storageSizeEnum;
  int? size;
  bool encryption = false;
  String? redundancy;
  String? throughput;

  StorageInstance({
    this.source,
    this.local = false,
    this.securityLevel,
    this.storageSizeEnum,
    this.size,
    this.encryption = false,
    this.redundancy,
    this.throughput,
  }): super();

  @override
  StorageInstance deserialize(json) {
    try { json = json as Map<String, dynamic>;
    } catch (e) { return StorageInstance(); }
    var w = StorageInstance(
      source: json.containsKey("source") && json["source"] != null ? json["source"] : null,
      local: json.containsKey("local") && json["local"] != null ? json["local"] : false,
      securityLevel: json.containsKey("security_level") && json["security_level"] != null ? json["security_level"] : null,
      storageSizeEnum: json.containsKey("size_type") ? EnumService.get("storage/size", json["size_type"]) : null,
      size: json.containsKey("size") && json["size"] != null ? json["size"] : null,
      encryption: json.containsKey("encryption") && json["encryption"] != null ? json["encryption"] : false,
      redundancy: json.containsKey("redundancy") && json["redundancy"] != null ? json["redundancy"] : null,
      throughput: json.containsKey("throughput") && json["throughput"] != null ? json["throughput"] : null,
    );
    w.mapFromJSON(json, StoragePartnership());
    return w;
  }

  @override
  Map<String, dynamic> infos() {
    return {
      "local": local,
      "security_level": securityLevel,
      "size_type": EnumService.enums["storage/size"] != null 
      && EnumService.enums["storage/size"]!["$storageSizeEnum"] != null ? 
      EnumService.enums["storage/size"]!["$storageSizeEnum"] : storageSizeEnum,
      "size": size,
      "encryption": encryption,
      "redundancy": redundancy,
      "throughput": throughput,
      "inputs": toListJson(inputs),
      "outputs": toListJson(outputs),
    };
  } 


  @override
  Map<String, dynamic> serialize() {
    var obj = infos();
    obj["source"] = source;
    obj["size_type"] = storageSizeEnum;
    obj.addAll(toJSON());
    return obj;
  }
}

class StoragePartnership extends AbstractPartnerShip<StoragePricing> {
  double? maxSizeGBAllowed;
  bool onlyEncryptedAllowed = false;

  StoragePartnership({
    this.maxSizeGBAllowed,
    this.onlyEncryptedAllowed = false,
  }): super();

  @override
  StoragePartnership deserialize(json) {
    try { json = json as Map<String, dynamic>;
    } catch (e) { return StoragePartnership(); }
    var w = StoragePartnership(
      maxSizeGBAllowed: json.containsKey("allowed_gb") && json["allowed_gb"] != null ? json["allowed_gb"] : null,
      onlyEncryptedAllowed: json.containsKey("personal_data_allowed") && json["personal_data_allowed"] != null ? json["personal_data_allowed"] : false,
    );
    w.mapFromJSON(json, StoragePricing());
    return w;
  }

  @override
  Map<String, dynamic> serialize() {
    Map<String, dynamic> obj = {
      "allowed_gb": maxSizeGBAllowed,
      "personal_data_allowed": onlyEncryptedAllowed,
    };
    obj.addAll(toJSON());
    return obj;
  }
}

class StoragePricing extends AbstractPricing {
  @override StoragePricing deserialize(json) {
    var w = StoragePricing();
    w.mapFromJSON(json);
    return w;
  }
  @override
  Map<String, dynamic> serialize() {
    return toJSON();
  }
}