import gettext
import uno
import unohelper
from com.sun.star.task import XJobExecutor, XJob
import easymacro as app

import qrcode
import qrcode.image.svg as svg
from barcode import generate


ID_EXTENSION = 'net.elmau.zaz.BarCode'
SERVICE = ('com.sun.star.task.Job',)
TITLE = 'ZAZ BarCode'
QR = 'qrcode'


p, *_ = app.get_info_path(__file__)
path_locales = app.join(p, 'locales')
try:
    lang = gettext.translation('base', path_locales, languages=[app.LANG])
    lang.install()
    _ = lang.gettext
except Exception as e:
    from gettext import gettext as _
    app.error(e)


class Controllers(object):

    def __init__(self, dlg):
        self.d = dlg

    def button_action(self, event):
        if not self.d.listbox.value:
            self.d.listbox.set_focus()
            msg = _('Select barcode type')
            app.warning(msg, TITLE)
            return
        if not self.d.text.value.strip():
            self.d.text.set_focus()
            msg = _('Data field is mandatory')
            app.warning(msg, TITLE)
            return

        self.d.close(1)
        return


class ZAZBarCode(unohelper.Base, XJob, XJobExecutor):

    def __init__(self, ctx):
        self.ctx = ctx
        self._data = ''
        self._type = ''

    def execute(self, args):
        data = app.property_to_dict(args)

        if data['Type'] == QR:
            factory = svg.SvgImage
            img = qrcode.make(data['Data'], image_factory=factory)
            img.save(data['Path'])
        else:
            try:
                generate(data['Type'].lower(), data['Data'], output=data['Path'])
            except Exception as e:
                app.debug(str(e))
        return

    def trigger(self, args):
        self._type = args
        if args == 'ask' and not self._get_values():
            return

        doc = app.get_document()
        getattr(self, '_insert_in_{}'.format(doc.type))(doc)
        return

    def _create_code(self, tmp_file):
        if self._type == QR:
            factory = svg.SvgImage
            img = qrcode.make(self._data, image_factory=factory)
            img.save(tmp_file.name)
        else:
            try:
                generate(self._type, self._data, output=tmp_file)
            except Exception as e:
                return str(e)
        return ''

    def _get_values(self):
        self._type = ''
        dlg = self._create_dialog()
        if dlg.open():
            self._data = dlg.text.value.strip()
            self._type = dlg.listbox.value
            return True

        return False

    def _insert_in_calc(self, doc):
        cell = doc.get_cell()
        if not self._data:
            self._data = cell.value
            if not self._data:
                msg = _('Select data')
                self._show_error(msg)
                return

        tf = app.get_temp_file()
        result = self._create_code(tf)
        if result:
            tf.close()
            self._show_error(result)
            return

        cell = cell.offset()
        if app.IS_WIN:
            tf.close()
        cell.insert_image(tf.name)
        tf.close()
        return

    def _insert_in_writer(self, doc):
        doc = app.get_document()
        sel = app.get_selection()
        if not self._data:
            self._data = sel.string
            if not self._data:
                msg = _('Select data')
                self._show_error(msg)
                return

        tf = app.get_temp_file()
        result = self._create_code(tf)
        if result:
            tf.close()
            self._show_error(result)
            return

        if app.IS_WIN:
            tf.close()
        doc.insert_image(tf.name)
        tf.close()
        return

    def _insert_in_draw(self, doc):
        tf = app.get_temp_file()
        result = self._create_code(tf)
        if result:
            tf.close()
            self._show_error(result)
            return

        if app.IS_WIN:
            tf.close()
        doc.insert_image(tf.name)
        tf.close()
        return

    def _insert_in_impress(self, doc):
        self._insert_in_draw(doc)
        return

    def _show_error(self, error):
        msg = _('Error in: {}\n\n{}').format(self._type, error)
        app.error(error)
        app.errorbox(msg, TITLE)
        return

    def _create_dialog(self):
        args = {
            'Name': 'dialog',
            'Title': TITLE,
            'Width': 160,
            'Height': 160,
        }
        dlg = app.create_dialog(args)
        dlg.events = Controllers(dlg)

        args = {
            'Type': 'Label',
            'Name': 'lbl_barcode',
            'Label': _('~Select barcode type'),
            'Width': 70,
            'Height': 15,
            'X': 10,
            'Y': 10,
            'VerticalAlign': 1,
        }
        dlg.add_control(args)

        args = {
            'Type': 'Label',
            'Name': 'lbl_data',
            'Label': _('~Capture data for barcode'),
            'Width': 100,
            'Height': 15,
            'VerticalAlign': 1,
        }
        dlg.add_control(args)

        args = {
            'Type': 'ListBox',
            'Name': 'listbox',
            'Width': 65,
            'Height': 15,
            'Dropdown': True,
        }
        dlg.add_control(args)
        data = ('code39', 'code128', 'ean', 'ean8', 'ean13', 'gs1', 'gtin',
            'isbn', 'isbn10', 'isbn13', 'issn', 'jan', 'pzn', 'upc', 'upca',
            'qrcode')
        dlg.listbox.data = data

        args = {
            'Type': 'Text',
            'Name': 'text',
            'Width': 140,
            'Height': 75,
            'MultiLine': True,
            'VScroll': True,
        }
        dlg.add_control(args)

        args = {
            'Type': 'Button',
            'Name': 'button',
            'Label': _('~Insert Barcode'),
            'Width': 60,
            'Height': 15,
        }
        dlg.add_control(args)

        dlg.listbox.move(dlg.lbl_barcode, 5, 0)
        dlg.lbl_data.move(dlg.lbl_barcode)
        dlg.text.move(dlg.lbl_data)
        dlg.button.move(dlg.text, 0, 10)
        dlg.button.center()

        return dlg


g_ImplementationHelper = unohelper.ImplementationHelper()
g_ImplementationHelper.addImplementation(ZAZBarCode, ID_EXTENSION, SERVICE)
