// ignore_for_file: non_constant_identifier_names

import 'dart:convert';

class DataMattermost {
  String? channel_id;
  String? channel;
  String? message;
  String? text;
  String? username;
  String? icon_url;
  String? icon_emoji;
  String? type;
  Map<String, dynamic>? props;
  List<MattermostAttachment>? attachments;

  String get json {
    return jsonEncode(toPostJson());
  }

  DataMattermost();

  factory DataMattermost.fromJson(Map<String, dynamic> json) {
    final data = DataMattermost();
    data.channel_id = json['channel_id'] as String?;
    data.channel = json['channel'] as String?;
    data.message = json['message'] as String?;
    data.text = json['text'] as String?;
    data.username = json['username'] as String?;
    data.icon_url = json['icon_url'] as String?;
    data.icon_emoji = json['icon_emoji'] as String?;
    data.type = json['type'] as String?;
    if (json['props'] is Map<String, dynamic>) {
      data.props =
          Map<String, dynamic>.from(json['props'] as Map<String, dynamic>);
    } else if (json['props'] is Map) {
      data.props = Map<String, dynamic>.from(json['props'] as Map);
    }
    if (json['attachments'] is List) {
      data.attachments = (json['attachments'] as List)
          .map((item) => MattermostAttachment.fromJson(
              Map<String, dynamic>.from(item as Map)))
          .toList();
    }
    return data;
  }

  Map<String, dynamic> toJson() {
    return removeEmptyKeys({
      'channel_id': channel_id,
      'channel': channel,
      'message': message,
      'text': text,
      'username': username,
      'icon_url': icon_url,
      'icon_emoji': icon_emoji,
      'type': type,
      'props': props,
      'attachments': attachments?.map((item) => item.toJson()).toList(),
    });
  }

  Map<String, dynamic> toPostJson({String? defaultChannelId}) {
    return normalizeMattermostPost(toJson(),
        defaultChannelId: defaultChannelId);
  }
}

class MattermostAttachment {
  String? fallback;
  String? color;
  String? pretext;
  String? text;
  String? author_name;
  String? author_link;
  String? author_icon;
  String? title;
  String? title_link;
  String? image_url;
  String? thumb_url;
  String? footer;
  String? footer_icon;
  List<MattermostField>? fields;
  List<Map<String, dynamic>>? actions;

  MattermostAttachment();

  factory MattermostAttachment.fromJson(Map<String, dynamic> json) {
    final data = MattermostAttachment();
    data.fallback = json['fallback'] as String?;
    data.color = json['color'] as String?;
    data.pretext = json['pretext'] as String?;
    data.text = json['text'] as String?;
    data.author_name = json['author_name'] as String?;
    data.author_link = json['author_link'] as String?;
    data.author_icon = json['author_icon'] as String?;
    data.title = json['title'] as String?;
    data.title_link = json['title_link'] as String?;
    data.image_url = json['image_url'] as String?;
    data.thumb_url = json['thumb_url'] as String?;
    data.footer = json['footer'] as String?;
    data.footer_icon = json['footer_icon'] as String?;
    if (json['fields'] is List) {
      data.fields = (json['fields'] as List)
          .map((item) =>
              MattermostField.fromJson(Map<String, dynamic>.from(item as Map)))
          .toList();
    }
    if (json['actions'] is List) {
      data.actions = (json['actions'] as List)
          .map((item) => Map<String, dynamic>.from(item as Map))
          .toList();
    }
    return data;
  }

  Map<String, dynamic> toJson() {
    return removeEmptyKeys({
      'fallback': fallback,
      'color': color,
      'pretext': pretext,
      'text': text,
      'author_name': author_name,
      'author_link': author_link,
      'author_icon': author_icon,
      'title': title,
      'title_link': title_link,
      'image_url': image_url,
      'thumb_url': thumb_url,
      'footer': footer,
      'footer_icon': footer_icon,
      'fields': fields?.map((item) => item.toJson()).toList(),
      'actions': actions,
    });
  }
}

class MattermostField {
  String? title;
  String? value;
  bool short = false;

  MattermostField();
  MattermostField.withParam(this.title, this.value, {this.short = false});

  factory MattermostField.fromJson(Map<String, dynamic> json) {
    final data = MattermostField();
    data.title = json['title'] as String?;
    data.value = json['value'] as String?;
    data.short = json['short'] as bool? ?? false;
    return data;
  }

  Map<String, dynamic> toJson() {
    return removeEmptyKeys({
      'title': title,
      'value': value,
      'short': short,
    });
  }
}

Map<String, dynamic> normalizeMattermostPost(Map<String, dynamic> payload,
    {String? defaultChannelId}) {
  final map = Map<String, dynamic>.from(payload);
  final props = map['props'] is Map<String, dynamic>
      ? Map<String, dynamic>.from(map['props'] as Map<String, dynamic>)
      : map['props'] is Map
          ? Map<String, dynamic>.from(map['props'] as Map)
          : <String, dynamic>{};

  if ((map['channel_id'] == null || '${map['channel_id']}'.isEmpty)) {
    final channel = map.remove('channel');
    if (channel != null && '$channel'.isNotEmpty) {
      map['channel_id'] = channel;
    } else if (defaultChannelId != null && defaultChannelId.isNotEmpty) {
      map['channel_id'] = defaultChannelId;
    }
  } else {
    map.remove('channel');
  }

  if ((map['message'] == null || '${map['message']}'.isEmpty) &&
      map['text'] != null) {
    map['message'] = map.remove('text');
  } else {
    map.remove('text');
  }

  _moveValueToProps(map, props, 'attachments', 'attachments');
  _moveValueToProps(map, props, 'username', 'override_username');
  _moveValueToProps(map, props, 'icon_url', 'override_icon_url');
  _moveValueToProps(map, props, 'icon_emoji', 'override_icon_emoji');

  if (props.isNotEmpty) {
    map['props'] = props;
  } else {
    map.remove('props');
  }

  return removeEmptyKeys(map);
}

void _moveValueToProps(
  Map<String, dynamic> source,
  Map<String, dynamic> props,
  String sourceKey,
  String targetKey,
) {
  if (props[targetKey] != null) {
    source.remove(sourceKey);
    return;
  }

  final value = source.remove(sourceKey);
  if (value != null) {
    props[targetKey] = value;
  }
}

Map<String, dynamic> removeEmptyKeys(Map<String, dynamic> map) {
  final emptyKeys = <String>[];
  for (final item in map.entries) {
    final value = item.value;
    if (value == null) {
      emptyKeys.add(item.key);
      continue;
    }
    if (value is String && value.isEmpty) {
      emptyKeys.add(item.key);
      continue;
    }
    if (value is List && value.isEmpty) {
      emptyKeys.add(item.key);
      continue;
    }
    if (value is Map && value.isEmpty) {
      emptyKeys.add(item.key);
    }
  }

  for (final key in emptyKeys) {
    map.remove(key);
  }
  return map;
}
