
import 'dart:html';
import 'dart:typed_data';

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:url_launcher/url_launcher.dart';

import '../constants.dart';
import '../events/eventbus.dart';
import '../events/events.dart';
import '../generated/l10n.dart';
import '../models/comment.dart' as mComment;
import '../models/order.dart';
import '../models/payment_platform.dart';
import '../models/user.dart';
import '../store/actions.dart';
import '../store/store.dart';
import '../widgets/general/e_transfer_pay.dart';
import 'http_util.dart';
import 'utils.dart';

typedef void OnGotFile(int imageId, String filePath);

class Util {
  static final Util _instance = Util._internal();
  factory Util() {
    return _instance;
  }
  Util._internal();
  init() {

  }

  static Future<Box> getBox() async {
    Hive.initFlutter();
    Box box = await Hive.openBox('wisetronic_app_data');
    return box;
  }

  static Widget showImage(String imageUrl, {double? width, double? height,
    BoxFit? fit, Widget Function(BuildContext, String?, dynamic)? errorWidget}) {
    return Image.network(imageUrl,
      fit: fit,
      width: width,
      height: height,
      cacheWidth: width != null ? width.round() : null,
      cacheHeight: height != null ? height.round() : null,
      loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent? loadingProgress) {
        if (loadingProgress == null) return child;
        return Center(
          child: Utils.imageLoadingIndicator(),
        );
      },
      errorBuilder: (BuildContext context, Object object, StackTrace? stackTrace) {
        print('StackTrace: $stackTrace');
        if (errorWidget != null) {
          return errorWidget(context, null, null);
        }
        return Image.asset(
          'assets/images/not_found.png',
          width: width,
          height: height,
          fit: fit,
        );
      },
    );
  }

  static void openWebUrl(BuildContext context, String link) async {
    var url = 'https://${link}';
    if (await canLaunch(url)) {
      await launch('$url');
    } else {
      print('Could not launch $url');
    }
  }

  AlertDialog getPicture(BuildContext context, User user, {int commentId = -1, int orderId = 0}) {
    return AlertDialog(
      title: Text(S.of(context).please_select),
      content: Text(S.of(context).please_select_an_image),
      actions: <Widget>[
        TextButton(
          child: Text(S.of(context).cancel),
          onPressed: () {
            Navigator.of(context).pop();
          },
        ),
        TextButton(
          child: Text(S.of(context).select, style: TextStyle(color: Colors.white),),
          style: TextButton.styleFrom(
            backgroundColor: Theme.of(context).primaryColor,
          ),
          onPressed: () {
            Navigator.of(context).pop();
            startFilePicker(context, user, commentId: commentId, orderId: orderId);
          },
        ),
      ],
    );
  }

  void startFilePicker(BuildContext context, User user, {int commentId = -1, int orderId = 0}) async {
    FileUploadInputElement uploadInput = FileUploadInputElement();
    uploadInput.click();
    uploadInput.onChange.listen((e) {
      final files = uploadInput.files;
      if (files != null && files.length >= 1) {
        final File file = files[0];
        final FileReader reader = new FileReader();

        reader.onLoadEnd.listen((e) {
          uploadPicture(context, reader.result as Uint8List, file.name, user, commentId: commentId, orderId: orderId);
        });
        reader.onError.listen((e) {
          Fluttertoast.showToast(
              msg: S.of(context).error_read_file,
              toastLength: Toast.LENGTH_SHORT,
              gravity: ToastGravity.CENTER,
              backgroundColor: Colors.black54,
              textColor: Colors.white
          );
        });
        reader.readAsArrayBuffer(file);
      }
    });
  }

  void uploadPicture(BuildContext context, Uint8List fileBytes, String fileName, User user, {int commentId = -1, int orderId = 0}) {
    MultipartFile imageFile = MultipartFile.fromBytes(fileBytes, filename: fileName);
    Map<String, dynamic> formMap = {
      'id': user.id,
      'file': imageFile,
    };
    if (commentId >= 0) {
      formMap = {
        'contact_id': user.id,
        'comment_id': commentId,
        'order_id': orderId,
        'file': imageFile,
      };
      HttpUtil.httpPost(
        'v1/upload-comment-image',
            (response) {
          eventBus.fire(new OnCommentUpdatedEvent(mComment.Comment.fromJson(response.data)));
        },
        isFormData: true,
        body: formMap,
        sendProgress: (int sent, int total) {
          if (sent == total) {
            eventBus.fire(OnUploadCommentImageProgressEvent(false, 0.0));
          } else {
            eventBus.fire(OnUploadCommentImageProgressEvent(true, sent / total));
          }
        },
      ).catchError((error) {
        Utils.showMessageDialog(context, error);
      });
    } else {
      HttpUtil.httpPost(
        'v1/upload-avatar',
            (response) {
          store.dispatch(new UpdateCurrentUser(User.fromJson(response.data)));
          eventBus.fire(new OnCurrentUserUpdated());
        },
        isFormData: true,
        body: formMap,
        sendProgress: (int sent, int total) {
          if (sent == total) {
            eventBus.fire(OnProgressEvent(false, 0.0));
          } else {
            eventBus.fire(OnProgressEvent(true, sent / total));
          }
        },
      ).catchError((error) {
        Utils.showMessageDialog(context, error);
      });
    }
  }

  AlertDialog getPicture2(BuildContext context, int imageId, OnGotFile onGotFile) {
    return AlertDialog(
      title: Text(S.of(context).please_select),
      content: Text(S.of(context).please_select_an_image),
      actions: <Widget>[
        TextButton(
          child: Text(S.of(context).cancel),
          onPressed: () {
            Navigator.of(context).pop();
          },
        ),
        TextButton(
          child: Text(S.of(context).select, style: TextStyle(color: Colors.white),),
          style: TextButton.styleFrom(
            backgroundColor: Theme.of(context).primaryColor,
          ),
          onPressed: () {
            Navigator.of(context).pop();
            startFilePicker2(context, imageId, onGotFile);
          },
        ),
      ],
    );
  }

  void startFilePicker2(BuildContext context, int imageId, OnGotFile onGotFile) async {
    final _image = await WebImagePicker().pickImage();
    onGotFile(imageId, _image?.dataScheme ?? '');
  }

  void createTicket(BuildContext context, String msg, List<Map<String, dynamic>> images,
      OnSuccess onSuccess, OnError onError, {int? id}) {
    var formData = FormData();
    formData.fields.add(MapEntry("msg", msg));
    formData.fields.add(MapEntry('id', id == null ? '0' : id.toString()));
    for (int i = 0; i < images.length; i++) {
      String imagePath = images[i]['path'];
      if (imagePath.isNotEmpty) {
        // (formMap['images'] as List).add(imagePath);
        formData.fields.add(MapEntry('images', imagePath));
      }
    }
    HttpUtil.httpPost('create-new-ticket-web/', (response) {
      if (onSuccess != null) {
        onSuccess(response);
      }
    },
      isFormData: true,
      // body: formMap,
      formData: formData,
      sendProgress: (int sent, int total) {
        if (sent == total) {
          eventBus.fire(OnSubmitProgressEvent(false, 100.0));
        } else {
          eventBus.fire(OnSubmitProgressEvent(true, sent / total * 100.0));
        }
      },
      businessId: Constants.BUSINESS_ID,
    ).catchError((error) {
      if (onError != null) {
        onError(error);
      }
    });
  }

  static void goPayment(BuildContext context, Order order,
      PaymentPlatform paymentPlatform, {
        bool googlePay=false,
        bool applePay=false,
      }) {
    switch(paymentPlatform.code) {
      case Constants.PAYMENT_METHOD_CODE_SQUARE:

        break;
      case Constants.PAYMENT_METHOD_CODE_CHASE:

        break;
      case Constants.PAYMENT_METHOD_CODE_PAYPAL:

        break;
      case Constants.PAYMENT_METHOD_CODE_OTT_ALIPAY:

        break;
      case Constants.PAYMENT_METHOD_CODE_OTT_WECHATPAY:

        break;
      case Constants.PAYMENT_METHOD_CODE_POD:

        break;
      case Constants.PAYMENT_METHOD_CODE_STRIPE:
        Navigator.pushReplacement(context, MaterialPageRoute(
            builder: (BuildContext context) {
              return ETransferPay(order: order);
            }
        ));
        break;
    }
  }

  Widget getNativePay(BuildContext context, Order order, PaymentPlatform paymentPlatform) {
    return SizedBox.shrink();
  }

  static Future<Uint8List> getBytesFromAsset(String path, int width) async {
    return Uint8List(0);
  }
}

class ImageInfo {
  String? name;
  String? data;
  String? dataScheme;
  String? path;
}

class WebImagePicker {
  Future<ImageInfo?> pickImage() async {
    print('pickImage');
    final ImageInfo data = ImageInfo();
    final FileUploadInputElement input = FileUploadInputElement();
    document.body?.children.add(input);
    input..accept = 'image/*';
    input.click();
    await input.onChange.first;
    if (input.files == null || input.files!.isEmpty) return null;
    final reader = FileReader();
    reader.readAsDataUrl(input.files![0]);
    await reader.onLoad.first;
    final encoded = reader.result as String;
    // remove data:image/*;base64 preambule
    final stripped =
    encoded.replaceFirst(RegExp(r'data:image/[^;]+;base64,'), '');
    //final imageBase64 = base64.decode(stripped);
    final imageName = input.files?[0].name;
    final imagePath = input.files?[0].relativePath;
    data.name = imageName;
    data.data = stripped;
    data.dataScheme = encoded;
    data.path = imagePath;
    return data;
  }
}