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

class DataItem extends AbstractItem<DataPricing, DataPartnership, DataInstance, DataItem> {
  // special attributes
  String? type;
  String? source;
  String? quality;
  bool openData = false;
  bool static = false;
  bool personalData = false;
  bool anonymizedPersonalData = false;
  double? size;
  String? example;
  DateTime? updatePeriod;
  
  DataItem({
    this.type,
    this.source,
    this.quality,
    this.openData = false,
    this.static = false,
    this.personalData = false,
    this.anonymizedPersonalData = false,
    this.size,
    this.example,
    this.updatePeriod,
  }): super();  

  @override String get topic => "data";

  @override deserialize(dynamic data) {
    try { data = data as Map<String, dynamic>;
    } catch (e) { return DataItem(); }   
    var w = DataItem(
      type: data.containsKey("type") && data["type"] != null ? data["type"] : null,
      source: data.containsKey("source") && data["source"] != null ? data["source"] : null,
      quality: data.containsKey("quality") && data["quality"] != null ? data["quality"] : null,
      openData: data.containsKey("open_data") && data["open_data"] != null ? data["open_data"] : false,
      static: data.containsKey("static") && data["static"] != null ? data["static"] : false,
      personalData: data.containsKey("personal_data") && data["l"] != null ? data["personal_data"] : false,
      anonymizedPersonalData: data.containsKey("anonymized_personal_data") && data["anonymized_personal_data"] != null ? data["anonymized_personal_data"] : false,
      size: data.containsKey("size") && data["size"] != null ? data["size"] : null,
      example: data.containsKey("example") && data["example"] != null ? data["example"] : null,
      updatePeriod: data.containsKey("update_period") && data["update_period"] != null ? DateTime.parse(data["update_period"]) : null,
    );
    w.mapFromJSON(data, DataInstance());
    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 {
      "type": type,
      "quality": quality,
      "open_data": openData,
      "static": static,
      "personal_data": personalData,
      "anonymized_personal_data": anonymizedPersonalData,
      "size": size,
      "example": example,
      "update_period": updatePeriod?.toIso8601String(),
    };
  }

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

class DataInstance extends AbstractInstance<DataPricing, DataPartnership> {
  String? source;
  DataInstance(
    {this.source}
  ): super();

  @override
  Map<String, dynamic> infos() {
    return {
      "inputs": toListJson(inputs),
      "outputs": toListJson(outputs),
    };
  } 

  @override
  DataInstance deserialize(json) {
    try { json = json as Map<String, dynamic>;
    } catch (e) { return DataInstance(); }
    var w = DataInstance(
      source: json.containsKey("source") && json["source"] != null ? json["source"] : null,
    );
    w.mapFromJSON(json, DataPartnership());
    return w;
  }

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

class DataPartnership extends AbstractPartnerShip<DataPricing> {
  double? maxDownloadableGBAllowed;
  bool personalDataAllowed = false;
  bool anonymizedPersonalDataAllowed = false;

  DataPartnership({
    this.maxDownloadableGBAllowed,
    this.personalDataAllowed = false,
    this.anonymizedPersonalDataAllowed = false,
  }): super();

  @override
  DataPartnership deserialize(json) {
    try { json = json as Map<String, dynamic>;
    } catch (e) { return DataPartnership(); }
    var w = DataPartnership(
      maxDownloadableGBAllowed: json.containsKey("max_downloadable_gb_allowed") && json["max_downloadable_gb_allowed"] != null ? json["max_downloadable_gb_allowed"] : null,
      personalDataAllowed: json.containsKey("personal_data_allowed") && json["personal_data_allowed"] != null ? json["personal_data_allowed"] : false,
      anonymizedPersonalDataAllowed: json.containsKey("anonymized_personal_data_allowed") && json["anonymized_personal_data_allowed"] != null ? json["anonymized_personal_data_allowed"] : false,
    );
    w.mapFromJSON(json, DataPricing());
    return w;
  }

  @override
  Map<String, dynamic> serialize() {
    Map<String, dynamic> obj = {
      "max_downloadable_gb_allowed": maxDownloadableGBAllowed,
      "personal_data_allowed": personalDataAllowed,
      "anonymized_personal_data_allowed": anonymizedPersonalDataAllowed,
    };
    obj.addAll(toJSON());
    return obj;
  }
}

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