from django.shortcuts import render

# Create your views here.

from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
from django.shortcuts import render, get_object_or_404, get_list_or_404, redirect
from django.urls import reverse
from django.contrib.auth.models import User, Group

from .models import *
from .forms import *

from django.utils import timezone
from django.core.serializers.json import DjangoJSONEncoder
import json
import datetime

import pdfcrowd
import random
from django.conf import settings

from django.views.decorators.csrf import csrf_exempt, csrf_protect
import csv

from django.contrib.auth import get_user_model
from django.contrib.sites.shortcuts import get_current_site
from django.contrib.auth.tokens import default_token_generator
from django.contrib.auth.forms import AuthenticationForm
from django.contrib import messages
from django.contrib.auth import authenticate, login as django_login
from django.template.loader import get_template
from django.template import Context ,loader
from django.core.mail import send_mail
from django.template.loader import render_to_string, get_template
from django.utils.encoding import force_bytes, force_text
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
import datetime

#def index(request):
#    user = request.user
#    if user.is_authenticated:
#        try:
#            points = get_list_or_404(Point, user_id=user.id)
#        except:
#            points = []
#        n = len(points)
#        return render(request, 'webmap/webmap.html', {'points': points})
#    else:
#        return HttpResponseRedirect(reverse('index'))

def login2(request):
    if request.method == 'POST':
        # AuthenticationForm_can_also_be_used__
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(request, username=username, password=password)
        try:
            value_cook = request.COOKIES.get('token')
            UserSess   = CookSession.objects.get(user=user)
            value_old  = UserSess.tokenBrowser
        except:
            value_cook = None
            value_old  = None
        if user is not None:
           if value_cook is not None and value_cook==value_old:
               form = django_login(request, user)
               return redirect('/')
           else:
                email = user.email
                if email is not None:
                    current_site   = get_current_site(request)
                    mail_subject   = 'REIndicator Login Verification'

                    token = default_token_generator.make_token(user)
                    if request.is_secure():
                        protocol = 'https'
                    else:
                        protocol = 'http'
                    message = render_to_string('webmap/activation_email_template.html', {
                        'user': user,
                        'domain': current_site.domain,
                        'uid': urlsafe_base64_encode(force_bytes(user.pk)),
                        'token': token,
                        'protocol' :protocol,
                    })
                    try:
                        CookSession.objects.filter(user=user).delete()
                    except:
                        print("New login")
                    send_mail(mail_subject, message, 'REIndicator Support <support@reindicator.com>', [email])
                    return render(request, 'webmap/activation_email_sent.html', {'email': user.email})
        else:
            messages.warning(request, f"Your username or password is incorrect. Please try again.")
    if request.user.is_authenticated:
        return redirect('/')
    else:
        form = AuthenticationForm()
        return render(request, 'webmap/login.html', {'form': form, 'title': 'log in'})

def activate(request, uidb64, token):
    User = get_user_model()
    try:
        uid = force_text(urlsafe_base64_decode(uidb64))
        user = User.objects.get(pk=uid)
    except(TypeError, ValueError, OverflowError, User.DoesNotExist):
        user = None
    if user is not None and default_token_generator.check_token(user, token):
        browser = request.META['HTTP_USER_AGENT']
        template = loader.get_template('webmap/activation_done.html')
        response = HttpResponse(template.render({'username':user.username}, request))
        value = f"{token}{browser}"
        max_age, expires = set_max_age(age=42)
        response.set_cookie(
            "token",
            value,
            max_age=max_age,
            expires=expires)

        form = django_login(request, user, backend='webmap.externalSettings.UserNameBackend')

        # create a link from the user to the current session (for later removal)
        CookSession.objects.get_or_create(
            user=user,
            tokenBrowser = value
        )
        return response
    else:
        return HttpResponse('Activation link is invalid!')

def set_max_age(age = 42): # default 6 weeks
    max_age = age * 24 * 60 * 60  # 6 weeks
    expires = datetime.datetime.strftime(
        datetime.datetime.utcnow() + datetime.timedelta(seconds=max_age),
        "%a, %d-%b-%Y %H:%M:%S GMT",
    )
    return max_age ,expires

def login(request):
    return render(request, 'webmap/login.html')

def index(request):
    user = request.user
    if user.is_superuser:
        userLevel = 'SuperUser'
    elif user.groups.filter(name='Both_Anticipator').exists():
        userLevel = 'Both_Anticipator'
    elif user.groups.filter(name='Both_Analyzer').exists():
        userLevel = 'Both_Analyzer'
    elif user.groups.filter(name='Both_Snapshots').exists():
        userLevel = 'Both_Snapshots'
    elif user.groups.filter(name='Multi_Anticipator').exists():
        userLevel = 'Multi_Anticipator'
    elif user.groups.filter(name='Multi_Analyzer').exists():
        userLevel = 'Multi_Analyzer'
    elif user.groups.filter(name='Multi_Snapshots').exists():
        userLevel = 'Multi_Snapshots'
    elif user.groups.filter(name='Single_Anticipator').exists():
        userLevel = 'Single_Anticipator'
    elif user.groups.filter(name='Single_Analyzer').exists():
        userLevel = 'Single_Analyzer'
    elif user.groups.filter(name='Single_Snapshots').exists():
        userLevel = 'Single_Snapshots'
    elif user.groups.filter(name='MDM1').exists():
        userLevel = 'MDM1'
    elif user.groups.filter(name='Hiatus').exists():
        userLevel = 'Hiatus'
    else:
        userLevel = 'Hiatus'
    now = timezone.now()
    DAY = timezone.timedelta(days=1)
    MINUTE = timezone.timedelta(minutes=1)
    
    if request.session.get('alert_dismissed') is None:
        alerts = PopUpAlert.objects.filter(start__lte=now, end__gte=now)
        request.session['alert_dismissed'] = json.dumps(
                                                        now,
                                                        sort_keys=True,
                                                        indent=1,
                                                        cls=DjangoJSONEncoder
                                                       )
    else:
        dismissed_time = json.loads(request.session['alert_dismissed'])
        dismissed_time = timezone.datetime.strptime(dismissed_time,
                                                    '%Y-%m-%dT%H:%M:%S.%fZ')
        dismissed_time = dismissed_time.astimezone(timezone.utc)
        if (now - dismissed_time) >= MINUTE:
            alerts = PopUpAlert.objects.filter(start__lte=now, end__gte=now)
            request.session['alert_dismissed'] = json.dumps(
                                                            now,
                                                            sort_keys=True,
                                                            indent=1,
                                                            cls=DjangoJSONEncoder
                                                           )
        else:
            alerts = PopUpAlert.objects.all().none()
        
    if user.is_authenticated:
        try:
            points = list(Point.objects.filter(user_id=user.id).order_by('location'))
        except:
            points = []
        try:
            categories1 = Category.objects.exclude(owner__isnull=False)
            categories2 = Category.objects.filter(owner_id=user.id)
            categories = categories1.union(categories2)
        except:
            categories = []
        try:
            basemap1 = Basemap.objects.get(default=True)
            basemap2 = Basemap.objects.filter(default=False)
            basemaps = [basemap1] + list(basemap2)
#            basemap2   = basemap2[0]
        except:
            basemap1 = Basemap()
            basemap2 = Basemap()
            basemaps = [basemap1, basemap2]
#        n = len(points)
        try:
            overlays = CartoOverlay.objects.order_by('-primary', '-name')
        except:
            overlays = [CartoOverlay()]
            
        try:
            token = AccessToken.objects.get(name='mapbox')
            token = token.token
        except:
            token = ''
        try:
            cartoApiKey = AccessToken.objects.get(name='CartoApiKey')
            cartoApiKey = cartoApiKey.token
        except:
            cartoApiKey = ''
        try:
            googleMapApiKey = AccessToken.objects.get(name='GoogleMapApiKey')
            googleMapApiKey = googleMapApiKey.token
        except:
            googleMapApiKey = ''
        try:
            folders_orderBy_name_asc = list(Folder.objects.filter(owner_id=user.id).order_by('name'))
            folders = folders_orderBy_name_asc
        except:
            folders_orderBy_name_asc = []
            folders = []
        try:
            folders_orderBy_name_desc = list(Folder.objects.filter(owner_id=user.id).order_by('-name'))
        except:
            folders_orderBy_name_desc = []
        try:
            folders_orderBy_date_asc = list(Folder.objects.filter(owner_id=user.id).order_by('created'))
        except:
            folders_orderBy_date_asc = []
        try:
            folders_orderBy_date_desc = list(Folder.objects.filter(owner_id=user.id).order_by('-created'))
        except:
            folders_orderBy_date_desc = []
        folders_groups = [folders_orderBy_name_asc,folders_orderBy_name_desc,folders_orderBy_date_asc,folders_orderBy_date_desc]
        
        form = PointForm()
        lat = request.session.get('lat', None)
        lon = request.session.get('lon', None)
        request.session['lat'] = None
        request.session['lon'] = None
        new_point = None
        deleted = request.session.get('deleted', None)
        request.session['deleted'] = None
        return render(request, 'webmap/index.html', {'points':     points,
#                                                     'n':          n,
                                                     'user':       user,
                                                     'token':      token,
                                                     'cartoApiKey':cartoApiKey,
                                                     'googleMapApiKey':googleMapApiKey,
                                                     'categories': categories,
#                                                     'basemap1':   basemap1,
#                                                     'basemap2':   basemap2,
                                                     'basemaps':   basemaps,
                                                     'form':       form,
                                                     'new_point':  new_point,
                                                     'overlays':   overlays,
                                                     'lat':        lat,
                                                     'lon':        lon,
                                                     'deleted':    deleted,
                                                     'folders':    folders,
                                                     'folders_groups':               folders_groups,
                                                     'alerts':     alerts,
                                                     'isColorBlind': user.profile.colorBlind,
                                                     'is_disclaimer_agreed': user.profile.is_disclaimer_agreed,
                                                     'userLevel' : userLevel,
                                                     'emergingMarketLayerNameForAnalyzerAndSnapshots' : 'EmergingMarkets2023Q2', # Emerging Market layer name to display for An, snap users
                                                    })
    else:
        n=0
        points=[]
        try:
            basemap1   = Basemap.objects.get(default=True)
            basemap2   = Basemap.objects.filter(default=False)
            basemaps   = [basemap1] + list(basemap2)
#            basemap2   = basemap2[0]
        except:
            basemap1   = Basemap()
            basemap2   = Basemap()
            basemaps   = [basemap1, basemap2]
        return render(request, 'webmap/index.html', {'points':   points,
#                                                     'n':        n,
                                                     'user':     user,
#                                                     'basemap1': basemap1,
#                                                     'basemap2': basemap2,
                                                     'basemaps':   basemaps,
                                                     'alerts':     alerts,
                                                    })
def drawer(request):
    return render(request, 'webmap/drawer.html')

def addpoint(request):
    if request.method == 'POST':
        form = PointForm(request.POST)
        if form and request.user.is_authenticated:
            new_point = form.save(commit=False)
            new_point.user = request.user
            categorypk = request.POST.get('category')
            new_point.category = Category.objects.get(pk=categorypk)
            allpks = Folder.objects.filter(owner=request.user).values_list('pk', flat=True)
            folderpk = request.POST.get('saveToFolder')
            if folderpk is not '':
                for pk in allpks:
                    if int(folderpk) == int(pk):
                        folder = get_object_or_404(Folder, pk=pk)
                        new_point.folder = folder
                        new_point.save()
                        request.session['modified'] = new_point.location
                        request.session['lat'] = new_point.latitude
                        request.session['lon'] = new_point.longitude
                        response = HttpResponseRedirect('/')
                        response.set_cookie('showAllIcon', 'show')
                        response.set_cookie('sAMIF'+folderpk,'show')
                        return response
            else:
                new_point.save()
                request.session['modified'] = new_point.location
                request.session['lat'] = new_point.latitude
                request.session['lon'] = new_point.longitude
                response = HttpResponseRedirect('/')
                response.set_cookie('showAllIcon', 'show')
                response.set_cookie('showAllMarkersNotInFolder','show')
                return response
            return redirect('/')
        else:
            return redirect('/')
    else:
        new_point = None
        return redirect('/')

def deletepoint(request):
    pk = request.POST.get('pk')
    pt = get_object_or_404(Point, pk=pk)
    request.session['lat'] = pt.latitude
    request.session['lon'] = pt.longitude
    request.session['zoom'] = 13
    if request.user == pt.user:
        pt.delete()
        request.session['deleted'] = pt.location
    return redirect('/')

def changepoint(request):
    ptpk = request.POST.get('ptpk')
    pt = get_object_or_404(Point, pk=ptpk)
    request.session['lat'] = pt.latitude
    request.session['lon'] = pt.longitude
    request.session['zoom'] = 13
    if request.user == pt.user:
        allpks = Category.objects.all().values_list('pk', flat=True)
        for pk in allpks:
            catpk = request.POST.get('catpk_'+str(pk)+'.x')
            if catpk:
                cat = get_object_or_404(Category, pk=pk)
                pt.category = cat
                pt.save()
                request.session['modified'] = pt.location
                return redirect('/')
    return redirect('/')

def changepointfolder(request):
    ptpk = request.POST.get('ptpk')
    pt = get_object_or_404(Point, pk=ptpk)
    request.session['lat'] = pt.latitude
    request.session['lon'] = pt.longitude
    request.session['zoom'] = 13
    if request.user == pt.user:
        allpks = Folder.objects.filter(owner=request.user).values_list('pk', flat=True)
        for pk in allpks:
            folderpk = request.POST.get('folderpk_'+str(pk)+'.x')
            if folderpk is not None:
                folder = get_object_or_404(Folder, pk=pk)
                pt.folder = folder
                pt.save()
                request.session['modified'] = pt.location
                return redirect('/')
    return redirect('/')
    
def editUserInfo(request):
    if not request.user.is_authenticated:
        return redirect('/')
    if request.method == 'POST':
        form = UserInfoForm(request.POST)
        if form.is_valid():
            user = request.user
            user.username = form.cleaned_data['username']
            user.email    = form.cleaned_data['email']
            user.first_name = form.cleaned_data['firstname']
            user.last_name = form.cleaned_data['lastname']
            user.profile.colorBlind = form.cleaned_data['colorBlind']
            user.save()
            return redirect('/')
    else:
        form = UserInfoForm(initial={'username': request.user.username,
                                     'email': request.user.email,
                                     'firstname': request.user.first_name,
                                     'lastname': request.user.last_name,
                                     'colorBlind': request.user.profile.colorBlind,
                                    }
                           )
        return render(request, 'webmap/userinfo.html', {'form': form})

def convertToPDF(request):
    data = request.POST.get('data')
    height = request.POST.get('height')
    width = request.POST.get('width')
    try:
        # enter your Pdfcrowd credentials to the converter's constructor

        client = pdfcrowd.HtmlToPdfClient(settings.PDFCROWD_USERNAME, settings.PDFCROWD_API_KEY)
        width = float(width) + 20 #margin
        height = float(height) + 10 #margin
        client.setPageWidth(str(width)+'mm')
        client.setPageHeight(str(height)+'mm')
        number = random.randint(1,101)
        client.convertStringToFile(data, settings.MEDIA_ROOT + '/pdf/Map'+str(number)+'.pdf')

        return HttpResponse('/media/pdf/Map'+str(number)+'.pdf')
    except pdfcrowd.Error as why:
        print(why)
        return HttpResponse(why)

def markerShow(request):
    boolValue = {'true':True,'false':False,}
    visible =  request.POST.get('visible')
    ptpk = request.POST.get('ptpk')
    pt = get_object_or_404(Point, pk=ptpk)
    try:
        if request.user == pt.user:
            pt.visible = boolValue.get(visible)
            pt.save()
            return HttpResponse('success')
        else:
            return HttpResponse('fail')
    except Exception as why:
        print(why)
        return HttpResponse(why)

def markerAllShow(request):
    boolValue = {'true':True,'false':False,}
    visible =  request.POST.get('visible')
    try:
        allpks = Point.objects.filter(user=request.user).values_list('pk', flat=True)
        for pk in allpks:
            point = get_object_or_404(Point, pk=pk)
            point.visible = boolValue.get(visible)
            point.save()            
        return HttpResponse('success')
    except Exception as why:
        print(why)
        return HttpResponse(why)

def showMarkersByFolder(request):
    try:
        points = list(Point.objects.filter(user=request.user).order_by('location'))
    except:
        points = []
    boolValue = {'true':True,'false':False,}
    visible =  request.POST.get('visible')
    folderID = request.POST.get('folderID')
    fd = get_object_or_404(Folder, pk=folderID)
    try:
        allpks = Point.objects.filter(user=request.user,folder=fd).values_list('pk', flat=True)
        indexs = []
        for pk in allpks:
            point = get_object_or_404(Point, pk=pk)
            point.visible = boolValue.get(visible)
            indexs.append(points.index(point))
            point.save()
        return JsonResponse(indexs,safe=False)
    except Exception as why:
        print(why)
        return HttpResponse("Failed")

def showMarkersNotInFolder(request):
    try:
        points = list(Point.objects.filter(user=request.user).order_by('location'))
    except:
        points = []
    boolValue = {'true':True,'false':False,}
    visible =  request.POST.get('visible')
    try:
        allpks = Point.objects.filter(user=request.user,folder__isnull=True).values_list('pk', flat=True)
        indexs = []
        for pk in allpks:
            point = get_object_or_404(Point, pk=pk)
            point.visible = boolValue.get(visible)
            indexs.append(points.index(point))
            point.save()
        return JsonResponse(indexs,safe=False)
    except Exception as why:
        print(why)
        return HttpResponse("Failed")

def markerCircleShow(request):
    boolValue = {'true':True,'false':False,}
    visible =  request.POST.get('visible')
    ptpk = request.POST.get('ptpk')
    mile_index = request.POST.get('mile_index')
    pt = get_object_or_404(Point, pk=ptpk)
    try:
        if request.user == pt.user:
            if mile_index == '0':
                pt.circleVisible = boolValue.get(visible)
                pt.save()
            elif mile_index == '1':
                pt.circleVisible1 = boolValue.get(visible)
                pt.save()
            elif mile_index == '2':
                pt.circleVisible2 = boolValue.get(visible)
                pt.save()
            else:
                return HttpResponse('fail')
            return HttpResponse('success')
        else:
            return HttpResponse('fail')
    except Exception as why:
        print(why)
        return HttpResponse(why)

def markerCirclesAllShow(request):
    boolValue = {'true':True,'false':False,}
    visible =  request.POST.get('visible')
    try:
        allpks = Point.objects.filter(user=request.user).values_list('pk', flat=True)
        for pk in allpks:
            point = get_object_or_404(Point, pk=pk)
            point.circleVisible = boolValue.get(visible)
            point.circleVisible1 = boolValue.get(visible)
            point.circleVisible2 = boolValue.get(visible)
            point.save()            
        return HttpResponse('success')
    except Exception as why:
        print(why)
        return HttpResponse(why)

def changeEmail(request):    
    if not request.user.is_authenticated:
        return HttpResponse('unAuthenticated')
    if request.method == 'POST':
        email =  request.POST.get('email')
        user = request.user
        try:            
            user.email = email
            user.save()
            return HttpResponse('success')
        except Exception as why:
            print(why)
            return HttpResponse(why)
    else:
        return HttpResponse('noPostMethod')

def disclaimerConfirm(request):
    if not request.user.is_authenticated:
        return HttpResponse('unAuthenticated')
    if request.method == 'POST':
        user = request.user
        try:            
            user.profile.is_disclaimer_agreed = True
            user.save()
            return HttpResponse('success')
        except Exception as why:
            print(why)
            return HttpResponse(why)
    else:
        return HttpResponse('noPostMethod')

@csrf_exempt
def receiveDataFromWP(request):
    if request.method=="POST":

        string_file = open('string.txt', 'w')
        byte_file = open('byte.txt', 'w+b')
        string_file.write(request.scheme)
        string_file.write('\n')
        byte_file.write(request.body)
        string_file.write(request.path)
        string_file.write('\n')
        string_file.write(request.path_info)
        string_file.write('\n')
        string_file.write(request.method)
        string_file.write('\n')
        string_file.write(request.content_type)
        string_file.write('\n')
        for key in request.FILES:
            string_file.write(key)
            string_file.write('\n')
        
        for key in request.FILES:
            string_file.write(key)
            string_file.write('\n')
        for key in request.headers:
            string_file.write(key)
            string_file.write(":")
            string_file.write(request.headers[key])
            string_file.write('\n')
        string_file.close()
        byte_file.close()
        
        string_file_after = open('string_after.txt', 'w')

        decoded_file = request.body.decode('utf-8').splitlines()
        data = csv.DictReader(decoded_file)
        user = User()
        membership = 'Multi_Snapshots' # default membership
        temp_email = 'none'
        password = '12345678'
        for row in data:
            for key, value in row.items():
                if key == 'billing_email':
                    user.username = value
                    user.email = value
                    temp_email = value
                elif key == 'billing_first_name':
                    user.first_name = value
                elif key == 'billing_last_name':
                    user.last_name = value
                elif key == 'item_sku':
                    if(value[0:4] == 'BATP'):
                        membership = 'Both_Anticipator'
                    elif(value[0:4] == 'BANZ'):
                        membership = 'Both_Analyzer'
                    elif(value[0:4] == 'BSNP'):
                        membership = 'Both_Snapshots'
                    elif(value[0:4] == 'MATP'):
                        membership = 'Multi_Anticipator'
                    elif(value[0:4] == 'MANZ'):
                        membership = 'Multi_Analyzer'
                    elif(value[0:4] == 'MSNP'):
                        membership = 'Multi_Snapshots'
                    elif(value[0:4] == 'SATP'):
                        membership = 'Single_Anticipator'
                    elif(value[0:4] == 'SANZ'):
                        membership = 'Single_Analyzer'
                    elif(value[0:4] == 'SSNP'):
                        membership = 'Single_Snapshots'
                    else: # Default
                        membership = 'Hiatus'
                    string_file_after.write(membership)
                elif key == 'password':
                    password = value

        string_file_after.write("HERE")
        string_file_after.close()
        if temp_email == 'none':
            return HttpResponse("Email is required.")
        if User.objects.filter(username=user.username).exists():
            return HttpResponse("This username has already existed.")
        if User.objects.filter(email=user.email).exists():
            return HttpResponse("This email has already existed.")
        #random password or get from request : temperary 12345678
        user.set_password(password)
        user.save()
        user.groups.add(Group.objects.get(name=membership))
        user.profile.group = Group.objects.get(name=membership)
        user.profile.save()
        
        # uploaded_file = request.FILES['file']
        # decoded_file = uploaded_file.read().decode('utf-8').splitlines()
        # data = csv.DictReader(decoded_file)
        # user = User()
        # membership = 'Multi_Snapshots' # default membership
        # temp_email = 'none'
        # for row in data:
        #     for key, value in row.items():
        #         if key == 'billing_email':
        #             user.username = value
        #             user.email = value
        #             temp_email = value
        #         elif key == 'billing_first_name':
        #             user.first_name = value
        #         elif key == 'billing_last_name':
        #             user.last_name = value
        #         elif key == 'item_sku':
        #             membership = value
        # if temp_email == 'none':
        #     return HttpResponse("Email is required.")
        # if User.objects.filter(username=user.username).exists():
        #     return HttpResponse("This username has already existed.")
        # if User.objects.filter(email=user.email).exists():
        #     return HttpResponse("This email has already existed.")
        # #random password or get from request : temperary 12345678
        # user.set_password('12345678')
        # user.save()
        # user.groups.add(Group.objects.get(name=membership))
        # user.profile.group = Group.objects.get(name=membership)
        # user.profile.save()
        return HttpResponse("success")
    return HttpResponse("Invalid request method")