#!/usr/bin/env python3
# -*- coding: utf-8 -*-

##@file
# @brief exports an invoice from gnucash using a template file, see \ref py_invoice_export
# @ingroup python_bindings_examples
# @author Christoph Holtermann (c.holtermann (at) gmx.de)
# @date 2014-2018
#
# @details
# Input is a template file that will be filled with information from
# gnucash Invoices. Jinja2 templating engine is being used for this.
# Templates can be Latex, Html or anything.
#
# Example templates for german invoices:
# - Invoice.tex.tmpl
# - Invoice_2.tex.tmpl
#
# This is a sequel to latex_invoices.py that exported to a lco file
# to be imported into a LaTeX letter.
# The approach used here is not as dependent on external files and
# more modular as it allows to use arbitrary templates
#
# Doxygen docs:
# - https://code.gnucash.org/docs/MAINT or MASTER
# - see page \ref py_invoice_export
#
# Questions / Issues:
# - How much logic in the template, how much preprocessing in this file ?
# - Internationalization - currencies, formatting of numbers
# - Providing data of gnucash owner

try:
    import locale
    import os
    import sys
    import getopt
    import gnucash
    import str_methods
    import jinja2
    from gncinvoicefkt import *
    from gnucash import SessionOpenMode
except ImportError as import_error:
    print("Problem importing modules.")
    print(import_error)
    sys.exit(2)


class Usage(Exception):
    def __init__(self, msg):
        self.msg = msg


def main(argv=None):
    if argv is None:
        argv = sys.argv
    try:
        # default values
        prog_name = argv[0]
        ignore_lock = True
        filename_template = None
        filename_output = None
        no_output = False
        list_invoices = False
        invoice_number = None
        invoice_id = None
        filename_from_invoice = False
        output_path = None
        with_ipshell = False

        try:
            opts, args = getopt.getopt(argv[1:], "fhliI:t:o:OP:", ["help"])
        except getopt.error as msg:
            raise Usage(msg)

        for opt in opts:
            if opt[0] in ["-f"]:
                print("ignoring lock")
                ignore_lock = True
            if opt[0] in ["-h", "--help"]:
                raise Usage("Help:")
            if opt[0] in ["-I"]:
                invoice_id = opt[1]
                print("using invoice ID '" + str(invoice_id) + "'.")
            if opt[0] in ["-i"]:
                print("Using ipshell")
                with_ipshell = True
            if opt[0] in ["-o"]:
                filename_output = opt[1]
                print("using output file", filename_output)
            if opt[0] in ["-O"]:
                if filename_output:
                    print("given output filename will be overwritten,")
                print("creating output filename from Invoice data.")
                filename_from_invoice = True
            if opt[0] in ["-t"]:
                filename_template = opt[1]
                print("using template file", filename_template)
            if opt[0] in ["-l"]:
                list_invoices = True
                print("listing invoices")
            if opt[0] in ["-P"]:
                output_path = opt[1]
                print("output path is", output_path + ".")

        # Check for correct input
        if len(args) > 1:
            print("opts:", opts, "args:", args)
            raise Usage("Only one input possible !")
        if len(args) == 0:
            raise Usage("No input given !")
        input_url = args[0]

        # Check for correct template
        if not filename_template:
            no_output = True
            if not list_invoices:
                raise Usage("No template given !")

        # Check for output file
        if not (filename_output or filename_from_invoice):
            if filename_template:
                filename_output = filename_template + ".out"
                print("no output filename given, will be:", filename_output)

    except Usage as err:
        if err.msg == "Help:":
            retcode = 0
        else:
            print("Error:", err.msg, file=sys.stderr)
            print("for help use --help", file=sys.stderr)
            retcode = 2

        print()
        print("Usage:")
        print()
        print("Invoke with", prog_name, "gnucash_url.")
        print("where input is")
        print("   filename")
        print("or file://filename")
        print("or mysql://user:password@host/databasename")
        print()
        print("-f             force open = ignore lock (read only)")
        print("-l             list all invoices")
        print("-h or --help   for this help")
        print("-I ID          use invoice ID")
        print("-t filename    use filename as template file")
        print("-o filename    use filename as output file")
        print("-O             create output filename by date, owner and invoice number")
        print("-P path        path for output file. Overwrites path in -o option")

        return retcode

    # Try to open the given input
    try:
        print(
            "Opening", input_url, " (ignore-lock = read-only)." if ignore_lock else "."
        )
        session = gnucash.Session(
            input_url,
            SessionOpenMode.SESSION_READ_ONLY
            if ignore_lock
            else SessionOpenMode.SESSION_NORMAL_OPEN,
        )
    except Exception as exception:
        print("Problem opening input.")
        print(exception)
        return 2

    book = session.book
    root_account = book.get_root_account()
    comm_table = book.get_table()
    EUR = comm_table.lookup("CURRENCY", "EUR")

    invoice_list = get_all_invoices(book)

    if list_invoices:
        for number, invoice in enumerate(invoice_list):
            print(str(number) + ")")
            print(invoice)

    if not (no_output):

        if invoice_id:
            invoice = book.InvoiceLookupByID(invoice_id)
            if not invoice:
                print("ID not found.")
                return 2

        if invoice_number:
            invoice = invoice_list[invoice_number]

        print("Using the following invoice:")
        print(invoice)

        path_template = os.path.dirname(filename_template)
        filename_template_basename = os.path.basename(filename_template)

        loader = jinja2.FileSystemLoader(path_template)
        env = jinja2.Environment(loader=loader)
        template = env.get_template(filename_template_basename)

        # company = gnucash_business.Company(book.instance)

        output = template.render(invoice=invoice, locale=locale)  # , company=company)

        if filename_from_invoice:
            filename_date = invoice.GetDatePosted().strftime(
                "%Y-%m-%d"
            )  # something like 2014-11-01
            filename_owner_name = str(invoice.GetOwner().GetName())
            filename_invoice_id = str(invoice.GetID())
            filename_output = (
                filename_date
                + "_"
                + filename_owner_name
                + "_"
                + filename_invoice_id
                + ".tex"
            )

        if output_path:
            filename_output = os.path.join(
                output_path, os.path.basename(filename_output)
            )

        print("Writing output", filename_output, ".")
        with open(filename_output, "w") as f:
            f.write(output)

        if with_ipshell:
            import IPython

            IPython.embed()


if __name__ == "__main__":
    sys.exit(main())
