import 'dart:async';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_tesseract_ocr/flutter_tesseract_ocr.dart';
import 'package:prasule/main.dart';
import 'package:prasule/network/tessdata.dart';
import 'package:prasule/pw/platformbutton.dart';

/// Used to manage downloaded Tessdata for OCR
class TessdataListView extends StatefulWidget {
  /// Used to manage downloaded Tessdata for OCR
  const TessdataListView({super.key});

  @override
  State<TessdataListView> createState() => _TessdataListViewState();
}

class _TessdataListViewState extends State<TessdataListView> {
  final _tessdata = [
    {"eng": true},
  ];
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    loadAllTessdata();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(AppLocalizations.of(context).ocrData)),
      body: Center(
        child: SizedBox(
          width: MediaQuery.of(context).size.width * 0.9,
          height: MediaQuery.of(context).size.height,
          child: (_tessdata.length == 1)
              ? const Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    SizedBox(
                      width: 80,
                      height: 80,
                      child: CircularProgressIndicator(),
                    ),
                  ],
                )
              : ListView.builder(
                  itemBuilder: (context, i) => ListTile(
                    title: Text(_tessdata[i].keys.first),
                    trailing: TextButton(
                      child: Text(
                        _tessdata[i][_tessdata[i].keys.first]!
                            ? AppLocalizations.of(context).downloaded
                            : AppLocalizations.of(context).download,
                      ),
                      onPressed: () async {
                        final lang = _tessdata[i].keys.first;
                        if (_tessdata[i][lang]!) {
                          // deleting data
                          await showAdaptiveDialog<void>(
                            context: context,
                            builder: (context) => AlertDialog.adaptive(
                              title:
                                  Text(AppLocalizations.of(context).sureDialog),
                              content: Text(
                                AppLocalizations.of(context).deleteOcr(lang),
                              ),
                              actions: [
                                PlatformButton(
                                  text: AppLocalizations.of(context).yes,
                                  onPressed: () async {
                                    await TessdataApi.deleteData(lang);
                                    _tessdata[i][lang] = true;
                                    if (context.mounted) {
                                      Navigator.of(context).pop();
                                    }
                                  },
                                ),
                                PlatformButton(
                                  text: AppLocalizations.of(context).no,
                                  onPressed: () {
                                    Navigator.of(context).pop();
                                  },
                                ),
                              ],
                            ),
                          );
                          setState(() {});
                          return;
                        }

                        // TODO: handle wifi errors
                        //* downloading traineddata
                        final progressStream = StreamController<double>();

                        unawaited(
                          showAdaptiveDialog(
                            context: context,
                            builder: (c) => AlertDialog.adaptive(
                              title: Text(
                                AppLocalizations.of(context)
                                    .langDownloadDialog(lang),
                              ),
                              content: StreamBuilder(
                                builder: (context, snapshot) {
                                  if (snapshot.connectionState ==
                                      ConnectionState.waiting) {
                                    return const CircularProgressIndicator();
                                  }
                                  if (snapshot.hasError) {
                                    return const Text("Error");
                                  }
                                  return Text(
                                    AppLocalizations.of(context)
                                        .langDownloadProgress(snapshot.data!),
                                  );
                                },
                                stream: progressStream.stream,
                              ),
                            ),
                          ),
                        );
                        await TessdataApi.downloadData(
                          lang,
                          callback: (a, b) {
                            if (progressStream.isClosed) return;
                            final p = a / b * 1000;
                            progressStream.add(p.roundToDouble() / 10);
                            if (p / 10 >= 100) {
                              logger.i("Done");
                              Navigator.of(context, rootNavigator: true)
                                  .pop("dialog");
                              _tessdata[i][lang] = true;
                              progressStream.close();
                            }
                            setState(() {});
                          },
                        );
                      },
                    ),
                  ),
                  itemCount: _tessdata.length,
                ),
        ),
      ),
    );
  }

  /// Used to find which `.traineddata` is already downloaded and which not
  /// so we can show it to the user
  Future<void> loadAllTessdata() async {
    final tessDir = Directory(await FlutterTesseractOcr.getTessdataPath());
    if (!tessDir.existsSync()) tessDir.createSync(recursive: true);
    final d = await TessdataApi.getAvailableData();
    final dataStatus = <Map<String, bool>>[];
    for (final data in d) {
      final e = <String, bool>{};
      e[data] = false;
      dataStatus.add(e);
    }
    final appDir = tessDir.listSync();
    for (final file in appDir) {
      if (file is! File ||
          !file.path.endsWith("traineddata") ||
          file.path.endsWith("eng.traineddata")) continue;
      logger.i(file.path);
      final filename = file.path.split("/").last;
      dataStatus[dataStatus.indexWhere(
        (element) =>
            element.keys.first == filename.replaceAll(".traineddata", ""),
      )][filename.replaceAll(".traineddata", "")] = true;
    }
    _tessdata.addAll(dataStatus);
    setState(() {});
  }
}
