import os
import string
import re
#import settings
import urllib.parse
# from pathlib import Path
from PIL import Image, ImageDraw, ImageFont

from django.http import HttpResponse
from django.shortcuts import render
# from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned

import troggle.settings as settings
from troggle.core.models.caves import Entrance, Area, SurvexStation, Cave
from troggle.core.views.caves import caveKey
from troggle.parsers.survex import MapLocations

''' Generates the prospecting guide document.

Also produces the overlay of points on top of a prospecting_image map - to be deleted.
I have tried to make this work with the version of PIL we have installed but something is missing still.
'''

AREANAMES = [
	#('',     'Location unclear'),
	('1a',   '1a – Plateau: around Top Camp'),
	('1b',   '1b – Western plateau near 182'),
	('1c',   '1c – Eastern plateau near 204 walk-in path'),
	('1d',   '1d – Further plateau around 76'),
	('2a',   '2a – Southern Schwarzmooskogel near 201 path and the Nipple'),
	('2b',   '2b – Eishöhle area'),
	('2b or 4 (unclear)', '2b or 4 (unclear)'),
	('2c',   '2c – Kaninchenhöhle area'),
	('2d',   '2d – Steinbrückenhöhle area'),
	('3',    '3 – Bräuning Alm'),
	('4',	'4 – Kratzer valley'),
	('5',	'5 – Schwarzmoos-Wildensee'),
	('6',	'6 – Far plateau'),
	('1626 or 6 (borderline)', '1626 or 6 (borderline)'),
	('7',	'7 – Egglgrube'),
	('8a',	'8a – Loser south face'),
	('8b',	'8b – Loser below Dimmelwand'),
	('8c',	'8c – Augst See'),
	('8d',	'8d – Loser-Hochganger ridge'),
	('9',	'9 – Gschwandt Alm'),
	('10',	'10 – Altaussee'),
	('11',	'11 – Augstbach')
	]


def prospecting(request):
    '''This produces the multipage 'prospecting guide' document,
    intended to be printed and carried into the field - in 1999.
    
    All the formatting and selection clverness is in the template file.
    '''
    areas = []
    for key, name in AREANAMES:
        a = Area.objects.get(short_name = key) # assumes unique
        caves = list(a.cave_set.all())
        caves.sort(key=caveKey)
        areas.append((name, a, caves))
    return render(request, 'prospecting.html', {"areas": areas})
    
        
# Parameters for big map and zoomed subarea maps:
# big map first (zoom factor ignored)

# These are the values for the url /prospecting/[mapcode].png 

maps = {
# id	left		top			right		bottom		zoom
#		G&K			G&K			G&K			G&K			factor
"all": [33810.4,	85436.5,	38192.0,		81048.2,	0.35,
		"All"],
"40":  [36275.6,	82392.5,	36780.3,	81800.0,	3.0,
		"Eishöhle"],
"76":  [35440.0,	83220.0,	36090.0,	82670.0,	1.3,
		"Eislufthöhle"],
"204": [36354.1,	84154.5,	37047.4,	83300,	3.0,
		"Steinbrückenhöhle"],
"tc":  [35230.0,	82690.0,	36110.0,	82100.0,	3.0,
		"Near Top Camp"],
"grieß":
       [36000.0,	86300.0,	38320.0,	84400.0,	4.0,
		"Grießkogel Area"],
}

for n in list(maps.keys()):
    L, T, R, B, S, name = maps[n]
    W = (R-L)/2
    H = (T-B)/2
    for i in range(2):
        for j in range(2):
            maps["%s%i%i" % (n, i, j)] = [L + i * W, T - j * H, L + (i + 1) * W, T - (j + 1) * H, S, name]
# Keys in the order in which we want the maps output
mapcodes = ["all", "grieß","40", "76", "204", "tc"] 
# Field codes
L = 0
T = 1
R = 2
B = 3
ZOOM = 4
DESC = 5
SIZE = 5

areacolours = {
	'1a' : '#00ffff',
	'1b' : '#ff00ff',
	'1c' : '#ffff00',
	'1d' : '#ffffff',
	'2a' : '#ff0000',
	'2b' : '#00ff00',
	'2c' : '#008800',
	'2d' : '#ff9900',
	'3'  : '#880000',
	'4'  : '#0000ff',
	'6'  : '#000000', # doubles for surface fixed pts, and anything else
	'7'  : '#808080'
	}

for FONT in [
		"/usr/share/fonts/truetype/freefont/FreeSans.ttf",
		"/usr/X11R6/lib/X11/fonts/truetype/arial.ttf",
		"/mnt/c/windows/fonts/arial.ttf",
		"C:\WINNT\Fonts\ARIAL.TTF"
		]:
	if os.path.isfile(FONT): break
TEXTSIZE = 16
CIRCLESIZE =8
LINEWIDTH = 2
myFont = ImageFont.truetype(FONT, TEXTSIZE)
#print(f' - myFont {myFont} {FONT} {TEXTSIZE}')

def mungecoord(x, y, mapcode, img):
	# Top of Zinken is 73 1201 = dataset 34542 81967
	# Top of Hinter is 1073 562 = dataset 36670 83317
	# image is 1417 by 2201
	# FACTOR1 = 1000.0 / (36670.0-34542.0)
	# FACTOR2 = (1201.0-562.0) / (83317 - 81967)
	# FACTOR = (FACTOR1 + FACTOR2)/2 
	# The factors aren't the same as the scanned map's at a slight angle. I
	# can't be bothered to fix this.  Since we zero on the Hinter it makes
	# very little difference for caves in the areas round 76 or 204.
	# xoffset = (x - 36670)*FACTOR
	# yoffset = (y - 83317)*FACTOR
	# return (1073 + xoffset, 562 - yoffset)

	m = maps[mapcode]
	factorX, factorY = img.size[0] / (m[R] - m[L]), img.size[1] / (m[T] - m[B])
	return ((x - m[L]) * factorX, (m[T] - y) * factorY)
	
COL_TYPES = {True: "red",
             False: "#dddddd",
             "Reference": "#dddddd"}
	

def prospecting_image(request, name):
    '''This draws map outlines on an existing map image.
    But getting the entrances plotted is broken by later changes elsewhere in the system since this code was written.

    SurvexStations are in x=latitude, y=longitude - these are what appear in essentials.gpx 
    Entrances are in northing, easting
    
    which is why we can't simply plot all the Entrances...
    
    We should replace all this with something that exports an overlay for Google Maps and OpenStreetView    
    '''
    
    mainImage = Image.open(os.path.join(settings.EXPOFILES, "location_maps", "pguidemap.jpg"))
    # if settings.PUBLIC_SITE and not request.user.is_authenticated:
        # mainImage = Image.new("RGB", mainImage.size, '#ffffff')
    m = maps[name]
    imgmaps = []
    if name == "all":
        img = mainImage
    else:
        M = maps['all']
        W, H = mainImage.size
        l = int((m[L] - M[L]) / (M[R] - M[L]) * W)
        t = int((m[T] - M[T]) / (M[B] - M[T]) * H)
        r = int((m[R] - M[L]) / (M[R] - M[L]) * W)
        b = int((m[B] - M[T]) / (M[B] - M[T]) * H)
        img = mainImage.crop((l, t, r, b))
        w = int(round(m[ZOOM] * (m[R] - m[L]) / (M[R] - M[L]) * W))
        h = int(round(m[ZOOM] * (m[B] - m[T]) / (M[B] - M[T]) * H))
        img = img.resize((w, h), Image.BICUBIC)
    draw = ImageDraw.Draw(img)
    #draw.setfont(myFont)
    if name == "all":
        for maparea in list(maps.keys()):
            if maparea == "all":
                continue
            localm = maps[maparea]
            l,t = mungecoord(localm[L], localm[T], "all", img)
            r,b = mungecoord(localm[R], localm[B], "all", img)
            text = maparea + " map"
            textlen = draw.textsize(text)[0] + 3
            draw.rectangle([l, t, l+textlen, t+TEXTSIZE+2], fill='#ffffff')
            draw.text((l+2, t+1), text, fill="#000000", font=myFont)
            imgmaps.append( [l, t, l+textlen, t+SIZE+2, "submap" + maparea, maparea + " subarea map"] )
            draw.line([l, t, r, t], fill='#777777', width=LINEWIDTH)
            draw.line([l, b, r, b], fill='#777777', width=LINEWIDTH)
            draw.line([l, t, l, b], fill='#777777', width=LINEWIDTH)
            draw.line([r, t, r, b], fill='#777777', width=LINEWIDTH)
            draw.line([l, t, l+textlen, t], fill='#777777', width=LINEWIDTH)
            draw.line([l, t+TEXTSIZE+2, l+textlen, t+TEXTSIZE+2], fill='#777777', width=LINEWIDTH)
            draw.line([l, t, l, t+TEXTSIZE+2], fill='#777777', width=LINEWIDTH)
            draw.line([l+textlen, t, l+textlen, t+TEXTSIZE+2], fill='#777777', width=LINEWIDTH)
    #imgmaps[maparea] = []
    
    # Draw scale bar
    m100 = int(100 / (m[R] - m[L]) * img.size[0])
    draw.line([10, TEXTSIZE*3, 10, TEXTSIZE*2], fill='#000000', width=LINEWIDTH)
    draw.line([10, TEXTSIZE*2, 10+m100, TEXTSIZE*2], fill='#000000', width=LINEWIDTH)
    draw.line([10+m100, TEXTSIZE * 3, 10+m100, TEXTSIZE*2], fill='#000000', width=LINEWIDTH)
    label = "100m"
    draw.text([10 + (m100 - draw.textsize(label)[0]) / 2, TEXTSIZE/2], label, fill='#000000', font=myFont)

    # Draw the circles for known points 
    # Northing, Easting, Diameter - but N&E are swapped re database
    for (N, E, D, num) in [(35975.37,    83018.21,    100,   "177"),    # Calculated from bearings
                           (35350.00,    81630.00,    50,    "71"),    # From Auer map
                           (36025.00,    82475.00,    50,    "146"),    # From mystery map
                           (35600.00,    82050.00,    50,    "35"),    # From Auer map
                           (35650.00,    82025.00,    50,    "44"),    # From Auer map
                           (36200.00,    82925.00,    50,    "178"),    # Calculated from bearings
                           (35232.64,    82910.37,    25,    "181"),    # Calculated from bearings
                           (35323.60,    81357.83,    50,    "74")    # From Auer map
                           ]:
        (N,E,D) = list(map(float, (N, E, D)))
        maparea = Cave.objects.get(kataster_number = num).getArea().short_name
        lo = mungecoord(N-D, E+D, name, img)
        hi = mungecoord(N+D, E-D, name, img)
        lpos = mungecoord(N-D, E, name, img)
        draw.ellipse([lo,hi], outline="#000000")
        draw.ellipse([lo[0]+1, lo[1]+1, hi[0]-1, hi[1]-1], outline=areacolours[maparea])
        draw.ellipse([lo[0]+2, lo[1]+2, hi[0]-2, hi[1]-2], outline=areacolours[maparea])
        draw.rectangle([lpos[0],lpos[1]-TEXTSIZE/2, lpos[0] + draw.textsize(name)[0], lpos[1]+TEXTSIZE/2], fill="#ffffff")
        draw.text((lpos[0], lpos[1]-TEXTSIZE/2), num, fill="#000000")
        #print(f' CIRCLES - {num} {(N,E,D)}')
  
    # ml = MapLocations()
    # for p in ml.points():
        # surveypoint, number,  point_type, label = p
        # print(f'{surveypoint}, {number},  {point_type}, {label}')
        # plot(surveypoint, number,  True, label, name, draw, img)
    # print(f'{name},\n{draw},\n{img}')
    
    ents = Entrance.objects.all() # only has entrances and fixed points in it these days, 
    # but there are only 11 Entrances with northing, easting and a useable tag!
    D = 50
    for e in ents:
        try:
            E, N = e.easting, e.northing
            if e.tag_station:
                st = e.tag_station
            elif e.exact_station:
                st = e.exact_station
            elif e.exact_station:
                st = e.exact_station
            else:
                # print(f' No tag    - {e.name}   ')
                continue
            if not e.northing:
                continue
            lo = mungecoord(N-D, E+D, st, img)
            hi = mungecoord(N+D, E-D, st, img)
            lpos = mungecoord(N-D, E, st, img)
            
            draw.ellipse([lo,hi], outline="#000000")
            draw.ellipse([lo[0]+1, lo[1]+1, hi[0]-1, hi[1]-1], outline="#ffffff")
            draw.ellipse([lo[0]+2, lo[1]+2, hi[0]-2, hi[1]-2], outline="#ffffff")
            draw.rectangle([lpos[0],lpos[1]-TEXTSIZE/2, lpos[0] + draw.textsize(st)[0], lpos[1]+TEXTSIZE/2], fill="#ffffff")
            draw.text((lpos[0], lpos[1]-TEXTSIZE/2), num, fill="#000000")
     
            # draw.ellipse([(x-CIRCLESIZE,y-CIRCLESIZE),(x+CIRCLESIZE,y+CIRCLESIZE)], fill="red", outline="blue")
            # draw.rectangle([(x+CIRCLESIZE, y-TEXTSIZE/2), (x+CIRCLESIZE*2+draw.textsize(shortnumber)[0], y+TEXTSIZE/2)], fill="#ffffff")
            # draw.text((x+CIRCLESIZE * 1.5,y-TEXTSIZE/2), shortnumber, fill="#000000")
            #print(f' SUCCESS - {st} {(E, N)}   ')
        except:
            #print(f' FAIL    - {st}  {(E, N)} ')
            pass

    response = HttpResponse(content_type = "image/png")
    del draw
    img.save(response, "PNG")
    return response

# def plot(surveypoint, number,  point_type, label, mapcode, draw, img):
    # try:
        # ss = SurvexStation.objects.lookup(surveypoint)
        # E, N = ss.x, ss.y
        # shortnumber = number.replace("—","")
        # (x,y) = list(map(int, mungecoord(E, N, mapcode, img)))
        # imgmaps[maparea].append( [x-4, y-SIZE/2, x+4+draw.textsize(shortnumber)[0], y+SIZE/2, shortnumber, label] )
        # draw.rectangle([(x+CIRCLESIZE, y-TEXTSIZE/2), (x+CIRCLESIZE*2+draw.textsize(shortnumber)[0], y+TEXTSIZE/2)], fill="#ffffff")
        # draw.text((x+CIRCLESIZE * 1.5,y-TEXTSIZE/2), shortnumber, fill="#000000")
        # draw.ellipse([(x-CIRCLESIZE,y-CIRCLESIZE),(x+CIRCLESIZE,y+CIRCLESIZE)], fill=COL_TYPES[point_type], outline="#000000")
        # print(f' SUCCESS - YES {surveypoint}, {number},  {point_type}, {label}')
    # except:
        # print(f'         - NO  {surveypoint}, {number},  {point_type}, {label}')
        # pass