import 'dart:async';

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_picker/image_picker.dart';
import 'package:provider/provider.dart';
import 'package:selectable_autolink_text/selectable_autolink_text.dart';
import 'package:telnow_mobile_new/src/api/api_auth_provider.dart';
import 'package:telnow_mobile_new/src/layouts/functions/message.dart';
import 'package:telnow_mobile_new/src/layouts/components/template.dart';
import 'package:telnow_mobile_new/src/utils/C.dart';
import 'package:telnow_mobile_new/src/utils/U.dart';
import 'package:telnow_mobile_new/src/utils/provider.dart';
import 'package:translator/translator.dart';
import 'package:url_launcher/url_launcher.dart';

import 'dart:ui' as ui;

import 'package:uuid/uuid.dart';

import '../components/photo_chat.dart';

class WebMessageListPage extends StatefulWidget {
  final Map<String, dynamic>? user;
  const WebMessageListPage(this.user, {super.key});

  @override
  State<WebMessageListPage> createState() => _WebMessageListPageState();
}

class _WebMessageListPageState extends State<WebMessageListPage> {
  final MessageFunction messageFunc = MessageFunction();
  final ApiAuthProvider apiAuthProvider = ApiAuthProvider();
  final translator = GoogleTranslator();
  StreamSubscription<QuerySnapshot>? subscription;

  String? idChat;
  String tenant = '';
  String opponent = '';
  ScrollController scrollController = ScrollController();
  ScrollController forumScrollController = ScrollController();
  List messageData = [];
  List forumData = [];

  int page = 0;
  bool isAfterLoad = false;
  String username = '';
  bool isLoad = false;
  bool stopLoad = false;
  bool scrollBottom = false;
  bool forumScrollBottom = false;
  bool isReverse = false;
  bool isForumReverse = false;
  bool askBroadcast = false;

  bool openChat = false;
  bool isSend = false;
  double borderRadius = 10.0;
  Uint8List? _image;
  String forumHeader = '';
  String activeForumId = '';
  String forumChatId = '';
  TextEditingController controllerForum = new TextEditingController();
  String locale = 'id';
  late MessageModule messageModule;

  @override
  void initState() {
    messageModule = Provider.of<MessageModule>(context, listen: false);
    messageModule.reset();
    if(widget.user == null){
      messageFunc.getUser(context);
    } else {
      messageModule.setUser(widget.user!);
      messageFunc.getDataMessages(context);
    }
    username = messageModule.user()['userId'];
    // TODO: implement initState
    super.initState();
  }

  @override
  void dispose() {
    subscription?.cancel();
    super.dispose();
  }


  selectMessage(data, isMe) async{
    if(idChat != data['chatId']){
      setState(() {
        idChat = data['chatId'];
        askBroadcast = isMe;
        opponent = isMe ? data['recipientName'] : data['senderName'];
        tenant = data['recipient'];

        messageData = [];
        page = 0;
        isAfterLoad = false;
        isLoad = false;
        stopLoad = false;
        scrollBottom = false;
        isReverse = false;
      });

      scrollController.addListener(() => scrollListener());
      if (!isMe) {
        await apiAuthProvider.patchData('/api/messages/' + data['id'].toString(), {'readStatus': 'READ'});
      }

      getMessage();
      getCollectionData();
    }
  }

  selectMessageForum(dt){
    forumChatId = '${U.decodeBase64Url(U.getAccessCode()!)}-${dt['ticketNo']}';
    activeForumId = dt['ticketNo'];
    openChat = !(dt['currentState'] == 'DIBATALKAN' || dt['currentState'] == 'TUNTAS');
    forumHeader = dt[U.langColumn(context, 'requestSubject')];
    forumScrollController.addListener(() => forumScrollListener());

    forumData = [];
    page = 0;
    stopLoad = false;

    // unsub dulu biar ga double2
    subscription?.cancel();
    subscription = null;

    getMessageForum();
    getCollectionDataForum();
  }

  getMessage() async {
    String url = 'myMessages/$idChat';
    String filter = '{"f":["uniqueId","LIKE","%-%"]}';
    if (askBroadcast) {
      url = 'myBroadcast';
      filter = '{"f":["1","EQ","1"]}';
    }
    if (!isLoad && !stopLoad) {
      isLoad = true;
      var mymess = await apiAuthProvider.getData('/api/messages/search/$url', {'isPaged': 'true', 'page': page.toString(), 'size': '20', 'filter': filter, 'tenant': tenant});
      if (mymess.containsKey('_embedded') && mounted) {
        List data = mymess['_embedded']['myMessages'];
        for (int i = 0; i < data.length; i++) {
          if (username == data[i]['from']['user']) {
            data[i]['selected'] = false;
          }
          else{
            if(U.autoTranslate()){
              data[i]['translate'] = '';
            }
          }

          messageData.insert(0, data[i]);
        }
        setState(() {
          if (page == 0) {
            scrollBottom = true;
          }
          isLoad = false;
          page++;

          if (messageData.length >= mymess['page']['totalElements']) {
            stopLoad = true;
          }
        });

        if(U.autoTranslate()){
          translateMessage(0);
        }
      } else {
        setState(() {
          isLoad = false;
          stopLoad = true;
        });
      }
    }
  }

  getMessageForum()async{
    if(stopLoad) return;
    try{
      var mymess = await apiAuthProvider.getData(
          '/api/messages/search/myMessages/${forumChatId}',
          {'isPaged': 'true', 'page': page.toString(), 'size': '20'});

      if (mymess.containsKey('_embedded')) {
        List data = mymess['_embedded']['myMessages'];
        for (var item in data) {
          if (username == item['from']['user'] && item['senderType'] != 'SERVANT') {
            item['selected'] = false;
          } else {
            if(U.autoTranslate()){
              item['translate'] = '';
            }
          }
          final exists = forumData.any((e) => e['id'] == item['id']);
          if (!exists) {
            forumData.insert(0, item);
          }
        }
        if(mymess['page']['number'] == page) page++;
        if(mounted) {
          setState(() {
            isAfterLoad = true;
          });
        }
      }
      if(U.autoTranslate()){
        translateMessage(1);
      }
      if (forumData.length >= mymess['page']['totalElements']) {
        stopLoad = true;
      }
    } catch(e) {
      print(e.toString());
    }
  }

  getCollectionData() {
    FirebaseFirestore.instance.collection("tmMessages").doc('messages').collection(idChat!).snapshots().listen((querySnapshot) {
      querySnapshot.docChanges.forEach((result) async {
        var data = result.doc.data();
        if (result.type == DocumentChangeType.added && isAfterLoad) {
          if ((username == data!['from']['user'] && messageData.where((element) => element['uniqueId'] == data['uniqueId']).isNotEmpty) || (username != data['from']['user'] && data['readStatus'] == 'DELETED')) {
            int index = messageData.indexWhere((element) => element['uniqueId'] == data['uniqueId']);
            messageData[index]['read'] = data['read'];
            messageData[index]['readStatus'] = data['readStatus'];
            messageData[index]['imageUrl'] = data['imageUrl'];
          } else {
            try{
              if(U.autoTranslate()){
                var loc = locale == 'zh' ? 'zh-cn' : locale;
                var translate = await translator.translate(data['msg']??'', to: loc);
                data['translate'] = translate.text;
              }
            }catch(e){
              print("Error: ${e.toString()}");
            }

            messageData.add(data);
          }
        } else if (result.type == DocumentChangeType.modified && isAfterLoad) {
          // print("modified");
          if (messageData.where((element) => element['uniqueId'] == data!['uniqueId']).isNotEmpty) {
            int index = messageData.indexWhere((element) => element['uniqueId'] == data!['uniqueId']);
            messageData[index]['read'] = data!['read'];
            messageData[index]['readStatus'] = data['readStatus'];
          }
        } else if (result.type == DocumentChangeType.removed && isAfterLoad) {
          // print("removed");
        }
      });

      if(mounted) {
        setState(() {
          isAfterLoad = true;
        });
      }
    });
  }

  getCollectionDataForum() {
    subscription = FirebaseFirestore.instance.collection("tmMessages").doc('messages').collection(forumChatId).snapshots().listen((querySnapshot) {
      querySnapshot.docChanges.forEach((result) async {
        var data = result.doc.data();
        print(data);
        if(!mounted) return;
        if (result.type == DocumentChangeType.added && isAfterLoad) {
          if((username == data!['from']['user'] && forumData.where((element) => element['uniqueId'] == data['uniqueId']).isNotEmpty) || (username != data['from']['user'] && data['readStatus'] == 'DELETED')) {
            int index = forumData.indexWhere((element) => element['uniqueId'] == data['uniqueId']);
            forumData[index]['read'] = data['read'];
            forumData[index]['readStatus'] = data['readStatus'];
            forumData[index]['imageUrl'] = data['imageUrl'];
          } else {
            try{
              if(U.autoTranslate()){
                var loc = locale == 'zh' ? 'zh-cn' : locale;
                var translate = await translator.translate(data['msg']??'', to: loc);
                data['translate'] = translate.text;

              }
            }catch(e){
              print("Error f: ${e.toString()}");
            }
            forumData.add(data);
            updateMessageDisplay(data);
          }
        } else if (result.type == DocumentChangeType.modified && isAfterLoad) {
          // print("modified");
          if (forumData.where((element) => element['uniqueId'] == data!['uniqueId']).isNotEmpty) {
            int index = forumData.indexWhere((element) => element['uniqueId'] == data!['uniqueId']);
            forumData[index]['read'] = data!['read'];
            forumData[index]['readStatus'] = data['readStatus'];
          }
        } else if (result.type == DocumentChangeType.removed && isAfterLoad) {
          // print("removed");
        }
        if(mounted) setState(() {});
      });
      if(mounted) {
        setState(() {
          isAfterLoad = true;
        });
      }
    });
  }

  void updateMessageDisplay(Map<String, dynamic> data) {
    final forum = messageModule.forum();
    final res = <Map<String, dynamic>>[];

    for (int i = 0; i < forum.length; i++) {
      final tmp = Map<String, dynamic>.from(forum[i]);
      if (tmp['ticket']['ticketNo'] == activeForumId) {
        tmp['msg'] = data['msg'];
      }
      res.add(tmp);
    }

    messageModule.setForum(res);
  }


  translateMessage(int t){
    var dt = t == 0 ? messageData : forumData;
    var loc = locale == 'zh' ? 'zh-cn' : locale;
    dt.forEach((element) async {
      if (element['senderType'] == 'SERVANT' && element['translate'] == '') { //&& username != element['from']['user']
        try {
          var translate = await translator.translate(
              element['msg'] ?? '', to: loc);
          element['translate'] = translate.text;
        }catch(e){
          element['translate'] = '';
        }
        setState(() {});
      }
    });
  }

  deleteCollection() {
    var ids = [idChat, forumChatId];
    for(int i=0; i < ids.length; i++){
      var id = ids[i]??'';
      if(id != '') {
        try {
          FirebaseFirestore.instance.collection("tmMessages").doc('messages')
              .collection(id).get()
              .then((value) {
            for (DocumentSnapshot ds in value.docs) {
              ds.reference.delete();
            }
          });
        } catch (e) {}
      }
    }
  }

  scrollToBottom() {
    if(scrollController.hasClients) {
      scrollController.animateTo(scrollController.position.minScrollExtent,
          duration: Duration(milliseconds: 1), curve: Curves.decelerate);
      scrollBottom = false;
    }
  }

  scrollListener() {
    if (scrollController.hasClients && scrollController.offset >= scrollController.position.maxScrollExtent) {
      // print('loadMessage');
      getMessage();
    }
  }

  forumScrollListener() {
    if(forumScrollController.hasClients && forumScrollController.offset >= forumScrollController.position.maxScrollExtent) {
      getMessageForum();
    }
  }


  @override
  Widget build(BuildContext context) {
    locale = context.locale.toString();
    if (messageData.length > 0) {
      try{
        if (scrollController.hasClients && scrollController.position.maxScrollExtent > 0 && !isReverse) {
          setState(() => isReverse = true);
        }

        if (isAfterLoad && scrollBottom && isReverse) {
          scrollToBottom();
        }
      }catch(e){
        print(e.toString());
      }
    }

    Widget tabForum(){
      return Row(
        mainAxisAlignment: MainAxisAlignment.start,
        children: [
          GestureDetector(
            onTap: () {
              Provider.of<MessageModule>(context, listen: false).setActiveTab(0);
            },
            child: Container(
              margin: EdgeInsetsDirectional.only(start: 100),
              padding: EdgeInsets.symmetric(vertical: 12, horizontal: 16),
              decoration: BoxDecoration(
                  color: Colors.white,
                  border: Border(bottom: BorderSide(color: Provider.of<MessageModule>(context).activeTab() == 0 ? primaryColor : primaryColor.withValues(alpha: 0.3), width: Provider.of<MessageModule>(context).activeTab() == 0 ? 2 : 1))),
              child: Text('chat'.tr(), style: TextStyle(color: Provider.of<MessageModule>(context).activeTab() == 0 ? textColor : textColor.withValues(alpha: 0.65), fontSize: 16)),
            ),
          ),
          GestureDetector(
            onTap: () {
              Provider.of<MessageModule>(context, listen: false).setActiveTab(1);
            },
            child: Container(
              padding: EdgeInsets.symmetric(vertical: 12, horizontal: 16),
              decoration: BoxDecoration(
                  color: Colors.white,
                  border: Border(bottom: BorderSide(color: Provider.of<MessageModule>(context).activeTab() == 1 ? primaryColor : primaryColor.withValues(alpha: 0.3), width: Provider.of<MessageModule>(context).activeTab() == 1 ? 2 : 1))),
              child: Text('forum'.tr(), style: TextStyle(color: Provider.of<MessageModule>(context).activeTab() == 1 ? textColor : textColor.withValues(alpha: 0.65), fontSize: 16)),
            ),
          ),
        ],
      );
    }

    // Widget chat(){
    //   final messageModule = Provider.of<MessageModule>(context);
    //   final dataList = messageModule.data();
    //   final currentUser = messageModule.user();
    //   final forumList = messageModule.forum();
    //
    //   return dataList.isEmpty ? Expanded(
    //     child: Center(
    //       child: Text('noMessageText'.tr()),
    //     ),
    //   ) : SingleChildScrollView(
    //     padding: EdgeInsets.symmetric(vertical: 20, horizontal: 10),
    //     child: Column(
    //       mainAxisSize: MainAxisSize.max,
    //       children: List.generate(dataList.length, (i) {
    //         final item = dataList[i];
    //         final isMe = item['userId'] == currentUser['userId'];
    //         final avatar = item['senderAvatar'];
    //         final chatIdMatch = idChat != null && idChat == item['chatId'];
    //         final recipientColor = U.getColor(isMe ? item['recipient'] : item['recipientId']);
    //         final recipientName = item['recipientName'];
    //         final senderName = item['senderName'];
    //         final lastText = item['lastText'] ?? '';
    //         final isImage = item['isImage'] ?? false;
    //         final fileType = item['fileType'] ?? '';
    //         final lastDate = item['lastDateTimeSend'];
    //         final lastReadStatus = item['lastReadStatus'];
    //         final forumReadStatus = forumList[i]['readStatus'];
    //
    //         return GestureDetector(
    //           onTap: () => selectMessage(item, isMe),
    //           child: Container(
    //             padding: EdgeInsets.all(10),
    //             decoration: BoxDecoration(
    //               color: chatIdMatch ? Color(0xff26DA17).withAlpha(50) : Colors.white,
    //               borderRadius: BorderRadius.circular(12),
    //             ),
    //             child: Row(
    //               children: [
    //                 avatar != null && avatar != ''
    //                     ? CircleAvatar(
    //                   backgroundImage: NetworkImage(avatar),
    //                   radius: 24,
    //                 )
    //                     : Container(
    //                   height: 48,
    //                   width: 48,
    //                   decoration: BoxDecoration(
    //                     shape: BoxShape.circle,
    //                     color: Color(recipientColor),
    //                   ),
    //                   child: Center(
    //                     child: Text(
    //                       isMe
    //                           ? recipientName == "all_informants"
    //                           ? "allInformants".tr()[0]
    //                           : recipientName[0]
    //                           : senderName[0],
    //                       style: TextStyle(
    //                         color: Colors.white,
    //                         fontWeight: FontWeight.bold,
    //                         fontSize: 18,
    //                       ),
    //                     ),
    //                   ),
    //                 ),
    //                 SizedBox(width: 20),
    //                 Expanded(
    //                   child: Column(
    //                     crossAxisAlignment: CrossAxisAlignment.start,
    //                     children: [
    //                       Text(
    //                         isMe
    //                             ? recipientName == "all_informants"
    //                             ? "allInformants".tr()
    //                             : recipientName
    //                             : senderName,
    //                         style: TextStyle(fontWeight: FontWeight.w600),
    //                       ),
    //                       SizedBox(height: 5),
    //                       Row(
    //                         children: [
    //                           if (isMe)
    //                             Padding(
    //                               padding: EdgeInsets.only(right: 5),
    //                               child: Icon(Icons.done_all, size: 18, color: Colors.blueGrey),
    //                             ),
    //                           if (isImage)
    //                             Row(
    //                               children: [
    //                                 Icon(
    //                                   fileType == 'pdf' ? Icons.picture_as_pdf : Icons.image,
    //                                   color: Colors.black45,
    //                                   size: 16,
    //                                 ),
    //                                 SizedBox(width: 6),
    //                                 if (lastText == '')
    //                                   Text(fileType == 'pdf' ? 'pdfFile'.tr() : 'photo'.tr()),
    //                               ],
    //                             ),
    //                           Expanded(
    //                             child: Text(
    //                               lastText,
    //                               style: TextStyle(fontSize: 13),
    //                               maxLines: 1,
    //                               overflow: TextOverflow.ellipsis,
    //                             ),
    //                           ),
    //                         ],
    //                       ),
    //                     ],
    //                   ),
    //                 ),
    //                 SizedBox(width: 20),
    //                 Column(
    //                   crossAxisAlignment: CrossAxisAlignment.end,
    //                   children: [
    //                     Text(
    //                       convertDate(lastDate, context.locale.toString()),
    //                       style: TextStyle(
    //                         fontSize: 11,
    //                         fontWeight: forumReadStatus == 'UNREAD' ? FontWeight.w600 : FontWeight.w300,
    //                         color: lastReadStatus == 'UNREAD' && !isMe ? primaryColor : Colors.black45,
    //                       ),
    //                     ),
    //                     SizedBox(height: 12),
    //                     Icon(
    //                       Icons.circle,
    //                       size: 12,
    //                       color: primaryColor.withAlpha(lastReadStatus == 'UNREAD' && !isMe ? 1 : 0),
    //                     ),
    //                   ],
    //                 ),
    //               ],
    //             ),
    //           ),
    //         );
    //       }),
    //     ),
    //   );
    // }

    Widget webChat(BuildContext context) {
      final messageModule = Provider.of<MessageModule>(context);
      final dataList = messageModule.data();
      final currentUser = messageModule.user();
      final isFirstLoad = messageModule.firstLoad();

      return Container(
        padding: EdgeInsets.symmetric(vertical: 20, horizontal: 10),
        alignment: Alignment.topCenter,
        child: dataList.isEmpty && !isFirstLoad
            ? loadingTemplateNoVoid()
            : dataList.isEmpty
            ? Center(child: Text('noMessageText'.tr()))
            : ListView.builder(
          itemCount: dataList.length,
          itemBuilder: (context, i) {
            final item = dataList[i];
            final isMe = item['userId'] == currentUser['userId'];
            final avatar = item['senderAvatar'];
            final recipientName = item['recipientName'];
            final senderName = item['senderName'];
            final lastText = item['lastText'] ?? '';
            final isImage = item['isImage'] ?? false;
            final fileType = item['fileType'] ?? '';
            final lastDate = item['lastDateTimeSend'];
            final lastReadStatus = item['lastReadStatus'];
            final chatId = item['chatId'];
            final recipientId = item['recipientId'];
            final recipient = item['recipient'];
            // final id = item['id'];

            return GestureDetector(
              onTap: () {
                selectMessage(item, isMe);
                // navigateTo(
                //   context,
                //   MobMessageChatPage(
                //     currentUser,
                //     chatId,
                //     isMe ? recipientName : senderName,
                //     id.toString(),
                //     isMe,
                //     recipient,
                //   ),
                // );
                messageFunc.onRefresh(context);
              },
              child: Container(
                padding: EdgeInsets.all(10),
                margin: EdgeInsets.only(bottom: 12),
                decoration: BoxDecoration(
                  color: idChat != null && idChat == chatId
                      ? Color(0xff26DA17).withAlpha(50)
                      : Colors.white,
                  borderRadius: BorderRadius.circular(12),
                ),
                child: Row(
                  children: [
                    avatar != null && avatar != ''
                        ? CircleAvatar(
                      backgroundImage: NetworkImage(avatar),
                      radius: 24,
                    )
                        : Container(
                      height: 48,
                      width: 48,
                      decoration: BoxDecoration(
                        shape: BoxShape.circle,
                        color: Color(U.getColor(isMe ? recipient : recipientId)),
                      ),
                      child: Center(
                        child: Text(
                          isMe
                              ? recipientName == "all_informants"
                              ? "allInformants".tr()[0]
                              : recipientName[0]
                              : senderName[0],
                          style: TextStyle(
                            color: Colors.white,
                            fontWeight: FontWeight.bold,
                            fontSize: 18,
                          ),
                        ),
                      ),
                    ),
                    SizedBox(width: 20),
                    Expanded(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text(
                            isMe
                                ? recipientName == "all_informants"
                                ? "allInformants".tr()
                                : recipientName
                                : senderName,
                            style: TextStyle(fontWeight: FontWeight.w600),
                          ),
                          SizedBox(height: 5),
                          Row(
                            children: [
                              if (isMe)
                                Padding(
                                  padding: EdgeInsets.only(right: 4),
                                  child: Icon(Icons.done_all, size: 18, color: Colors.blueGrey),
                                ),
                              if (isImage)
                                Row(
                                  children: [
                                    Icon(
                                      fileType == 'pdf' ? Icons.picture_as_pdf : Icons.image,
                                      color: Colors.black45,
                                      size: 16,
                                    ),
                                    SizedBox(width: 6),
                                    if (lastText == '')
                                      Text(fileType == 'pdf' ? 'pdfFile'.tr() : 'photo'.tr()),
                                  ],
                                ),
                              Expanded(
                                child: Text(
                                  lastText,
                                  style: TextStyle(fontSize: 13),
                                  maxLines: 1,
                                  overflow: TextOverflow.ellipsis,
                                ),
                              ),
                            ],
                          ),
                        ],
                      ),
                    ),
                    SizedBox(width: 20),
                    Column(
                      crossAxisAlignment: CrossAxisAlignment.end,
                      children: [
                        Text(
                          messageFunc.timeSet(lastDate),
                          style: TextStyle(
                            fontSize: 11,
                            color: lastReadStatus == 'UNREAD' && !isMe ? Colors.green : Colors.black45,
                          ),
                        ),
                        SizedBox(height: 4),
                        Icon(
                          Icons.circle,
                          color: Colors.green.withAlpha(lastReadStatus == 'UNREAD' && !isMe ? 1 : 0),
                        ),
                      ],
                    ),
                  ],
                ),
              ),
            );
          },
        ),
      );
    }

    // tampilan list pesan forum di sebelah kiri
    Widget forum(){
      final messageModule = Provider.of<MessageModule>(context);
      return messageModule.forum().isEmpty ? Center(
        child: Text('noMessageText'.tr()),
      ) : SingleChildScrollView(
        padding: EdgeInsets.symmetric(vertical: 20, horizontal: 10),
        child: Column(
          mainAxisSize: MainAxisSize.max,
          children: List.generate(messageModule.forum().length, (i){
            bool isMe0 = messageModule.forum()[i]['userId'] == messageModule.user()['userId'] ? true : false;
            return GestureDetector(
              onTap: (){
                var dt = messageModule.forum()[i]['ticket'];
                messageFunc.setAsRead(context, dt['ticketNo']);
                messageModule.forum()[i]['readStatus'] = 'READ';
                selectMessageForum(dt);
                setState(() {
                  isAfterLoad = false;
                  forumData = [];
                });
              },
              child: Container(
                  decoration: BoxDecoration(
                    color: activeForumId != '' && messageModule.forum()[i]['ticket']['ticketNo'] == activeForumId ? Color(0xff26DA17).withValues(alpha: 0.2) : Colors.white,
                    borderRadius: BorderRadius.all(Radius.circular(12)),
                  ),
                  width: double.infinity,
                  child: Column(
                    children: [
                      Padding(
                        padding: const EdgeInsets.all(10.0),
                        child: Row(
                          children: [
                            Container(
                              height: 48,
                              width: 48,
                              decoration: BoxDecoration(
                                image: DecorationImage(image: NetworkImage(messageModule.forum()[i]['ticket']['_requestImage'])),
                                // color: Colors.green,
                                border: Border.all(color: Colors.black12),
                                borderRadius: BorderRadius.circular(50),
                              ),
                            ),
                            SizedBox(width: 20,),
                            Expanded(
                              child: Column(
                                crossAxisAlignment: CrossAxisAlignment.start,
                                children: [
                                  Row(
                                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                                    crossAxisAlignment: CrossAxisAlignment.start,
                                    children: [
                                      Flexible(
                                        child: Text(
                                          messageModule.forum()[i]['ticket'][U.langColumn(context, 'requestSubject')],
                                          maxLines: 1,
                                          overflow: TextOverflow.ellipsis,
                                          softWrap: false,
                                          style: TextStyle(
                                            fontWeight: FontWeight.w600,
                                          ),
                                        ),
                                      ),
                                      SizedBox(width: 4),
                                      Text(
                                        convertDate(messageModule.forum()[i]['datetime'], context.locale.toString()),
                                        style: TextStyle(
                                          fontSize: 11,
                                          fontWeight: messageModule.forum()[i]['readStatus']=='UNREAD' ? FontWeight.w600 : FontWeight.w300,
                                          color: messageModule.forum()[i]['readStatus']=='UNREAD' && !isMe0 ? primaryColor : Colors.black45,
                                        ),
                                      ),
                                    ],
                                  ),
                                  SizedBox(height: 8,),
                                  Row(
                                    crossAxisAlignment: CrossAxisAlignment.start,
                                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                                    children: [
                                      Flexible(
                                        child: Text(
                                          messageModule.forum()[i]['msg'],
                                          overflow: TextOverflow.ellipsis,
                                          maxLines: 2,
                                        ),
                                      ),
                                      SizedBox(width: 12,),
                                      Icon(
                                        Icons.circle,
                                        size: 12,
                                        color: messageModule.forum()[i]['readStatus']=='UNREAD' && !isMe0 ? primaryColor : Colors.transparent,
                                      ),
                                    ],
                                  ),
                                ],
                              ),
                            ),
                          ],
                        ),
                      ),
                    ],
                  )
              ),
            );
          }),
        ),
      );
    }

    Widget chatList(){
      return idChat != null ? Column(
        children: [
          Container(
            width: double.infinity, padding: EdgeInsets.all(20),
            child: Text(opponent != 'all_informants' ? opponent : "allInformants".tr(), style: TextStyle(color: textColor, fontSize: 16)),
          ),
          divider(),
          Expanded(
            child: messageData.isEmpty && !isAfterLoad ? loadingTemplateNoVoid() : SingleChildScrollView(
              padding: const EdgeInsets.fromLTRB(10, 10, 10, 7),
              controller: scrollController,
              reverse: isReverse,
              child: Column(
                children: List.generate(messageData.length, (i) {
                  bool hideDate = i == 0 ? false : checkDate(messageData[i]['datetime'], messageData[i - 1]['datetime']);
                  bool isNip = i == 0 ? true : !hideDate ? true : messageData[i]['from']['user'] == messageData[i - 1]['from']['user'] ? false : true;
                  return Column(
                    children: [
                      !hideDate ? Center(
                        child: Padding(
                          padding: const EdgeInsets.all(10),
                          child: bubble_chat(Text(convertDate(messageData[i]['datetime'], context.locale.toString()), textAlign: TextAlign.center, style: TextStyle(fontSize: 12)), null, false, false),
                        ),
                      ) : Container(),
                      Builder(builder: (context) {
                        var isMe = messageData[i]['from']['user'] == Provider.of<MessageModule>(context, listen: false).user()['userId'];
                        var isFile = messageData[i]['imageUrl'] != null && messageData[i]['imageUrl'] != '' && messageData[i]['readStatus'] != 'DELETED';
                        var isPdf = isFile && messageData[i]['imageUrl'].split('.').last == 'pdf';
                        var isImg = isFile && !isPdf;
                        var isTranslate = U.autoTranslate() && !isMe && messageData[i]['msg'] != messageData[i]['translate'];

                        var wdg = messageData[i]['readStatus'] == 'DELETED' ? Text('deletedMessage'.tr(), style: TextStyle(fontSize: 14, color: Colors.black54, fontStyle: FontStyle.italic)) : Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            isPdf ? GestureDetector(
                              child: Builder(builder: (context) {
                                var pdfContainer = Container(
                                  padding: EdgeInsets.all(6),
                                  decoration: BoxDecoration(color: Colors.black12.withValues(alpha: 0.1), borderRadius: BorderRadius.all(Radius.circular(4))),
                                  child: Row(
                                    mainAxisSize: MainAxisSize.min,
                                    children: [
                                      Icon(Icons.picture_as_pdf),
                                      SizedBox(width: 6),
                                      Flexible(child: Text(getImageName(messageData[i]['imageUrl'])))
                                    ],
                                  ),
                                );

                                return pdfContainer;
                              }),
                              onTap: () async {
                                await launchUrl( messageData[i]['imageUrl']);
                              },
                            ) : isImg ? GestureDetector(
                              child: Container(
                                  margin: const EdgeInsets.only(bottom: 5),
                                  child: Builder(builder: (context) {
                                    return Image.network(messageData[i]['imageUrl'], fit: BoxFit.cover, width: 200, height: 200);
                                  })
                              ),
                              onTap: () => navigateTo(context, PhotoPreview(opponent, messageData[i]['imageUrl'], true)),
                            ) : SizedBox(height: 1),
                            messageData[i]['msg'] != null && messageData[i]['msg'] != '' ? Column(
                              crossAxisAlignment: !isMe?CrossAxisAlignment.start:CrossAxisAlignment.end,
                              children: [
                                SizedBox(height: 4),
                                SelectableAutoLinkText(
                                  messageData[i]['msg'],
                                  style: TextStyle(fontSize: 14, color: Colors.black),
                                  linkStyle: TextStyle(color: Colors.blueAccent),
                                  highlightedLinkStyle: TextStyle(color: Colors.blueAccent, backgroundColor: Colors.blueAccent.withAlpha(0x33)),
                                  onTap: (link) async{
                                    if (await canLaunchUrl(Uri.parse(link))) {
                                      await launchUrl(Uri.parse(link));
                                    }
                                  },
                                  onLongPress: (link) {
                                    Clipboard.setData(new ClipboardData(text: link)).then((value){
                                      showSuccess('link_copied'.tr(), context);
                                    });
                                  },
                                  enableInteractiveSelection: false,
                                ),
                                isTranslate ? Container(
                                  margin: EdgeInsets.only(top: 2), decoration: BoxDecoration(border: Border(top: BorderSide(color: Colors.black.withValues(alpha: 0.2)))),
                                  child: Text(messageData[i]['translate'] != '' ? '(${messageData[i]['translate']})' : '...', style: TextStyle(fontSize: 14, color: Colors.black.withValues(alpha: 0.65), fontStyle: FontStyle.italic)),
                                ) : Container(),
                              ],
                            ) : Container()
                          ],
                        );

                        var timeBubble = Positioned(
                          bottom: 2, right: isNip ? 6 : 0,
                          child: Text(DateFormat('HH:mm').format(DateTime.parse(messageData[i]['datetime'])), style: TextStyle(fontSize: 10, color: Colors.black45)),
                        );

                        var expander = Expanded(
                            flex: 8,
                            child: Column(
                              crossAxisAlignment: isMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
                              children: [
                                bubble_chat(wdg, timeBubble, isNip, isMe),
                                SizedBox(height: 5),
                              ],
                            )
                        );

                        return isMe ? Row(
                          children: [
                            Expanded(flex: 2, child: Container()),
                            expander,
                          ],
                        ) : Row(
                          children: [
                            expander,
                            Expanded(flex: 2, child: Container()),
                          ],
                        );
                      }),
                    ],
                  );
                }),
              ),
            ),
          )
        ],
      ) : Center(
        child: Text("noMessageText".tr()),
      );
    }

    sendMessage(data) async {
      isSend = false;
      controllerForum.clear();
      forumData.add({
        'msg': data['text'],
        'datetime': DateTime.now().toString(),
        'read': null,
        'imageUrl': data['images'],
        'readStatus': '',
        'from': {'name': 'my name', 'user': data['userId']},
        'uniqueId': data['uniqueId'],
        'selected': false,
        'senderType': 'INFORMANT'
      });
      scrollBottom = true;

      var res = await apiAuthProvider.postData('/api/messages', null, data);
      if (res != null) {
        int index = forumData.indexWhere((element) => element['uniqueId'] == data['uniqueId']);
        forumData[index]['read'] = false;
      } else {
        int index = forumData.indexWhere((element) => element['uniqueId'] == data['uniqueId']);
        forumData[index]['readStatus'] = 'FAILED';
      }
      setState(() {});
    }

    // tampilan list chat forum yg sebelah kanan
    Widget forumList(){
      return activeForumId == '' ? Center(child: Text("noMessageText".tr())) : Column(
        children: [
          Container(
            width: double.infinity, padding: EdgeInsets.all(20),
            child: Text(forumHeader, style: TextStyle(color: textColor, fontSize: 16)),
          ),
          divider(),
          Expanded(
            child: forumData.isEmpty && !isAfterLoad ? loadingTemplateNoVoid() : Align(
              alignment: Alignment.topCenter,
              child: SingleChildScrollView(
                padding: const EdgeInsets.fromLTRB(10, 10, 10, 7),
                controller: forumScrollController,
                reverse: true,
                child: Column(
                  children: List.generate(forumData.length, (i) {
                    bool hideDate = i == 0 ? false : checkDate(forumData[i]['datetime'], forumData[i - 1]['datetime']);
                    bool isNip = i == 0 ? true : !hideDate ? true : forumData[i]['from']['user'] == forumData[i - 1]['from']['user'] ? false : true;
                    return Column(
                      children: [
                        !hideDate ? Container(margin: EdgeInsets.only(bottom: 5), child: bubble_chat(Text(convertDate(forumData[i]['datetime'], context.locale.toString()), textAlign: TextAlign.center, style: TextStyle(fontSize: 12)), null, false, false)) : Container(),
                        Builder(builder: (context) {
                          var isMe = username == forumData[i]['from']['user'] && forumData[i]['senderType'] == 'INFORMANT';
                          var isImage = forumData[i]['imageUrl'] != null && forumData[i]['imageUrl'] != '' && forumData[i]['readStatus'] != 'DELETED';
                          var isTranslate = U.autoTranslate() && !isMe && forumData[i]['msg'] != forumData[i]['translate'];

                          var widget = Row(
                            mainAxisSize: MainAxisSize.min,
                            children: [
                              forumData[i]['readStatus'] == 'FAILED' ? Padding(
                                padding: const EdgeInsets.only(right: 15),
                                child: PopupMenuButton<int>(
                                  itemBuilder: (context) => [
                                    PopupMenuItem(value: 1, height: 40, child: Text("delete".tr(), style: TextStyle(fontSize: 14))),
                                    PopupMenuItem(value: 2, height: 40, child: Text("resend".tr(), style: TextStyle(fontSize: 14))),
                                  ],
                                  offset: Offset(MediaQuery.of(context).size.width, 0),
                                  onSelected: (value) {
                                    if (value == 1) {
                                      forumData.removeWhere((item) => item['uniqueId'] == forumData[i]['uniqueId']);
                                    } else if (value == 2) {
                                      var text = forumData[i]['msg'];
                                      var images = forumData[i]['imageUrl'];
                                      forumData.removeWhere((item) => item['uniqueId'] == forumData[i]['uniqueId']);

                                      var uuid = Uuid().v1().replaceAll('-', '');
                                      var data = {
                                        "uniqueId": uuid,
                                        "userId": username,
                                        "recipientId": "#forum",
                                        "senderType": "INFORMANT",
                                        "text": text,
                                        "chatId": idChat,
                                        "images": images
                                      };
                                      sendMessage(data);
                                    }
                                  },
                                  child: Icon(Icons.refresh, color: Colors.red),
                                ),
                              ) : Container(),
                              Flexible(
                                child: Column(
                                  crossAxisAlignment: CrossAxisAlignment.start,
                                  children: <Widget>[
                                    !isMe ? Padding(
                                      padding: const EdgeInsets.only(bottom: 6.0,),
                                      child: Text(
                                        forumData[i]['from']['name'],
                                        style: TextStyle(color: Color(U.getColor(forumData[i]['from']['user'])), fontSize: 12.0),
                                        textAlign: TextAlign.start,
                                      ),
                                    ) : SizedBox(),
                                    isImage ? Padding(
                                      padding: EdgeInsets.only(bottom: 2),
                                      child: GestureDetector(
                                        child: Container(
                                          margin: const EdgeInsets.only(bottom: 5),
                                          child: Builder(builder: (context) {
                                            return Image.network(forumData[i]['imageUrl']);
                                          }),
                                        ),
                                        onTap: () => navigateTo(context, PhotoPreview('forum'.tr(), forumData[i]['imageUrl'], true)),
                                      ),
                                    ) : Container(width: 1),
                                    forumData[i]['readStatus'] == 'DELETED' ? Text('deletedMessage'.tr(), style: TextStyle(fontSize: 14, color: Colors.white70, fontStyle: FontStyle.italic)) : forumData[i]['msg'] != null && forumData[i]['msg'] != '' ? SelectableAutoLinkText(
                                      forumData[i]['msg'],
                                      style: TextStyle(fontSize: 14, color: Colors.black),
                                      linkStyle: TextStyle(color: Colors.blueAccent),
                                      highlightedLinkStyle: TextStyle(color: Colors.blueAccent, backgroundColor: Colors.blueAccent.withAlpha(0x33)),
                                      onTap: (link) async{
                                        if (await canLaunchUrl(Uri.parse(link))) {
                                          await launchUrl(Uri.parse(link));
                                        }
                                      },
                                      onLongPress: (link) {
                                        Clipboard.setData(new ClipboardData(text: link)).then((value){
                                          showSuccess('link_copied'.tr(), context);
                                        });
                                      },
                                      textAlign: TextAlign.start,
                                    ) : Container(width: 1),
                                    isTranslate ? Container(
                                      margin: EdgeInsets.only(top: 2), decoration: BoxDecoration(border: Border(top: BorderSide(color: Colors.black.withValues(alpha: 0.2)))),
                                      child: Text(forumData[i]['translate']!=''?'(${forumData[i]['translate']})':'...', style: TextStyle(fontSize: 14, color: Colors.black.withValues(alpha: 0.65), fontStyle: FontStyle.italic)),
                                    ) : Container(),
                                  ],
                                ),
                              )
                            ],
                          );

                          var timeBubble = RichText(
                            text: TextSpan(children: [
                              TextSpan(text: DateFormat('HH:mm').format(DateTime.parse(forumData[i]['datetime'])), style: TextStyle(fontSize: 12, color: Colors.black38)),
                              WidgetSpan(
                                  child: Padding(
                                      padding: const EdgeInsets.only(left: 3),
                                      child: isMe ? Icon(
                                        forumData[i]['read'] == null ? Icons.done : Icons.done_all,
                                        color: forumData[i]['read'] != null && forumData[i]['read'] ? Colors.green : Colors.black38,
                                        size: 15,
                                      ) : SizedBox()
                                  )
                              ),
                            ]),
                          );

                          var expander = Expanded(
                              flex: 8,
                              child: Column(
                                crossAxisAlignment: isMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
                                children: [
                                  bubble_chat(widget, timeBubble, isNip, isMe),
                                  SizedBox(height: 5),
                                ],
                              )
                          );

                          return isMe ? Row(
                            children: [
                              Expanded(
                                flex: 2,
                                child: Container(),
                              ),
                              expander,
                            ],
                          ) : Row(
                            children: [
                              expander,
                              Expanded(
                                flex: 2,
                                child: Container(),
                              ),
                            ],
                          );
                        })
                      ],
                    );
                  }),
                ),
              ),
            ),
          ),
          openChat ? divider() : Container(),
          openChat ? Container(
            alignment: Alignment.bottomCenter,
            // color: Colors.white,
            padding: EdgeInsets.all(12),
            child: Row(
              children: [
                Expanded(
                  child: SizedBox(
                    width: double.infinity,
                    child: TextField(
                      controller: controllerForum,
                      maxLength: 256,
                      style: const TextStyle(fontSize: 14, color: Colors.black),
                      keyboardType: TextInputType.multiline,
                      minLines: 1,
                      maxLines: 5,
                      decoration: InputDecoration(
                          counterText: '',
                          hintText: 'writeMessage'.tr()+'..',
                          hintStyle: TextStyle(color: textColor.withValues(alpha: 0.5), fontSize: 14),
                          filled: true,
                          fillColor: backgroundColor,
                          hoverColor: Colors.black.withValues(alpha: 0.1),
                          contentPadding: EdgeInsets.symmetric(vertical: 17, horizontal: 20),
                          suffixIcon: GestureDetector(
                            child: Padding(
                              padding: EdgeInsets.only(left: 13, right: 13),
                              child: U.iconsax('paperclip-2', color: textColor, size: 24),
                            ),
                            onTap: ()async{
                              var uuid = Uuid().v1().replaceAll('-', '');
                              var data = {
                                "uniqueId": uuid,
                                "userId": username,
                                "recipientId": "#forum",
                                "senderType": "INFORMANT",
                                "text": controllerForum.text.trim(),
                                "chatId": forumChatId,
                                "images": null
                              };

                              await getImage(ImageSource.gallery).then((value) {
                                if (_image != null) {
                                  navigateTo(context, PhotoChat(data, ImageSource.gallery, false, _image!)).then((value) {
                                    if (value != null) {
                                      sendMessage(value);
                                    }
                                  });
                                }
                              });
                            },
                          ),
                          border: InputBorder.none,
                          enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(borderRadius), borderSide: BorderSide(color: textColor)),
                          focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(borderRadius), borderSide: BorderSide(color: primaryColor)),
                          isDense: true
                      ),
                      onChanged: (val) {
                        setState(() {
                          if (val.trim() != '') {
                            final tp = TextPainter(text: TextSpan(text: val), textDirection: ui.TextDirection.ltr);
                            tp.layout(maxWidth: 400);
                            final line = tp.computeLineMetrics().length;
                            if (line == 1) {
                              borderRadius = 50.0;
                            } else {
                              borderRadius = 20.0;
                            }

                            isSend = true;
                          } else {
                            isSend = false;
                          }
                        });
                      },
                    ),
                  ),
                ),
                SizedBox(width: 12),
                GestureDetector(
                  child: Container(
                    padding: EdgeInsets.all(12),
                    child: Image.asset('assets/image/icon/Send.png', width: 20, height: 20),
                    decoration: BoxDecoration(color: primaryColor, borderRadius: BorderRadius.all(Radius.circular(50))),
                  ),
                  onTap: (){
                    if(controllerForum.text.isNotEmpty){
                      var uuid = Uuid().v1().replaceAll('-', '');
                      var data = {
                        "uniqueId": uuid,
                        "userId": username,
                        "recipientId": "#forum",
                        "senderType": "INFORMANT",
                        "text": controllerForum.text.trim(),
                        "chatId": forumChatId,
                        "images": null
                      };

                      sendMessage(data);
                    }
                  },
                )
              ],
            ),
          ) : U.getInternetStatus() ? Center(child: Padding(
            padding: EdgeInsets.symmetric(vertical: 20),
            child: bubble_chat(Text('chatClosed'.tr(), textAlign: TextAlign.center, style: TextStyle(fontSize: 12)), null, false, false),
          )):Container()
        ],
      );
    }

    return Scaffold(
      backgroundColor: backgroundColor,
      appBar: PreferredSize(preferredSize: Size.fromHeight(0), child: AppBar(elevation: 0, backgroundColor: primaryColor)),
      body: Column(
        children: [
          Container(
            padding: EdgeInsets.symmetric(vertical: 25, horizontal: 100),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Text('message'.tr(), style: TextStyle(color: textColor, fontSize: 17, fontWeight: FontWeight.w500), overflow: TextOverflow.ellipsis),
                GestureDetector(
                  child: Text('buttonBack'.tr(), style: TextStyle(color: primaryColor, fontSize: 14)),
                  onTap: (){
                    deleteCollection();
                    navigateBack(context);
                  },
                )
              ],
            ),
          ),
          divider(),
          tabForum(),
          Expanded(
            child: Container(
              width: double.infinity, height: double.infinity,
              padding: EdgeInsets.symmetric(vertical: 12, horizontal: 100),
              child: Row(
                children: [
                  Expanded(
                    child: Stack(
                      children: [
                        Container(
                          width: double.infinity, height: double.infinity,
                          decoration: BoxDecoration(color: Colors.white, border: Border.all(color: textColor.withValues(alpha: 0.15)), borderRadius: BorderRadius.all(Radius.circular(12))),
                          child: EasyRefresh(
                            header: MaterialHeader(clamping: true, color: primaryColor),
                            onRefresh: () => messageFunc.onRefresh(context),
                            child: !Provider.of<MessageModule>(context).firstLoad() ? loadingTemplateNoVoid()
                                : Provider.of<MessageModule>(context).activeTab() == 0 ? webChat(context) : forum()
                          ),
                        ),
                        Provider.of<MessageModule>(context).user().isNotEmpty && Provider.of<MessageModule>(context).user()['canSendMessage'] ? Align(
                          alignment: Alignment.bottomRight,
                          child: GestureDetector(
                            child: Container(
                              margin: EdgeInsets.only(right: 20, bottom: 20),
                              width: 50, height: 50, alignment: Alignment.center,
                              decoration: BoxDecoration(
                                color: primaryColor,
                                borderRadius: BorderRadius.all(Radius.circular(50))
                              ),
                              child: U.iconsax('message', color: Colors.white),
                            ),
                            onTap: ()=>messageFunc.createMessage(context),
                          ),
                        ) : Container()
                      ],
                    ),
                  ),
                  SizedBox(width: 24),
                  Expanded(
                    child: Container(
                      decoration: BoxDecoration(color: Colors.white, border: Border.all(color: textColor.withValues(alpha: 0.15)), borderRadius: BorderRadius.all(Radius.circular(12))),
                      child: Provider.of<MessageModule>(context).activeTab() == 0 ? chatList() : forumList(),
                    )
                  )
                ],
              ),
            ),
          )
        ],
      ),
    );
  }

  getImageName(imageUrl) {
    var imgSplit = imageUrl.toString().split('/');
    return imgSplit[imgSplit.length - 1];
  }

  Widget bubble_chat(Widget child, Widget? time, bool isNip, bool isMe) {
    bool isDate = false;
    if (time == null) {
      isDate = true;
      time = Container();
    }
    Color color = isMe ? primaryColor.withValues(alpha: 0.3) : isDate ? Color(0xffD5F5FF) : Color(0xffECECEC);
    var clipPath = ClipPath(
      clipper: isMe ? MyClipper(isNip) : YourClipper(isNip),
      child: ConstrainedBox(
        constraints: BoxConstraints(minWidth: 50),
        child: Container(
          decoration: BoxDecoration(
            color: color,
          ),
          child: Padding(padding: EdgeInsets.all(8),
            child: isDate ? child : Stack(
              children: [
                Padding(
                  padding: EdgeInsets.only(
                    bottom: 15,
                    right: isNip && isMe ? 6 : 0,
                    left: isNip && !isMe ? 6 : 0,
                  ),
                  child: child,
                ),
                Positioned(
                  bottom: 2,
                  right: 2,
                  child: time,
                ),
                // time
              ],
            ),
          ),
        ),
      ),
    );

    return Padding(
        padding: EdgeInsets.only(
            right: isNip && isMe ? 0 : 6,
            left: isNip && !isMe ? 0 : 6
        ),
        child: clipPath
    );
  }

  bool checkDate(date1, date2) {
    final dateToCheck1 = DateTime(DateTime.parse(date1).year, DateTime.parse(date1).month, DateTime.parse(date1).day);
    final dateToCheck2 = DateTime(DateTime.parse(date2).year, DateTime.parse(date2).month, DateTime.parse(date2).day);

    return dateToCheck1 == dateToCheck2 ? true : false;
  }

  getImage(ImageSource gallery) {}
}
