from django.forms import Form, ModelForm, ChoiceField, MultipleChoiceField, EmailField, CharField, BooleanField, IntegerField, URLInput, ModelChoiceField, ModelMultipleChoiceField
from django import forms # FIXME the whole thing?
from django.db.models import ForeignKey 
from django.db import models 
from django.forms.widgets import HiddenInput, RadioSelect, TextInput, Textarea, SelectMultiple
from .models import Node, Edge, Map_desc, NodeComment, UserProfile, Friend, ContactUs, Vote
from django.contrib.auth.models import User
from django.apps import apps
from django.conf import settings
import django_tables2 as tables
from django.utils.safestring import mark_safe
 
#import pdb
#import pprint

# NOTE: Use ModelForm rather than just Form to gain the unique=true property without introducing race conditions.
# For how to use a form widget with ModelForm rather than straight form classes:
# http://stackoverflow.com/questions/9878475/beginner-django-modelform-override-widget


from allauth.account.forms import SignupForm
from captcha.fields import ReCaptchaField
from captcha.widgets import ReCaptchaV2Checkbox

# for django-allauth:
class MyCustomSignupForm(SignupForm):
    captcha = ReCaptchaField( widget=ReCaptchaV2Checkbox( attrs={ 'data-theme': 'light', 'data-size': 'normal', }))

    def save(self,request):
        user = super(MyCustomSignupForm, self).save(request)
        #custom code here
        return user



class FileUploadForm(forms.Form):
	file_source = forms.FileField()

	def __init__(self, *args, **kwargs):
		super(FileUploadForm, self).__init__(*args, **kwargs)
		self.fields['file_source'].required = False



class ConfirmCancelAccountForm(forms.Form):
    confirmcancel = forms.CharField(max_length=100, strip=True, required=True, widget=forms.TextInput(attrs={'class': 'cancelAccountConfirmation' }) )
    deleteDataInNonOwnedMaps = forms.BooleanField(required=False)
    iHaveReadAndUnderstood = forms.BooleanField(required=False)


class MyAccountForm(ModelForm):
  email=forms.CharField(widget=forms.TextInput(attrs={'class':'borderNone', 'readonly':'readonly'}))

  class Meta:
    model = User
    fields = ['first_name','last_name','email']


class MapSettingsForm(ModelForm):
	class Meta:
		model = UserProfile
		fields = ['mapsettings']


class FriendDefineForm(ModelForm):
	class Meta:
		model = Friend 
		fields = ['friend']


class VoteForm(ModelForm):
	class Meta:
		model = Vote 
		fields = ['node','vote']


class FriendTable(tables.Table):
	removeFromMap = tables.Column(accessor='friend_id', orderable=False, verbose_name=mark_safe(""))
	username = tables.Column(accessor='username')
	first_name = tables.Column(accessor='first_name')
	last_name = tables.Column(accessor='last_name')
	#email = tables.Column(accessor='email')
	mapname = tables.Column(accessor='mapname', verbose_name=settings.WHAT_A_GRAPH_IS_CALLED.capitalize() + " Name")
	class Meta:
		model = Friend 
		empty_text = "No shares found."
		fields = []
		attrs = {'class': 'paleblue' }
		sequence = ['username','first_name','last_name','mapname','removeFromMap' ]

	def render_removeFromMap(self,value,record):
		if record['mapid']: # display button only if there's something in the mapname column
			return mark_safe("<button title='Stop sharing the "+ settings.WHAT_A_GRAPH_IS_CALLED.capitalize() + "with this person' class='removeFromMap' type='button' data-userid="+str(record['friend_id'])+" data-mapid="+str(record['mapid'])+">UnShare</button>")
		raise Exception("Internal Error: Missing required mapId value in table form.")

	#def render_removeFromTeam(self,value,record):
		# NOTE: type=button removes the default 'submit' event handler
		#if record.friend_id:
			#return mark_safe("<button title='Remove from team' class='removeFromTeam' type='button' data-teammemberid="+str(record.friend_id)+">Remove</button>")
		#return HttpResponse("Internal Error: Missing required friend ID value.", status=406)



class UserSelectTable(tables.Table):
	addToMap = tables.Column(accessor='id', orderable=False, verbose_name=mark_safe("Share Current Map"))
	username = tables.Column(accessor='username')
	first_name = tables.Column(accessor='first_name')
	last_name = tables.Column(accessor='last_name')
	class Meta:
		model = User 
		empty_text = "No one found."
		fields = []
		attrs = {'class': 'paleblue' }
		sequence = ['username','first_name','last_name','addToMap' ]

	def render_addToMap(self,value,record):
		if record.id: 
			return mark_safe("<button class='addToMap' data-userid=" + str(record.id) + ">Yes</button>")
		raise Exception("Internal Error: Missing required mapId value in table form.")
		# FIXME return HttpResponse("Internal Error: Missing required map ID value.", status=406)



class NotifyUsersForm(Form):
	# FIXME: remove styles and add classes instead, here and elsewhere
	users = ModelMultipleChoiceField(queryset=None, widget=SelectMultiple(attrs={'style': 'padding:0 5px'}) )
	emailbody = CharField(widget = Textarea( attrs={'style':'word-wrap:break-word', 'name':'emailbody', 'class':'centeredMargins', 'rows':8, 'cols':55 }))
	clear = BooleanField(required=False)

	def __init__(self, *args, clear=False, emailbody_required=True, queryset=None, **kwargs):
		if kwargs.get('emailbody_required'):
			emailbody_required = kwargs.pop('emailbody_required')
		if kwargs.get('queryset'):
			queryset = kwargs.pop('queryset')
		super(NotifyUsersForm, self).__init__(*args, **kwargs)
		self.fields['users'].label= ''
		if emailbody_required:
			self.fields['emailbody'].required = emailbody_required 
		if queryset:
			self.fields['users'].queryset = queryset 
		self.clear=clear

	def clean_emailbody(self):
		emailbody = self.cleaned_data['emailbody']
		if(self.clear):
			emailbody=''
		return emailbody 
	
	

class SearchAllUsersForm(Form):
	SEARCH_USERS_CHOICES = (
    ('username','Username'),
    ('first_name','First Name'),
    ('last_name','Last Name'),
	)

	# FIXME: DIY for id:searchTerm, here and in js/registerEventsForInvite.js
	email = EmailField(required=False)
	searchTerm = CharField(required=False, widget = TextInput( attrs={'id':'searchTerm', 'size':10, 'maxlength':30 }))
	searchType = ChoiceField(widget=RadioSelect(), choices=SEARCH_USERS_CHOICES, initial='username') 

	def __init__(self, *args, **kwargs):
		super(SearchAllUsersForm, self).__init__(*args, **kwargs)
		self.fields['email'].widget.attrs['placeholder'] = 'Their email address'

	def clean(self):
		cleaned_data = super(SearchAllUsersForm, self).clean()
		email = cleaned_data.get("email")
		searchTerm = cleaned_data.get("searchTerm")
		if not email and not searchTerm:
			raise forms.ValidationError("At least one entry is required.")
		return cleaned_data



class ValidateNodeForm(ModelForm):
	class Meta:
		model = Node 
		#fields = '__all__'
		fields = ['label','description','url']


class ValidateEdgeForm(ModelForm):
	class Meta:
		model = Edge 
		fields = ['label']


class ValidateNodeComment(ModelForm):
	class Meta:
		model = NodeComment
		fields = ['comment']


class ValidateMapForm(ModelForm):
	class Meta:
		model = Map_desc 
		fields = ['mapname','description']




class ContactUsForm(ModelForm):
    captcha = ReCaptchaField( widget=ReCaptchaV2Checkbox( attrs={ 'data-theme': 'light', 'data-size': 'normal', }))

    class Meta:
        model = ContactUs
        fields = ['email','message']
        widgets = {'message': Textarea(attrs={'placeholder':'To help us help you:\n\nAre you using Chrome, Firefox, Safari, other?\n\nOn Windows, Mac, Linux, other?'}) }



class OpenMapForm(Form):
	mapId = ForeignKey(Map_desc, null=False, on_delete=models.PROTECT)

	def clean_id(self):
		mapId = self.cleaned_data['mapId']
		if not Map_desc.objects.filter(pk=mapId).exists():
			raise ValidationError("Map id does not exist.")
		return mapId



class AlterEdgeForm(ModelForm):
	class Meta:
		model = Edge 
		fields = ['id','cost','label','color','ofmap','owner']


class AlterMapForm(ModelForm):
	class Meta:
		model = Map_desc 
		fields = ['mapname','description','bgcolor','orientation','defaultNodeStyle','defaultNodeShape','defaultNodeHeight','defaultNodeWidth','defaultNodeFillcolor'  ]


class DeleteMapForm(ModelForm):
	class Meta:
		model = Map_desc 
		fields = []


class NewMapForm(ModelForm):
	class Meta:
		model = Map_desc 
		fields = ['mapname','description']
		widgets = {
			'mapname':Textarea(attrs={'placeholder': settings.WHAT_A_GRAPH_IS_CALLED + ' name', 'rows':1, 'size':settings.LABELSHOWLEN, 'maxlength':settings.LABELSHOWLEN }), 
			'description':Textarea(attrs={'placeholder':'Description', 'size':50, 'rows':5, 'maxlength':settings.MAPDESCLEN }), 
		}

	def __init__(self, *args, **kwargs ):
		super().__init__(*args, **kwargs)
		self.fields['mapname'].required = True  # FIXME: supplementing the model.  Document why it can't be there instead of here.

		def clean_mapname(self):
			if self.cleaned_data.get('mapname'):
				# Remove extra white space
				return self.cleaned_data.get('mapname','').strip()

		def clean_description(self):
			if self.cleaned_data.get('description'):
				# Remove extra white space
				return self.cleaned_data.get('description','').strip()



class NewTunnelNodeForm(ModelForm):
	class Meta:
		model = Node 
		fields = ['nodetype','xpos','ypos','size','tunnelfarendmap']
		widgets = {
			'nodetype':HiddenInput(), 
			'xpos':HiddenInput(), 
			'ypos':HiddenInput(), 
			'size':HiddenInput(), 
		}

	def __init__(self, *args, queryset=None, **kwargs):
		super(NewTunnelNodeForm, self).__init__(*args, **kwargs)
		self.fields['tunnelfarendmap'] = ModelChoiceField(queryset, label='', empty_label=None)



class NewNodeForm(ModelForm):
	class Meta:
		model = Node 
		fields = ['label','nodetype','url','description','xpos','ypos','size']
		widgets = {
			#'label':Textarea(attrs={'placeholder':'Label', 'rows':1, 'cols':40, 'maxlength':settings.NODE_LABEL_LENGTH }), 
			'label':Textarea(attrs={'rows':1, 'cols':40, 'maxlength':settings.NODE_LABEL_LENGTH }), 
			'url':URLInput(attrs={'id':'nodeurl', 'size':40, 'maxlength':settings.NODE_URLFIELD_LENGTH }), 
			'nodetype':HiddenInput(), 
			'description':Textarea(attrs={'rows':10, 'cols':40, 'maxlength':settings.NODE_DESCRIPTION_LENGTH}), 
			'xpos':HiddenInput(), 
			'ypos':HiddenInput(), 
			'size':HiddenInput()
		}

	def clean_label(self):
		# Remove extra white space
		if self.cleaned_data.get('label'):
			return self.cleaned_data.get('label','').strip()


	# FIXME: write test to submit dirty url
	def clean_url(self):
		# Remove extra white space.
		# If 'http://' is missing it will be added.
		if self.cleaned_data.get('url'):
			url = self.cleaned_data.get('url').strip()
			if not url.startswith("http"):
				url = "http://" + url 
			return url


	def clean_description(self):
		# Remove extra white space
		if self.cleaned_data.get('description'):
			return self.cleaned_data.get('description','').strip()



class NodeCommentForm(ModelForm):
	class Meta:
		model = NodeComment 
		fields = ['comment']
		# FIXME: replace style with a class
		widgets = {'comment':Textarea(attrs={ 'style':'word-wrap:break-word', 'rows':4, 'cols':45, 'placeholder':'New comment'}) }
		labels = {'comment':''}

	def clean_comment(self):
		# Remove extra white space
		if self.cleaned_data.get('comment'):
			return self.cleaned_data.get('comment','').strip()
	


# FIXME: remove old stuff

"""
	mapname = ModelChoiceField(queryset=None, widget=RadioSelect, to_field_name='id')
	description = CharField()

	class Meta:
		model = Map_desc
		fields = ['mapname']

	def __init__(self, queryset, *args, **kwargs):
		super(OpenMapForm, self).__init__(*args, **kwargs)
		self.fields['mapname'].queryset = queryset 
"""
	

	

"""
class PickQuestionForm(ModelForm):
	question = ModelChoiceField(queryset=None, widget=RadioSelect, empty_label=None, to_field_name='id')
	class Meta:
		model = Question
		exclude = ['question_text','pub_date','asker']

	def __init__(self, queryset,**kwargs):
		super(PickQuestionForm,self).__init__(**kwargs)
		self.fields['question'].queryset = queryset
		self.fields['question'].label_suffix = ''
		self.fields['question'].label= 'Pick A Question'
"""

"""
def construct_form_field(model, field_name, **kwargs):
	app_name, model_name = model.split('.', 1)
	Model = apps.get_model('askWisdom', model_name)
	field = Model._meta.get_field_by_name(field_name)[0]
	return field.formfield(**kwargs)
"""

"""
class AnswerQuestionForm(ModelForm):
	class Meta:
		model = Answer
		fields = ['answer_text','question']
		widgets = {'answer_text': Textarea(attrs={'class': 'answerDisplay', 'placeholder':'Answer here'}), 'question': HiddenInput }

	def __init__(self, data=None, answer_label=None, answer_text_required=True, **kwargs ):
		super().__init__(data, **kwargs)
		self.fields['answer_text'].label = answer_label
		self.fields['answer_text'].label_suffix = ''
		self.fields['answer_text'].required = answer_text_required

"""
