import 'dart:convert';

class GetCityInfoList {
  CategoriesNames? categoriesNames;
  String? category;
  String? categoryValue;
  int? cityId;
  String? cityName;
  String? cityNameN;
  ColorName? colorName;
  String? createdOn;
  String? id;
  int? iniceId;
  bool? isOrderEmpty;
  bool? isValuesReversed;
  bool? language;
  double? latitude;
  double? longitude;
  String? name;
  int? orderNum;
  double? temperature;
  String? value;

  GetCityInfoList({
    this.categoriesNames,
    this.category,
    this.categoryValue,
    this.cityId,
    this.cityName,
    this.cityNameN,
    this.colorName,
    this.createdOn,
    this.id,
    this.iniceId,
    this.isOrderEmpty,
    this.isValuesReversed,
    this.language,
    this.latitude,
    this.longitude,
    this.name,
    this.orderNum,
    this.temperature,
    this.value,
  });

  factory GetCityInfoList.fromRawJson(String str) => GetCityInfoList.fromJson(json.decode(str));

  String toRawJson() => json.encode(toJson());

  factory GetCityInfoList.fromJson(Map<String, dynamic> json) {
    ColorName? parseColorName(dynamic value) {
      if (value == null) return null;
      try {
        return colorNameValues.map[value.toString()];
      } catch (e) {
        print("Unknown color name: $value");
        return null;
      }
    }

    CategoriesNames? parseCategoriesNames(dynamic value) {
      if (value == null) return null;
      try {
        return CategoriesNames.fromJson(value as Map<String, dynamic>);
      } catch (e) {
        print("Error parsing CategoriesNames: $e");
        return null;
      }
    }

    return GetCityInfoList(
      categoriesNames: parseCategoriesNames(json["CategoriesNames"]),
      category: json["Category"],
      categoryValue: json["CategoryValue"],
      cityId: json["CityID"],
      cityName: json["CityName"],
      cityNameN: json["CityNameN"],
      colorName: parseColorName(json["ColorName"]),
      createdOn: json["CreatedOn"],
      id: json["ID"],
      iniceId: json["IniceID"],
      isOrderEmpty: json["IsOrderEmpty"],
      isValuesReversed: json["IsValuesReversed"],
      language: json["Language"],
      latitude: json["Latitude"]?.toDouble(),
      longitude: json["Longitude"]?.toDouble(),
      name: json["Name"],
      orderNum: json["OrderNum"],
      temperature: json["Temperature"]?.toDouble(),
      value: json["Value"],
    );
  }

  Map<String, dynamic> toJson() => {
    "CategoriesNames": categoriesNames?.toJson(),
    "Category": category,
    "CategoryValue": categoryValue,
    "CityID": cityId,
    "CityName": cityName,
    "CityNameN": cityNameN,
    "ColorName": colorNameValues.reverse[colorName],
    "CreatedOn": createdOn,
    "ID": id,
    "IniceID": iniceId,
    "IsOrderEmpty": isOrderEmpty,
    "IsValuesReversed": isValuesReversed,
    "Language": language,
    "Latitude": latitude,
    "Longitude": longitude,
    "Name": name,
    "OrderNum": orderNum,
    "Temperature": temperature,
    "Value": value,
  };
}

class CategoriesNames {
  Category1? category1;
  Category2? category2;
  Category3? category3;
  Category4? category4;
  Category5? category5;

  CategoriesNames({
    this.category1,
    this.category2,
    this.category3,
    this.category4,
    this.category5,
  });

  factory CategoriesNames.fromRawJson(String str) => CategoriesNames.fromJson(json.decode(str));

  String toRawJson() => json.encode(toJson());

  factory CategoriesNames.fromJson(Map<String, dynamic> json) {
    T? parseEnum<T>(dynamic value, EnumValues<T> enumValues, String enumName) {
      if (value == null) return null;
      try {
        return enumValues.map[value.toString()];
      } catch (e) {
        print("Unknown $enumName value: $value");
        return null;
      }
    }

    return CategoriesNames(
      category1: parseEnum(json["Category1"], category1Values, "Category1"),
      category2: parseEnum(json["Category2"], category2Values, "Category2"),
      category3: parseEnum(json["Category3"], category3Values, "Category3"),
      category4: parseEnum(json["Category4"], category4Values, "Category4"),
      category5: parseEnum(json["Category5"], category5Values, "Category5"),
    );
  }

  Map<String, dynamic> toJson() => {
    "Category1": category1Values.reverse[category1],
    "Category2": category2Values.reverse[category2],
    "Category3": category3Values.reverse[category3],
    "Category4": category4Values.reverse[category4],
    "Category5": category5Values.reverse[category5],
  };
}

enum Category1 {
  AT_EXTREME_RISK,
  CATEGORY1_EXTREME,
  EXTREME,
  POOR
}

final category1Values = EnumValues({
  "At Extreme Risk": Category1.AT_EXTREME_RISK,
  "Extreme\u000d\n": Category1.CATEGORY1_EXTREME,
  "Extreme": Category1.EXTREME,
  "Poor": Category1.POOR
});

enum Category2 {
  AT_HIGH_RISK,
  CATEGORY2_VERY_HIGH,
  FAIR,
  VERY_HIGH
}

final category2Values = EnumValues({
  "At High Risk": Category2.AT_HIGH_RISK,
  "Very High\u000d\n": Category2.CATEGORY2_VERY_HIGH,
  "Fair": Category2.FAIR,
  "Very High": Category2.VERY_HIGH
});

enum Category3 {
  AT_RISK,
  CATEGORY3_HIGH,
  GOOD,
  HIGH
}

final category3Values = EnumValues({
  "At Risk": Category3.AT_RISK,
  "High\u000d\n": Category3.CATEGORY3_HIGH,
  "Good": Category3.GOOD,
  "High": Category3.HIGH
});

enum Category4 {
  CATEGORY4_MODERATE,
  MODERATE,
  NEUTRAL,
  VERY_GOOD
}

final category4Values = EnumValues({
  "Moderate\u000d\n": Category4.CATEGORY4_MODERATE,
  "Moderate": Category4.MODERATE,
  "Neutral": Category4.NEUTRAL,
  "Very Good": Category4.VERY_GOOD
});

enum Category5 {
  BENEFICIAL,
  CATEGORY5_LOW,
  EXCELLENT,
  LOW
}

final category5Values = EnumValues({
  "Beneficial": Category5.BENEFICIAL,
  "Low\u000d\n": Category5.CATEGORY5_LOW,
  "Excellent": Category5.EXCELLENT,
  "Low": Category5.LOW
});

enum ColorName {
  GREEN,
  LIGHTGREEN,
  ORANGE,
  RED,
  YELLOW
}

final colorNameValues = EnumValues({
  "green": ColorName.GREEN,
  "lightgreen": ColorName.LIGHTGREEN,
  "orange": ColorName.ORANGE,
  "red": ColorName.RED,
  "yellow": ColorName.YELLOW
});

class EnumValues<T> {
  Map<String, T> map;
  late Map<T, String> reverseMap;

  EnumValues(this.map);

  Map<T, String> get reverse {
    reverseMap = map.map((k, v) => MapEntry(v, k));
    return reverseMap;
  }
}
