from django import forms
from django.forms import widgets
from django.core.exceptions import ValidationError
from parts import models as parts_models
from shimatta_modules.EngineeringNumberConverter import EngineeringNumberConverter


class AutoCompleteWidget(widgets.TextInput):
    template_name = 'widgets/autrocomplete-foreign-key.html'

class AutocompleteForeingKeyField(forms.UUIDField):
    def __init__(self, foreign_model=None, api_search_url=None, autocomplete_media_div=False, **kwargs):
        kwargs['widget'] = AutoCompleteWidget
        super().__init__(**kwargs)

class MyTestForm(forms.Form):
    pass

class AddSubStorageForm(forms.Form):
    storage_name = forms.CharField(label="storage_name", initial='')
    responsible = forms.CharField(label='responsible_user')

class DeleteStockForm(forms.Form):
    stock_uuid = forms.UUIDField()

class EditWatermarkForm(forms.Form):
    stock_uuid = forms.UUIDField()
    watermark_active = forms.BooleanField(required=False) #If it is false, the webbrowser won't send it at all. Therefore we have to set it to required=False
    watermark = forms.IntegerField(min_value=0)

    def clean(self):
        cleaned_data = super().clean()
        id = cleaned_data.get("stock_uuid")
        
        if not id:
            raise ValidationError("No stock UUID given")

        stock = None
        try:
            stock = parts_models.Stock.objects.get(id=id)
        except:
            raise ValidationError("Stock with uuid %s does not exist" % (id))
        cleaned_data['stock'] = stock

        return cleaned_data

    def save(self):
        stock = self.cleaned_data['stock']
        active = self.cleaned_data['watermark_active']
        watermark = self.cleaned_data['watermark']

        if not active:
            watermark = -1

        stock.watermark = watermark
        stock.save()

class EditStockAmountForm(forms.Form):
    stock_uuid = forms.UUIDField()
    amount = forms.IntegerField(min_value=0)

    def clean(self):
        cleaned_data = super().clean()
        id = cleaned_data.get("stock_uuid")

        if not id:
            raise ValidationError("No stock UUID given")

        stock = None
        try:
            stock = parts_models.Stock.objects.get(id=id)
        except:
            raise ValidationError("Stock with uuid %s does not exist" % (id))
        cleaned_data['stock'] = stock

        return cleaned_data

    def save(self, increase: bool):
        stock = self.cleaned_data['stock']
        amount = self.cleaned_data['amount']

        if not increase:
            amount = -amount 

        return stock.atomic_increment(amount)

class AddStockForm(forms.Form):
    watermark_active = forms.BooleanField(required=False)
    watermark = forms.IntegerField(min_value=0, required=True, initial=0)
    amount = forms.IntegerField(min_value=0, required=True, initial=1)
    component_uuid = forms.UUIDField(required=True)
    lot = forms.CharField(max_length=255, required=False)

    def clean(self):
        cleaned_data = super().clean()

        id = cleaned_data.get('component_uuid')
        if not id:
            raise ValidationError('No valid component selected!')
        component = None
        try:
            component = parts_models.Component.objects.get(id=id)
        except:
            raise ValidationError("Invalid component selected!")
        cleaned_data['component'] = component

        return cleaned_data
    
    def save(self, storage):
        component = self.cleaned_data.get('component')
        amount = self.cleaned_data.get('amount')
        watermark = -1

        if self.cleaned_data.get('watermark_active'):
            watermark = self.cleaned_data.get('watermark')

        new_stock = parts_models.Stock.objects.create(storage=storage, component=component, watermark=watermark, amount=amount, lot=self.cleaned_data['lot'])
        new_stock.save()

class ComponentForm(forms.ModelForm):
    manufacturer = AutocompleteForeingKeyField(widget=AutoCompleteWidget)
    component_type = AutocompleteForeingKeyField()
    class Meta:
        model = parts_models.Component
        fields = '__all__'
        
class EditComponentForm(forms.Form):
    name = forms.CharField(required=True)
    datasheet_link = forms.CharField(max_length=300, required=False)
    description = forms.CharField(required=False, widget=forms.Textarea)
    
    # Look up these fields later. Will be autocompleted in UI
    manufacturer = forms.CharField(required=False, initial='')
    component_type = forms.CharField(required=False, label='Component Type', initial='')
    pref_distri = forms.CharField(required=False, label='Preferred Distributor', initial='')
    package = forms.CharField(required=False, initial='')

    image = forms.ImageField(required=False)

    def __init__(self, *args, instance=None, **kwargs):
        super().__init__(*args, **kwargs)

        self.instance = instance
        if instance:
            self.fields['name'].initial = instance.name
            self.fields['datasheet_link'].initial = instance.datasheet_link
            if instance.component_type:
                self.fields['component_type'].initial = instance.component_type.class_name
            self.fields['description'].initial = instance.description
            if instance.manufacturer:
                self.fields['manufacturer'].initial = instance.manufacturer.name
            if instance.package:
                self.fields['package'].initial = instance.package.name
            if instance.pref_distri:
                self.fields['pref_distri'].initial = instance.pref_distri.name
            self.fields['image'].initial = instance.image

    def clean_component_type(self):
        data = self.cleaned_data['component_type'].strip()
        
        if len(data) == 0:
            self.cleaned_data['component_type_object'] = None
            return

        try:
            self.cleaned_data['component_type_object'] = parts_models.ComponentType.objects.get(class_name=data)
        except:
            raise ValidationError('Invalid Component Type')
    
    def clean_manufacturer(self):
        data = self.cleaned_data['manufacturer'].strip()
        
        if len(data) == 0:
            self.cleaned_data['manufacturer_object'] = None
            return
        try:
            self.cleaned_data['manufacturer_object'] = parts_models.Manufacturer.objects.get(name=data)
        except:
            raise ValidationError('Invalid Manufacturer')

    def clean_pref_distri(self):
        data = self.cleaned_data['pref_distri'].strip()
        
        if len(data) == 0:
            self.cleaned_data['pref_distri_object'] = None
            return
        try:
            self.cleaned_data['pref_distri_object'] = parts_models.Distributor.objects.get(name=data)
        except:
            raise ValidationError('Invalid Distributor')

    def clean_package(self):
        data = self.cleaned_data['package'].strip()
        
        if len(data) == 0:
            self.cleaned_data['package_object'] = None
            return
        try:
            self.cleaned_data['package_object'] = parts_models.Package.objects.get(name=data)
        except:
            raise ValidationError('Invalid Package')


    def _save_new(self):
        self.instance = parts_models.Component.objects.create(
            name=self.cleaned_data['name'],
            datasheet_link=self.cleaned_data['datasheet_link'],
            description=self.cleaned_data['description'],
            package=self.cleaned_data['package_object'],
            component_type=self.cleaned_data['component_type_object'],
            pref_distri=self.cleaned_data['pref_distri_object'],
            manufacturer=self.cleaned_data['manufacturer_object']
        )

        if bool(self.cleaned_data['image']):
            self.instance.image = self.cleaned_data['image']
        self.instance.save()

    def save(self):
        if self.instance is None:
            self._save_new()
            return

        self.instance.name = self.cleaned_data['name']
        self.instance.datasheet_link = self.cleaned_data['datasheet_link']
        self.instance.description = self.cleaned_data['description']
        
        if bool(self.cleaned_data['image']) is False:
            self.instance.image = None
        else:
            self.instance.image = self.cleaned_data['image']

        self.instance.manufacturer = self.cleaned_data['manufacturer_object']
        self.instance.pref_distri = self.cleaned_data['pref_distri_object']
        self.instance.package = self.cleaned_data['package_object']
        self.instance.component_type = self.cleaned_data['component_type_object']
        self.instance.save()


class PackageForm(forms.ModelForm):
    class Meta:
        model = parts_models.Package
        fields = '__all__'

class DistributorForm(forms.ModelForm):
    class Meta:
        model = parts_models.Distributor
        fields = '__all__'
class ManufacturerForm(forms.ModelForm):
    class Meta:
        model = parts_models.Manufacturer
        fields = '__all__'