from django.views import generic
from .models import Container, ContainerType
import logging, json, re
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin

logger = logging.getLogger(__name__)


class ContainerListView(LoginRequiredMixin, generic.ListView):
    model = Container
    template_name = 'container/container_list.html'
    context_object_name = 'container_list'
    paginate_by = 20

    '''
    def get_queryset(self):
        # Return the last five created containers
        return Container.objects.order_by('-created_ts')[:5]
    '''


class ContainerCreateView(LoginRequiredMixin, generic.CreateView):
    model = Container
    fields = ['named_id', 'description', 'color', 'container_type']
    success_url = '/container/'

    def form_valid(self, form):
        if not form.instance.named_id.startswith('C-'):
            form.instance.named_id = 'C-' + form.instance.named_id
        form.instance.changed_by = self.request.user
        form.instance.created_by = self.request.user
        return super().form_valid(form)


class ContainerImportView(LoginRequiredMixin, generic.TemplateView):
    template_name = 'container_import.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        if 'start_import' in self.request.POST:
            context['import_file'] = self.request.POST['import_file']

        return context

    def get(self, *args, **kwargs):
        return super().get(self.request, args, **kwargs)

    def post(self):
        return super().render_to_response(self)


class ContainerUpdateView(LoginRequiredMixin, generic.UpdateView):
    model = Container
    # template_name = 'container/detail.html'
    fields = ['named_id', 'description', 'color', 'container_type']
    success_url = "/container/"

    def form_valid(self, form):
        if not form.instance.named_id.startswith('C-'):
            form.instance.named_id = 'C-' + form.instance.named_id
        form.instance.changed_by = self.request.user
        return super().form_valid(form)


class ContainerDetailView(LoginRequiredMixin, generic.DetailView):
    model = Container


class ContainerDeleteView(LoginRequiredMixin, generic.DetailView):
    model = Container


class ContainerPrintLabelView(LoginRequiredMixin, generic.DetailView):
    model = Container
    template_name = 'container/container_print_label.html'

    def get(self, request, **kwargs):
        context = super().get(request, **kwargs)
        '''
        label_writer = LabelWriter(
            "container/templates/label/container_label.html",
            default_stylesheets=("container/templates/label/label_style.css",)
        )
        label_writer.write_labels([dict(named_id=kwargs['pk'], id=kwargs['pk'])], target="container_label.pdf")
        '''
        return context

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        num_copies = int(self.request.GET['num_copies']) if 'num_copies' in self.request.GET else 0
        context['num_copies'] = num_copies
        context['logs'] = ['creating label for container ' + self.object.named_id]
        from labelprinter.labels import container_label, pil_to_html_imgdata
        container_description = self.object.container_type.named_id
        if len(self.object.container_type.description) > 0:
            container_description += ': ' + self.object.container_type.description
        if len(self.object.description) > 0:
            container_description_line2 = self.object.description
        label_image = container_label(
            self.object.named_id,
            fmt='image',
            description=container_description,
            description_line2=container_description_line2,
            writer_options={'font_size': 14,
                            'module_height': 10.0,
                            'quiet_zone': 4.5,
                            'text': 'This is the text',
                            'text_distance': 1.0
                            })
        context['barcode_img'] = pil_to_html_imgdata(label_image, fmt='PNG')
        context['logs'].append('Image created')
        if num_copies > 0:
            # from brother_ql.devicedependent import models, label_type_specs, label_sizes
            # from brother_ql.devicedependent import ENDLESS_LABEL, DIE_CUT_LABEL, ROUND_DIE_CUT_LABEL
            from brother_ql import BrotherQLRaster, create_label
            from brother_ql.backends import backend_factory, guess_backend

            try:
                with open('config.json', encoding='utf-8') as fh:
                    config = json.load(fh)
            except FileNotFoundError as e:
                with open('config.example.json', encoding='utf-8') as fh:
                    config = json.load(fh)

            # LABEL_SIZES = [(name, label_type_specs[name]['name']) for name in label_sizes]

            '''
            if context['kind'] == ENDLESS_LABEL:
                rotate = 0 if context['orientation'] == 'standard' else 90
            elif context['kind'] in (ROUND_DIE_CUT_LABEL, DIE_CUT_LABEL):
                rotate = 'auto'
            red = False
            if 'red' in context['label_size']:
                red = True
            '''

            qlr = BrotherQLRaster(config['PRINTER']['MODEL'])
            context['logs'].append('Connected to printer')
            create_label(qlr, image=label_image, label_size='62', red=False, threshold=1,
                         cut=True, rotate='auto')
            context['logs'].append('Created raster information')

            try:
                selected_backend = guess_backend(config['PRINTER']['PRINTER'])
            except ValueError:
                context['messages'].append(
                    "Could't guess the backend to use from the printer string descriptor (config PRINTER.PRINTER)")
            context['logs'].append('Backend found: ' + selected_backend)
            try:
                be_class = backend_factory(selected_backend)['backend_class']
                be = be_class(config['PRINTER']['PRINTER'])
                context['logs'].append('Got backend driver')
                for i in range(1, num_copies):
                    be.write(qlr.data)

                context['logs'].append('Data sent to printer')
                be.dispose()
                del be
            except Exception as e:
                context['logs'].append('Exception: ' + str(e))
                logger.warning('Exception happened: %s', e)

        context['logs'].append('Finished printing label')

        return context


class ContainerTypeListView(LoginRequiredMixin, generic.ListView):
    template_name = 'container/container_type_list.html'
    context_object_name = 'container_type_list'
    paginate_by = 20
    model = ContainerType

    '''
    def get_queryset(self):
        # Return the last five created container types
        return ContainerType.objects.order_by('-created_ts')[:5]
    '''


class ContainerTypeDetailView(LoginRequiredMixin, generic.DetailView):
    model = ContainerType
    context_object_name = 'container_type'
    template_name = 'container/container_type_detail.html'


class ContainerTypeCreateView(LoginRequiredMixin, generic.CreateView):
    model = ContainerType
    template_name = 'container/container_type_form.html'
    fields = ['named_id', 'description', 'width', 'length', 'height', 'inner_width', 'inner_length', 'inner_height',
              'has_cover', 'contains_container']

    def form_valid(self, form):
        form.instance.changed_by = self.request.user
        form.instance.created_by = self.request.user
        return super().form_valid(form)


class ContainerTypeUpdateView(LoginRequiredMixin, generic.UpdateView):
    model = ContainerType
    # template_name = 'container/detail.html'
    template_name = 'container/container_type_form.html'
    fields = ['named_id', 'description', 'width', 'length', 'height', 'inner_width', 'inner_length', 'inner_height',
              'has_cover', 'contains_container']

    def form_valid(self, form):
        form.instance.changed_by = self.request.user
        return super().form_valid(form)


class ContainerTypeDeleteView(LoginRequiredMixin, generic.DetailView):
    model = ContainerType


class ContainerTypeImportView(LoginRequiredMixin, generic.TemplateView):
    template_name = 'container/container_type_import.html'

    def get_context_data(self, **kwargs):
        # print('get_context_data')
        context = super().get_context_data(**kwargs)
        context['import_file'] = self.request.FILES['import_file'] if 'import_file' in self.request.FILES else ''
        if context['import_file'] != '':
            # if 'show-cmd' in self.request.POST:
                # print('Show button pressed')
            context['filename'] = self.request.FILES['import_file'].name
            context['filesize'] = self.request.FILES['import_file'].size
            context['content_type'] = self.request.FILES['import_file'].content_type

            import openpyxl as excel
            workbook = excel.open(self.request.FILES['import_file'])
            sheet = workbook.active
            sheet_data = []
            row_num = 1
            for row in sheet.values:
                row_data = [row_num]
                row_num = row_num + 1
                for col in row:
                    row_data.append(col if col is not None else '')
                sheet_data.append(row_data)

            context['excel_data'] = sheet_data

        return context

    def post(self, request):
        # print('POST method executed')
        if 'import-cmd' in request.POST:
            # print('import button pressed')
            first_data_row = int(request.POST['first_data_row']) if 'first_data_row' in request.POST else 0
            # context['first_data_row'] = first_data_row
            # print('first_data_row=%d' % first_data_row)
            p = re.compile(r'^data_(\d+)_(\d+)$')
            import_data = {}
            for key in request.POST:
                match = p.match(key)
                if match:
                    key_row, key_col = match.group(1, 2)
                    row_num = int(key_row)
                    col_num = int(key_col)
                    if row_num >= first_data_row:
                        value = request.POST[key]
                        if row_num not in import_data:
                            import_data[row_num] = {}
                        import_data[row_num][col_num] = value
                        # print('Value row=%d, col=%d, value=%s' % (row_num, col_num, value))
            for col in import_data:
                c7 = import_data[col][7]
                c12 = import_data[col][12]
                has_cover = True if c7 == 'j' or c7 == 'J' or c7 == 'y' or c7 == 'Y' else False
                contains_container = True if c12 == 'j' or c12 == 'J' or c12 == 'y' or c12 == 'Y' else False
                try:
                    ct = ContainerType.objects.get(named_id=import_data[col][2])
                    # Update entry
                    ct.description = None if import_data[col][3] == '' else import_data[col][3]
                    ct.width = None if import_data[col][4] == '' else import_data[col][4]
                    ct.length = None if import_data[col][5] == '' else import_data[col][5]
                    ct.height = None if import_data[col][6] == '' else import_data[col][6]
                    ct.inner_width = None if import_data[col][8] == '' else import_data[col][8]
                    ct.inner_length = None if import_data[col][9] == '' else import_data[col][9]
                    ct.inner_height = None if import_data[col][10] == '' else import_data[col][10]
                    ct.has_cover = has_cover
                    ct.contains_container = contains_container
                    ct.changed_by_id = request.user.id
                    # print('Updated %s' % import_data[col][2])
                except ObjectDoesNotExist:
                    # Create a new entry
                    ct = ContainerType.objects.create(
                        named_id=import_data[col][2],
                        description=None if import_data[col][3] == '' else import_data[col][3],
                        width=None if import_data[col][4] == '' else import_data[col][4],
                        length=None if import_data[col][5] == '' else import_data[col][5],
                        height=None if import_data[col][6] == '' else import_data[col][6],
                        inner_width=None if import_data[col][8] == '' else import_data[col][8],
                        inner_length=None if import_data[col][9] == '' else import_data[col][9],
                        inner_height=None if import_data[col][10] == '' else import_data[col][10],
                        has_cover=has_cover,
                        contains_container=contains_container,
                        created_by_id=request.user.id,
                        changed_by_id=request.user.id
                    )
                    # print('Created %s' % import_data[col][2])
                finally:
                    ct.save()
        return super().get(request)
