# -*- coding: utf-8 -*-

from PyQt5.QtWidgets import (QWidget, QSlider, QApplication, 
    QHBoxLayout, QVBoxLayout, QLabel, QLineEdit, QDesktopWidget, QPushButton, QComboBox)
from PyQt5.QtCore import QObject, Qt
from PyQt5.QtGui import QPainter, QFont, QColor, QPen, QImage, QPixmap

from perlin import PerlinNoise

import matplotlib.pyplot as pp
import numpy as np
from math import floor,ceil
import threading
import sys

try: application
except NameError: application = QApplication([])

class MapNavigator(QWidget):
    
    carte = QLabel()
    
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Navigateur")
        
        ### Centrer la fenetre ###
        
        self.resize(750,505)
        
        self.initFrame()
        
        
        self.show()
        self.centrer()
    
    def centrer(self):
        qtRectangle = self.frameGeometry()
        centerPoint = QDesktopWidget().availableGeometry().center()
        qtRectangle.moveCenter(centerPoint)
        self.move(qtRectangle.topLeft())
        
        
    def initFrame(self):
        ##### Config #####
        
        globalayout = QHBoxLayout()
        
        configl = QVBoxLayout()
        configl.setAlignment(Qt.AlignTop)
        
        ##  Fichier ##
        fichier = QHBoxLayout()
        fichierlabel = QLabel("Fichier :")
        fichiertext = QLineEdit()
        fichier.addWidget(fichierlabel)
        fichier.addWidget(fichiertext)
        
        ## Refresh ##
        refresh = QPushButton("Refresh")
        
        ## Coords ##
        Xs = QHBoxLayout()
        posxlabel = QLabel("x:")
        posxtext = QLineEdit()
        lxlabel = QLabel("lx:")
        lxtext = QLineEdit()
        Xs.addWidget(posxlabel)
        Xs.addWidget(posxtext)
        Xs.addWidget(lxlabel)
        Xs.addWidget(lxtext)
        
        Ys = QHBoxLayout()
        posylabel = QLabel("y:")
        posytext = QLineEdit()
        lylabel = QLabel("ly:")
        lytext = QLineEdit()
        Ys.addWidget(posylabel)
        Ys.addWidget(posytext)
        Ys.addWidget(lylabel)
        Ys.addWidget(lytext)
        
        ## Redraw ##
        redraw = QPushButton("Redraw")
        
        ## Colormap ##
        colormap = QHBoxLayout()
        colormaplabel = QLabel("Color map :")
        colormapchooser = QComboBox()#["Noir","Blanc","Rouge","Vert","Bleu"])
        colormap.addWidget(colormaplabel)
        colormap.addWidget(colormapchooser)
        
        

        configl.addLayout(fichier)
        configl.addWidget(refresh)
        configl.addLayout(Xs)
        configl.addLayout(Ys)
        configl.addWidget(redraw)
        configl.addLayout(colormap)
        globalayout.addLayout(configl)
        globalayout.addWidget(self.carte)
        
        self.setLayout(globalayout)
        
    lastx,lasty = None,None
    def mouseMoveEvent(self,e):
        dx,dy = e.x() - self.lastx,e.y() - self.lasty
        print(dx/self.generator.w*self.generator.rx,dy/self.generator.h*self.generator.ry)
        self.lastx,self.lasty = e.x(),e.y()
        self.generator.x += dx/self.generator.w*self.generator.rx
        self.generator.y += dy/self.generator.h*self.generator.ry
    def mousePressEvent(self,e):
        self.lastx,self.lasty = e.x(),e.y()
    def mouseReleaseEvent(self,e):
        self.lastx,self.lasty = None,None
        
    def closeEvent(self,e):
        self.generator.running = False
        
    
    def getChunk(self,x,y,rx,ry):
        
        if (x,y) not in self.generated:
            self.genqueue.append((x,y))
            return np.zeroes((rx,ry))
        return self.generated[(x,y)]
    
    
    def updateImage(self):
        x,y = self.x,self.y
        rx,ry = self.rx,self.ry
        w,h = self.w,self.h
        lx,ly = w/rx,h/ry
        
        #out = np.zeros((self.WIDTH,self.HEIGTH))
        
        x0 = x-lx/2
        x1 = x+lx/2
        y0 = y-ly/2
        y1 = y+ly/2
        
        cx0,cy0 = int((x0-floor(x0))*rx),int((y0-floor(y0))*ry)
        cx1,cy1 = int((x1-floor(x1))*rx),int((y1-floor(y1))*ry)
        zx,zy = int((1+floor(x0)-x0)*rx),int((1+floor(y0)-y0)*ry)
        
        print(x0,x1,y0,y1,cx0,cy0,w,h,lx,ly)
        for i in range(floor(x0),floor(x1)+1):
            
            for j in range(floor(y0),floor(y1)+1):
                chk = self.getChunk(i,j,rx,ry)
                
                cx,dx = cx0 if i==floor(x0) else 0 , cx1 if i==floor(x1) else rx
                cy,dy = cy0 if j==floor(y0) else 0 , cy1 if j==floor(y1) else ry
                
                ax,ay = 0 if i==floor(x0) else zx+(i-floor(x0)-1)*rx , 0 if j==floor(y0) else zy+(j-floor(y0)-1)*ry
                bx,by = ax + (dx-cx) , ay + (dy-cy)
                
                
                print(i,j,"->",ax,bx,cx,dx,ay,by,cy,dy)
                out[ax:bx,ay:by] = chk[cx:dx,cy:dy]
                
                
        
        self.setImage(out)
        
        
class Generator(threading.Thread):
    
    label = None
    
    noise = None
    
    generated = {}
    genqueue = []
    
    running = True
    
    x,y = 0,0
    rx,ry = 256,256
    w,h = 512,512
    
    def __init__(self,linkedLabel,noise):
        super().__init__()
        self.label = linkedLabel
        self.noise = noise
        
    def getChunk(self,x,y,rx,ry):
        
        if (x,y) not in self.generated:
            self.genqueue.append((x,y))
            chunk = self.noise.getChunk(x,y,(rx,ry))
            self.generated[(x,y)] = chunk
        return self.generated[(x,y)]
               

    def setImage(self,im):
        im = np.uint8((im - im.min())/im.ptp()*255.0)
        
        qi = QImage(im.data, im.shape[1], im.shape[0], im.shape[1], QImage.Format_Indexed8)
        
        qp = QPixmap.fromImage(qi)

        self.label.setPixmap(qp)
        
    
    def run(self):
        out = np.zeros((self.w,self.h))
        while(self.running):
            x,y = self.x,self.y
            rx,ry = self.rx,self.ry
            w,h = self.w,self.h
            lx,ly = w/rx,h/ry
            
            #out = np.zeros((self.WIDTH,self.HEIGTH))
            
            x0 = x-lx/2
            x1 = x+lx/2
            y0 = y-ly/2
            y1 = y+ly/2
            
            cx0,cy0 = int((x0-floor(x0))*rx),int((y0-floor(y0))*ry)
            cx1,cy1 = int((x1-floor(x1))*rx),int((y1-floor(y1))*ry)
            zx,zy = int((1+floor(x0)-x0)*rx),int((1+floor(y0)-y0)*ry)
            
            print(x0,x1,y0,y1,cx0,cy0,w,h,lx,ly)
            for i in range(floor(x0),floor(x1)+1):
                
                for j in range(floor(y0),floor(y1)+1):
                    self.setImage(out)
                    chk = self.getChunk(i,j,rx,ry)
                    
                    cx,dx = cx0 if i==floor(x0) else 0 , cx1 if i==floor(x1) else rx
                    cy,dy = cy0 if j==floor(y0) else 0 , cy1 if j==floor(y1) else ry
                    
                    ax,ay = 0 if i==floor(x0) else zx+(i-floor(x0)-1)*rx , 0 if j==floor(y0) else zy+(j-floor(y0)-1)*ry
                    bx,by = ax + (dx-cx) , ay + (dy-cy)
                    
                    
                    print(i,j,"->",ax,bx,cx,dx,ay,by,cy,dy)
                    out[ax:bx,ay:by] = chk[cx:dx,cy:dy]
                    
                    
            
            self.setImage(out)
    print('Bybye !')
    


nav = MapNavigator()

seed=42
perl1 = PerlinNoise(10 ,seed)
perl2 = PerlinNoise(5 ,seed)
perl3 = PerlinNoise(1 ,seed)

noise = perl1+.1*perl2+.03*perl3
generator = Generator(nav.carte,noise)
nav.generator = generator
generator.start()

###### Content #####


