// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:flutter/material.dart';
import 'dart:io';
import 'dart:async';

import 'package:jni/jni.dart';
import 'package:path/path.dart';

import 'package:pdfbox_plugin/pdfbox_plugin.dart';

Stream<String> files(String dir) => Directory(dir).list().map((e) => e.path);

const jarError = 'No JAR files were found.\n'
    'Run `dart run jnigen:download_maven_jars --config jnigen.yaml` '
    'in plugin directory.\n'
    'Alternatively, regenerate JNI bindings in plugin directory, which will '
    'automatically download the JAR files.';

void main() {
  if (!Platform.isAndroid) {
    // Assuming application is run from example/ folder
    // It's required to manually provide the JAR files as classpath when
    // spawning the JVM.
    const jarDir = '../mvn_jar/';
    List<String> jars;
    try {
      jars = Directory(jarDir)
          .listSync()
          .map((e) => e.path)
          .where((path) => path.endsWith('.jar'))
          .toList();
    } on OSError catch (_) {
      stderr.writeln(jarError);
      return;
    }
    if (jars.isEmpty) {
      stderr.writeln(jarError);
      return;
    }
    Jni.spawn(classPath: jars);
  }
  runApp(const PDFInfoApp());
}

class PDFInfoApp extends StatefulWidget {
  const PDFInfoApp({super.key});

  @override
  PDFInfoAppState createState() => PDFInfoAppState();
}

class PDFInfoAppState extends State<PDFInfoApp> {
  bool _isLoading = true;
  String _dir = '.';
  List<String> _pdfs = [];
  List<String> _dirs = [];

  void setDir(String dir) async {
    final pdfs = <String>[];
    final dirs = <String>[];

    setState(() => _isLoading = true);

    await for (var item in Directory(dir).list()) {
      final isDir = (await item.stat()).type == FileSystemEntityType.directory;
      if (item.path.endsWith('.pdf') && !isDir) {
        pdfs.add(item.path);
      } else if (isDir) {
        dirs.add(item.path);
      }
    }
    setState(() {
      _isLoading = false;
      _dir = dir;
      _pdfs = pdfs;
      _dirs = dirs;
    });
  }

  @override
  void initState() {
    super.initState();
    final dir = Platform.environment['HOME'] ?? '.';
    setDir(dir);
  }

  @override
  Widget build(BuildContext context) {
    final dirBaseName = basename(_dir);
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('PDF Info: $dirBaseName'),
        ),
        body: SingleChildScrollView(
          child: Container(
              padding: const EdgeInsets.all(10),
              child: _isLoading
                  ? const Text('loading...')
                  : Table(border: TableBorder.all(), children: [
                      TableRow(children: [
                        for (var heading in ['File', 'Title', 'Pages'])
                          TableCell(
                              child: _pad(Text(heading,
                                  style: const TextStyle(
                                      fontSize: 16,
                                      decoration: TextDecoration.underline)))),
                      ]),
                      TableRow(children: [
                        TableCell(
                          child: _pad(
                            InkWell(
                              child: const Text('..'),
                              onTap: () => setDir(dirname(_dir)),
                            ),
                          ),
                        ),
                        const TableCell(child: Text('')),
                        const TableCell(child: Text('')),
                      ]),
                      for (var dir in _dirs) _dirTile(basename(dir)),
                      for (var pdfname in _pdfs)
                        _pdfInfo(PDFFileInfo.usingPDFBox(pdfname)),
                    ])),
        ),
      ),
    );
  }

  TableRow _dirTile(String target) {
    return TableRow(children: [
      TableCell(
        child: _pad(
          InkWell(
            onTap: () => setDir(join(_dir, target)),
            child: Text(
              target,
              style: const TextStyle(fontWeight: FontWeight.bold),
            ),
          ),
        ),
      ),
      const TableCell(child: Text('-')),
      const TableCell(child: Text('-')),
    ]);
  }
}

// It's generally a good practice to separate JNI calls from UI / model code.
class PDFFileInfo {
  String filename;
  late String author, subject, title;
  late int numPages;

  /// Converts JString to dart string and deletes the original.
  /// Also handles the case where the underlying string is Null.
  String _fromJavaStr(JString jstr) {
    if (jstr.reference.pointer == nullptr) {
      return '(null)';
    }
    return jstr.toDartString(releaseOriginal: true);
  }

  PDFFileInfo.usingPDFBox(this.filename) {
    // Since java.io is not directly available, use package:jni API to
    // create a java.io.File object.
    final inputFile =
        Jni.newInstance("java/io/File", "(Ljava/lang/String;)V", [filename]);
    // Static method call PDDocument.load -> PDDocument
    final pdf = PDDocument.load(inputFile);
    // Instance method call getNumberOfPages() -> int
    numPages = pdf.getNumberOfPages();
    // Instance method that returns an object
    final info = pdf.getDocumentInformation();

    /// java.lang.String is a special case and is mapped to JlString which is
    /// a subclass of JlObject.
    author = _fromJavaStr(info.getAuthor());
    title = _fromJavaStr(info.getTitle());
    subject = _fromJavaStr(info.getSubject());

    pdf.close();
  }
}

Padding _pad(Widget w) => Padding(
    padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: w);

TableRow _pdfInfo(PDFFileInfo info) {
  return TableRow(children: [
    TableCell(
        child: _pad(Text(basename(info.filename),
            style: const TextStyle(fontWeight: FontWeight.bold)))),
    TableCell(child: _pad(Text(info.title))),
    TableCell(
        child: _pad(Text(info.numPages.toString(),
            style: const TextStyle(color: Colors.grey)))),
  ]);
}
