import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:absenkuv3/UI/Template/Camera/Bloc/CameraBloc.dart';
import 'package:absenkuv3/UI/Template/Camera/Model/CameraModel.dart';
import 'package:absenkuv3/UI/Template/Camera/UI/HalamanCamera.dart';
import 'package:absenkuv3/UI/Template/MultiImagePicker/Model/MultiImagePickerModel.dart';
import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart' as path_provider;
import 'package:image/image.dart' as resizeImage;

abstract class MultiImagePickerEvent {}

class PickImage extends MultiImagePickerEvent {
  final BuildContext context;
  bool absensi;
  bool fromCamera;
  String? pluginCamera;
  String defaultCamera;
  PickImage(this.context, this.absensi,
      {this.fromCamera = false,
      this.defaultCamera = 'front',
      this.pluginCamera = '1'});
}

class PickImageSingle extends MultiImagePickerEvent {
  BuildContext context;
  bool absensi;
  bool fromCamera;
  String? pluginCamera;
  String defaultCamera;
  PickImageSingle(this.context, this.absensi,
      {this.fromCamera = false,
      this.defaultCamera = 'front',
      this.pluginCamera = '1'});
}

class DeleteImage extends MultiImagePickerEvent {
  MultiImagePickerModel data;
  DeleteImage(this.data);
}

abstract class MultiImagePickerState {
    // List<MultiImagePickerModel>? listData;

}

class MultiImageSuccessState extends MultiImagePickerState {
  List<MultiImagePickerModel> listData;
  MultiImageSuccessState(this.listData);
}

class MultiImageProgressState extends MultiImagePickerState {}

class MultiImagePickerBloc
    extends Bloc<MultiImagePickerEvent, MultiImagePickerState> {
  List<MultiImagePickerModel> listData = <MultiImagePickerModel>[];

  MultiImagePickerBloc(MultiImagePickerState initialState)
      : super(initialState);

  @override
  Stream<MultiImagePickerState> mapEventToState(
      MultiImagePickerEvent event) async* {
    // TODO: implement mapEventToState
    if (event is PickImage) {
      if (event.fromCamera && event.pluginCamera == '1') {
        //MASUK KE HALAMAN PLUGIN CAMERA
        CameraModel? cameraModel = await Navigator.push<CameraModel>(
            event.context,
            MaterialPageRoute(
              builder: (_) => BlocProvider(
                create: (BuildContext context) =>
                    CameraBloc(InitializeCameraProgress()),
                child: CameraApp(
                  'Ambil Foto',
                  event.absensi,
                  defaultCamera: event.defaultCamera,
                ),
              ),
            ));
        listData.add(MultiImagePickerModel(
            base64Encode(File(cameraModel!.path).readAsBytesSync()),
            cameraModel.path));
      } else {
        final picker = ImagePicker();
        final pickedFile = await picker.pickImage(
            source: event.fromCamera ? ImageSource.camera : ImageSource.gallery,
            imageQuality: 20);
        if (pickedFile != null) {
          final dir = await path_provider.getTemporaryDirectory();
          File fileCompressed = File(pickedFile.path);
          resizeImage.Image? imageNew =
              resizeImage.decodeImage(fileCompressed.readAsBytesSync());
          resizeImage.Image? thumbnail =
              resizeImage.copyResize(imageNew!, height: 800);
          fileCompressed = new File(pickedFile.path)
            ..writeAsBytesSync(resizeImage.encodePng(thumbnail));
          fileCompressed = await testCompressAndGetFile(File(pickedFile.path),
              "${dir.absolute.path}/${DateTime.now()}.jpg");
          listData.add(MultiImagePickerModel(
              base64Encode(File(fileCompressed.path).readAsBytesSync()),
              fileCompressed.path));
        }
      }
      yield MultiImageSuccessState(listData);
    } else if (event is PickImageSingle) {
      if (event.fromCamera && event.pluginCamera == '1') {
        //MASUK KE HALAMAN PLUGIN CAMERA
        CameraModel? cameraModel = await Navigator.push<CameraModel>(
            event.context,
            MaterialPageRoute(
              builder: (_) => BlocProvider(
                create: (BuildContext context) =>
                    CameraBloc(InitializeCameraProgress()),
                child: CameraApp(
                  'Ambil Foto',
                  event.absensi,
                  defaultCamera: event.defaultCamera,
                ),
              ),
            ));
        if (cameraModel != null) {
          listData.clear();
          listData.add(MultiImagePickerModel(
              base64Encode(File(cameraModel.path).readAsBytesSync()),
              cameraModel.path));
        }
      } else {
        final picker = ImagePicker();
        final pickedFile = await picker.pickImage(
            source: event.fromCamera ? ImageSource.camera : ImageSource.gallery,
            imageQuality: 20);
        if (pickedFile != null) {
          final dir = await path_provider.getTemporaryDirectory();
          File fileCompressed = File(pickedFile.path);
          resizeImage.Image? imageNew =
              resizeImage.decodeImage(fileCompressed.readAsBytesSync());
          resizeImage.Image? thumbnail =
              resizeImage.copyResize(imageNew!, height: 800);
          fileCompressed = new File(pickedFile.path)
            ..writeAsBytesSync(resizeImage.encodePng(thumbnail));
          fileCompressed = await testCompressAndGetFile(File(pickedFile.path),
              "${dir.absolute.path}/${DateTime.now()}.jpg");
          listData.clear();
          listData.add(MultiImagePickerModel(
              base64Encode(File(fileCompressed.path).readAsBytesSync()),
              fileCompressed.path));
        }
      }
      if (listData.length > 0) yield MultiImageSuccessState(listData);
    } else if (event is DeleteImage) {
      listData.remove(event.data);
      yield MultiImageSuccessState(listData);
    }
  }

  Future<File> testCompressAndGetFile(File file, String targetPath) async {
    final result = await FlutterImageCompress.compressAndGetFile(
      file.absolute.path,
      targetPath,
      quality: 75,
    );

    if (result == null) {
      throw Exception('Compression failed');
    }

    print(file.lengthSync());

    // Convert XFile to File
    return File(result.path);
  }
}
