import 'dart:async';
import 'dart:convert';
import 'dart:io' as file;
import 'package:flutter_share/flutter_share.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:invoiceninja_flutter/data/models/invoice_model.dart';
import 'package:flutter/foundation.dart';
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
import 'package:invoiceninja_flutter/utils/dialogs.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:native_pdf_view/native_pdf_view.dart';
import 'package:path_provider/path_provider.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:native_pdf_renderer/native_pdf_renderer.dart';
import 'package:invoiceninja_flutter/utils/web_stub.dart'
    if (dart.library.html) 'package:invoiceninja_flutter/utils/web.dart';

Future<Null> viewPdf(InvoiceEntity invoice, BuildContext context) async {
  /*
  final localization = AppLocalization.of(context);
  if (Platform.isIOS) {
    if (await canLaunch(invoice.invitationBorderlessLink)) {
      await launch(invoice.invitationBorderlessLink,
          forceSafariVC: true, forceWebView: true);
    } else {
      throw localization.anErrorOccurred;
    }

    return;
  }
  */

  showDialog<Scaffold>(
      context: context,
      builder: (BuildContext context) {
        return PDFScaffold(
          invoice: invoice,
        );
      });
}

class PDFScaffold extends StatefulWidget {
  const PDFScaffold({this.invoice});

  final InvoiceEntity invoice;

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

class _PDFScaffoldState extends State<PDFScaffold> {
  String _pdfString;
  List<PDFPageImage> _pdfImages;
  http.Response _response;

  @override
  void initState() {
    super.initState();

    _loadPDF(context, widget.invoice).then((response) {
      setState(() {
        _response = response;
      });
      if (kIsWeb) {
        renderWebPDF(
          context: context,
          invoice: widget.invoice,
          response: response,
        ).then((value) => setState(() {
              _pdfString = value;
              registerWebView(_pdfString);
            }));
      } else {
        renderMobilePDF(
          context: context,
          invoice: widget.invoice,
          response: response,
        ).then((value) => setState(() {
              _pdfImages = value;
            }));
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    final localization = AppLocalization.of(context);
    final invoice = widget.invoice;

    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
          icon: Icon(Icons.arrow_back),
          onPressed: () => Navigator.of(context).pop(),
        ),
        title: Text(localization.invoice + ' ' + (invoice.number ?? '')),
        actions: <Widget>[
          FlatButton(
            child: Text(
              localization.download,
              //style: TextStyle(color: Colors.white),
            ),
            onPressed: _response == null
                ? null
                : () async {
                    if (kIsWeb) {
                      launch(invoice.invitationDownloadLink,
                          forceSafariVC: false, forceWebView: false);
                    } else {
                      final directory = await getExternalStorageDirectory();
                      final filePath =
                          '${directory.path}/${invoice.invoiceId}.pdf';
                      final pdfData = file.File(filePath);
                      pdfData.writeAsBytes(_response.bodyBytes);
                      await FlutterShare.shareFile(
                          title: 'test.pdf',
                          //text: 'Example share text',
                          filePath: filePath);
                    }
                  },
          ),
        ],
      ),
      body: kIsWeb
          ? _pdfString == null
              ? LoadingIndicator()
              : _pdfString == ''
                  ? SizedBox()
                  : HtmlElementView(viewType: _pdfString)
          : _pdfImages == null
              ? LoadingIndicator()
              : _pdfImages.isEmpty
                  ? SizedBox()
                  : Container(
                      color: Colors.grey,
                      padding: const EdgeInsets.symmetric(vertical: 16),
                      child: _pdfImages.length == 1
                          ? Center(
                              child: Container(
                                color: Colors.white,
                                child: Image(
                                    image: MemoryImage(_pdfImages.first.bytes),
                                    height: double.infinity),
                              ),
                            )
                          : ListView(
                              scrollDirection: Axis.horizontal,
                              children: _pdfImages
                                  .map((page) => Row(
                                        children: <Widget>[
                                          Container(
                                            width: 20,
                                            height: double.infinity,
                                            color: Colors.grey,
                                          ),
                                          Container(
                                            color: Colors.white,
                                            child: ExtendedImage.memory(
                                              page.bytes,
                                              fit: BoxFit.fitHeight,
                                            ),
                                          ),
                                        ],
                                      ))
                                  .toList(),
                            ),
                    ),
    );
  }
}

Future<Response> _loadPDF(BuildContext context, InvoiceEntity invoice) async {
  final invitation = invoice.invitations.first;
  final url = invitation.downloadLink;
  final http.Response response = await http.Client().get(url);

  if (response.statusCode >= 400) {
    showErrorDialog(
        context: context,
        message: '${response.statusCode}: ${response.reasonPhrase}');
    return null;
  }

  return response;
}

Future<String> renderWebPDF({
  @required BuildContext context,
  @required http.Response response,
  @required InvoiceEntity invoice,
}) async {
  if (response == null) {
    return '';
  }

  return 'data:application/pdf;base64,' + base64Encode(response.bodyBytes);
}

Future<List<PDFPageImage>> renderMobilePDF({
  @required BuildContext context,
  @required http.Response response,
  @required InvoiceEntity invoice,
}) async {
  final List<PDFPageImage> pages = [];

  if (response == null) {
    return pages;
  }

  final document = await PDFDocument.openData(response.bodyBytes);
  for (var i = 1; i <= document.pagesCount; i++) {
    final page = await document.getPage(i);
    final pageImage = await page.render(width: page.width, height: page.height);
    pages.add(pageImage);
    page.close();
  }

  return pages;
}
