// ignore_for_file: depend_on_referenced_packages, deprecated_member_use

import 'dart:io';
import 'dart:ui';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart' as m;
import 'package:flutter/services.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:demand/presentation/style/style.dart';
import 'package:path_provider/path_provider.dart';
import 'package:http/http.dart' as http;
import 'package:image/image.dart' as img;
import 'dart:async';
import 'dart:math';

import '../../presentation/app_assets.dart';

class ImageCropperForMarker {
  Future<BitmapDescriptor> getMarkerBitmap(int size, {String? text}) async {
    if (kIsWeb) size = (size / 2).floor();

    final PictureRecorder pictureRecorder = PictureRecorder();
    final Canvas canvas = Canvas(pictureRecorder);
    final Paint paint1 = Paint()..color = CustomStyle.black;
    final Paint paint2 = Paint()..color = CustomStyle.white;

    canvas.drawCircle(Offset(size / 2, size / 2), size / 2.0, paint1);
    canvas.drawCircle(Offset(size / 2, size / 2), size / 2.2, paint2);
    canvas.drawCircle(Offset(size / 2, size / 2), size / 2.8, paint1);

    if (text != null) {
      m.TextPainter painter = m.TextPainter(textDirection: TextDirection.ltr);
      painter.text = m.TextSpan(
        text: text,
        style: m.TextStyle(
          fontSize: size / 3,
          color: m.Colors.white,
          fontWeight: FontWeight.normal,
        ),
      );
      painter.layout();
      painter.paint(
        canvas,
        Offset(size / 2 - painter.width / 2, size / 2 - painter.height / 2),
      );
    }

    final img = await pictureRecorder.endRecording().toImage(size, size);
    final data = await img.toByteData(format: ImageByteFormat.png) as ByteData;

    return BitmapDescriptor.fromBytes(data.buffer.asUint8List());
  }

  Future<BitmapDescriptor> resizeAndCircle(String? imageURL, int size) async {
    final File imageFile = await urlToFile(imageURL);
    final Uint8List byteData = imageFile.readAsBytesSync();
    final Image image = await _resizeAndConvertImage(byteData, size, size);
    return _paintToCanvas(image, Size.zero);
  }

  Future<File> imageToFile({String? imageName, String? ext}) async {
    var bytes = await rootBundle.load('assets/$imageName.$ext');
    String tempPath = (await getTemporaryDirectory()).path;
    File file = File('$tempPath/app_logo.png');
    await file.writeAsBytes(
      bytes.buffer.asUint8List(bytes.offsetInBytes, bytes.lengthInBytes),
    );
    return file;
  }

  Future<File> urlToFile(String? imageUrl) async {
    final rd = Random();
    final Directory tempDir = await getTemporaryDirectory();
    final String tempPath = tempDir.path;
    try {
      final File file = File('$tempPath${rd.nextInt(100)}.png');
      final http.Response response = await http.get(Uri.parse(imageUrl ?? ''));
      await file.writeAsBytes(response.bodyBytes);
      return file;
    } catch (e) {
      return await imageToFile(imageName: "images/app_logo", ext: "png");
    }
  }

  Future<Image> _resizeAndConvertImage(
    Uint8List? data,
    int height,
    int width,
  ) async {
    ByteData bytes = await rootBundle.load(Assets.imagesAppLogo);
    final img.Image? baseSizeImage = img.decodeImage(
      data ?? bytes.buffer.asUint8List(),
    );
    final img.Image? newSizeImage = img.decodeImage(bytes.buffer.asUint8List());

    final img.Image resizeImage = img.copyResize(
      baseSizeImage ?? newSizeImage!,
      height: height,
      width: width,
    );
    final Codec codec = await instantiateImageCodec(
      Uint8List.fromList(img.encodePng(resizeImage)),
    );
    final FrameInfo frameInfo = await codec.getNextFrame();
    return frameInfo.image;
  }

  Future<BitmapDescriptor> _paintToCanvas(Image image, Size size) async {
    final pictureRecorder = PictureRecorder();
    final canvas = Canvas(pictureRecorder);
    final paint = Paint();
    paint.isAntiAlias = true;

    _performCircleCrop(image, size, canvas);

    final recordedPicture = pictureRecorder.endRecording();
    Image img = await recordedPicture.toImage(image.width, image.height);
    final byteData = await img.toByteData(format: ImageByteFormat.png);
    final buffer = byteData?.buffer.asUint8List();

    return BitmapDescriptor.fromBytes(buffer!);
  }

  Canvas _performCircleCrop(Image image, Size size, Canvas canvas) {
    Paint paint = Paint();
    canvas.drawCircle(const Offset(0, 0), 0, paint);

    double drawImageWidth = 0;
    double drawImageHeight = 0;
    double imageW = image.width.toDouble();
    double imageH = image.height.toDouble();
    final Path path = Path()
      ..addOval(
        Rect.fromLTRB(
          drawImageWidth + imageW / 8,
          drawImageHeight + imageH / 8,
          imageW - imageW / 8,
          imageH - imageH / 8,
        ),
      );
    canvas.drawRRect(
      RRect.fromRectAndRadius(
        Rect.fromLTRB(drawImageWidth, drawImageHeight, imageW, imageH),
        Radius.circular(imageW / 4),
      ),
      Paint()
        ..color = CustomStyle.white.withValues(alpha: 0.75)
        ..imageFilter = ImageFilter.blur(sigmaX: 7, sigmaY: 7),
    );
    canvas.clipPath(path);
    canvas.drawImage(image, Offset(drawImageWidth, drawImageHeight), Paint());
    return canvas;
  }
}
