# Pyhton on windows

from urllib.request import urlopen
from datetime import date
# from neopixel import *

import json, time, sys, random, string

import pygame
from pygame.locals import *

YourKey = '21de2debd39d187e'

ledpin  = 18
numrows = 16
ledsrow = 18
numleds = numrows * ledsrow

black = Color (0,0,0)

#
# weather Underground data
#

def weatherForecast(YourKey):
    try:
        weatherUrl = urlopen('http://api.wunderground.com/api/' + YourKey + '/forecast/q/NL/Twenthe%20Air%20Base.json')
        json_string = weatherUrl.read()
        forecast_json = json.loads(json_string.decode('utf-8'))

#       with open('forecast.txt', 'w') as jsonfile:
#           json.dump(forecast_json, jsonfile)
#       jsonfile.close()

        temp_high0 = forecast_json['forecast']['simpleforecast']['forecastday'][0]['high']['celsius']
        temp_low0  = forecast_json['forecast']['simpleforecast']['forecastday'][0]['low']['celsius']
        temp_high1 = forecast_json['forecast']['simpleforecast']['forecastday'][1]['high']['celsius']
        temp_low1  = forecast_json['forecast']['simpleforecast']['forecastday'][1]['low']['celsius']

        weatherUrl.close

        if str(temp_high0) != "":
            temp_high0 = int(float(temp_high0)*10)
        else:
            temp_high0 = int(float(temp_high1)*10)

        if str(temp_high1) != "":
            temp_high1 = int(float(temp_high1)*10)
        else:
            temp_high1 = int(float(temp_high0)*10)

        if str(temp_low0) != "":
            temp_low0  = int(float(temp_low0)*10)
        else:
            temp_low0  = int(float(temp_low1)*10)

        if str(temp_low1) != "":
            temp_low1  = int(float(temp_low1)*10)
        else:
            temp_low0  = int(float(temp_low0)*10)

    except Exception as diag:
        temp_high0 = 400
        temp_low0 = -200
        temp_high1 = 400
        temp_low1 = -200
        print(diag.__class__.__name__,':',diag)

    return min(temp_low0, temp_low1), max(temp_high0, temp_high1)

#
# weather Underground data
#

def weatherConditions(YourKey):
    try:
        weatherUrl = urlopen('http://api.wunderground.com/api/' + YourKey + '/conditions/q/NL/Twenthe%20Air%20Base.json')
        json_string = weatherUrl.read()
        conditions_json = json.loads(json_string.decode('utf-8'))

        with open('conditions.txt', 'w') as jsonfile:
            json.dump(conditions_json, jsonfile)
        jsonfile.close()

        temp_now = conditions_json['current_observation']['temp_c']
        wind_dir = conditions_json['current_observation']['wind_degrees']
        wind_kph = conditions_json['current_observation']['wind_kph']
        real_rain = conditions_json['current_observation']['precip_1hr_metric'] # actual rain

        weatherUrl.close

        temp_now  = int(float(temp_now)*10)
        wind_kph  = float(wind_kph)
        real_rain = float(real_rain)

    except Exception as diag:
        temp_now = 0
        wind_dir = N
        wind_kph = 0
        real_rain = 0
        print(diag.__class__.__name__,':',diag)

    return temp_now, wind_kph, wind_dir, real_rain

#
# weather Underground data
#

def weatherHourly(YourKey):
    try:
        weatherUrl = urlopen('http://api.wunderground.com/api/' + YourKey + '/hourly/q/NL/Twenthe%20Air%20Base.json')
        json_string = weatherUrl.read()
        hourly_json = json.loads(json_string.decode('utf-8'))

#       with open('hourly.txt', 'w') as jsonfile:
#           json.dump(hourly_json, jsonfile)
#       jsonfile.close()

        hour_rain = hourly_json['hourly_forecast'][0]['qpf']['metric'] # Quantitative Precipitation Forecasts
        hour_snow = hourly_json['hourly_forecast'][0]['snow']['metric']

        weatherUrl.close()

    except Exception as diag:
        hour_rain = 0
        hour_snow = 0
        print(diag.__class__.__name__,':',diag)

    return hour_rain, hour_snow

#
# Display Data
#

def colorRange():
    today=date.today()

    if   (today.month == 1): minTempRange = -100 ; maxTempRange = 200 # Temperature values times 10
    elif (today.month == 2): minTempRange =  -50 ; maxTempRange = 250
    elif (today.month == 3): minTempRange =    0 ; maxTempRange = 250
    elif (today.month == 4): minTempRange =    0 ; maxTempRange = 300
    elif (today.month == 5): minTempRange =   50 ; maxTempRange = 300
    elif (today.month == 6): minTempRange =  100 ; maxTempRange = 350
    elif (today.month == 7): minTempRange =  100 ; maxTempRange = 300
    elif (today.month == 8): minTempRange =   50 ; maxTempRange = 300
    elif (today.month == 9): minTempRange =    0 ; maxTempRange = 300
    elif (today.month == 10):minTempRange =    0 ; maxTempRange = 300
    elif (today.month == 11):minTempRange =  -50 ; maxTempRange = 250
    else:                    minTempRange = -100 ; maxTempRange = 200

    return minTempRange, maxTempRange

#
# Lamp Class
#

class Lamp:
    def __init__(self, stick, minTemp, maxTemp):

        self.black = Color(0,0,0)
        self.white = Color(255,255,255)
        self.maxBrightBackground =  64
        self.maxBrightForeground = 255
        self.xleds = 16
        self.yleds = 18

        self.minTempRange=minTemp
        self.maxTempRange=maxTemp
        self.stick=stick

        self.colorMapRed   = []
        self.colorMapGreen = []
        self.colorMapBlue  = []
        self.backArray = []
        self.rainArray=[]
        self.windArray=[]

        self.windspeed = 2
        self.hourRain = 2

        self.ColorMap()
        self.initRain()
        self.initWind()
        self.BackGround(self.minTempRange, self.maxTempRange)
#       self.showLeds(self.backArray)

    #
    # Creates an array with colors
    #

    def ColorMap(self):
        minRange   = abs(self.minTempRange)+1
        plusRange  = int(self.maxTempRange/2)+1
        minFactor  = abs(self.maxBrightBackground/minRange)
        plusFactor = self.maxBrightBackground/plusRange

        resultRed   = []
        resultGreen = []
        resultBlue  = []

        for x in range (plusRange):
                resultRed.append   (int(self.maxBrightBackground))
                resultGreen.append (int(self.maxBrightBackground-x*plusFactor))
                resultBlue.append  (int(0))

        for x in range (plusRange):
                resultRed.append   (int(self.maxBrightBackground-x*plusFactor/2))
                resultGreen.append (int(0))
                resultBlue.append  (int(x*plusFactor/2))

        for x in range (minRange):
                resultRed.append   (int(x*minFactor))
                resultGreen.append (int(x*minFactor))
                resultBlue.append  (int(self.maxBrightBackground-x*minFactor))

        self.colorMapRed   = resultRed
        self.colorMapGreen = resultGreen
        self.colorMapBlue  = resultBlue

    def BackGround(self, temp_low, temp_high):
        thisArray = []
        for i in range (self.xleds * self.yleds):
            thisArray.append (i)

        for t in range (self.yleds):
            cindx = int (temp_low + (temp_high-temp_low)*t/self.yleds)
            color = Color(self.colorMapGreen[cindx],self.colorMapRed[cindx],self.colorMapBlue[cindx])
            for r in range (self.xleds):
                thisArray[numleds-1 -(t+r*self.yleds)]=color

        self.backArray = thisArray

    def initRain(self):
        for i in range (self.xleds * self.yleds):
            self.rainArray.append (i)
            self.rainArray[i] = self.black

    def initWind(self):
        for i in range (self.xleds * self.yleds):
            self.windArray.append (i)
            self.windArray[i] = self.black

    def rainMoveDown(self):
        for i in range (16):
            for j in range (17, 0, -1):
                self.rainArray [i*18+j] = self.rainArray [i*18+j-1]
            self.rainArray [i*18] = self.black

        for i in range (self.hourRain):
            x = random.randint(0,15)
            c = random.randint(100,200)
            self.rainArray[x*18]=Color(c,c,255)

    def windMoveDir(self,windDir,windSpeed):

        if   (windSpeed < 1  ): insertLeds =  0
        elif (windSpeed < 6  ): insertLeds =  1
        elif (windSpeed < 12 ): insertLeds =  2
        elif (windSpeed < 20 ): insertLeds =  3
        elif (windSpeed < 29 ): insertLeds =  4
        elif (windSpeed < 39 ): insertLeds =  5
        elif (windSpeed < 50 ): insertLeds =  6
        elif (windSpeed < 62 ): insertLeds =  7
        elif (windSpeed < 75 ): insertLeds =  8
        elif (windSpeed < 89 ): insertLeds =  9
        elif (windSpeed < 103): insertLeds = 10
        elif (windSpeed < 117): insertLeds = 11
        else:                   insertLeds = 12

        if   (windDir <=  11.25): windLed = 0
        elif (windDir <=  33.75): windLed = 1
        elif (windDir <=  56.25): windLed = 2
        elif (windDir <=  78.75): windLed = 3
        elif (windDir <= 101.25): windLed = 4
        elif (windDir <= 123.75): windLed = 5
        elif (windDir <= 146.25): windLed = 6
        elif (windDir <= 168.75): windLed = 7
        elif (windDir <= 191.25): windLed = 8
        elif (windDir <= 213.75): windLed = 9
        elif (windDir <= 236.25): windLed = 10
        elif (windDir <= 258.75): windLed = 11
        elif (windDir <= 281.25): windLed = 12
        elif (windDir <= 303.75): windLed = 13
        elif (windDir <= 326.25): windLed = 14
        elif (windDir <= 348.75): windLed = 15
        else:                     windLed = 0

        windStartLed = (windLed+8)%16
        print (windStartLed, windLed, insertLeds)

        for j in range (self.yleds):
            for i in range (0, 8):
                self.windArray[(windLed*18 + (i * 18) + j)%288] = self.windArray[(windLed*18 + (i * 18) + j + 18)%288]
                self.windArray[(windLed*18 - (i * 18) + j)%288] = self.windArray[(windLed*18 - (i * 18) + j - 18)%288]

        for y in range (18):
            self.windArray[windStartLed*18+y]= self.black

        for i in range (self.hourRain):
            y = random.randint(0,17)
            r = random.randint(150,250)
            g = random.randint(150,250)
            b = random.randint(150,250)
            self.windArray[windStartLed*18+y]=Color(r,g,b)

    def showLeds(self, colorArray):
        for j in range (self.yleds):
            for i in range (0, 8):
                self.stick.setPixelColor(i*self.yleds*2+j, colorArray [i*self.yleds*2+j])
                self.stick.setPixelColor(self.yleds+i*self.yleds*2+self.yleds-j-1, colorArray [self.yleds+i*self.yleds*2+j])
        self.stick.show()

    def showLed (self, x, y, color):
        j=y
        i=int(x/2)
        if x%2 == 0:
        	self.stick.setPixelColor(i*self.yleds*2+j, color)
        else:
          self.stick.setPixelColor(self.yleds+i*self.yleds*2+self.yleds-j-1, color)
        self.stick.show()

    def getPixel(self, x, y, array):
        p=x*18+y
        color=array[p]
        hexval=str(hex(color))
        r=int("0x"+hexval[2:4],16)
        g=int("0x"+hexval[4:6],16)
        b=int("0x"+hexval[6:8],16)
        return r,g,b

    def setPixel(self, x, y, color, array):
        p=x*18+y
        array[p]=color
        return

#
# Neopixel Simulator
#

class WS2812:
    def __init__(self,color,screen):
        self.c = color
        self.screen = screen
        self.draw()

    def draw(self):
        for x in range (numrows):
            for y in range (ledsrow):
                r=self.c[287-(x*ledsrow+y)].r
                g=self.c[287-(x*ledsrow+y)].g
                b=self.c[287-(x*ledsrow+y)].b
                led = pygame.draw.rect (screen,(r,g,b),(32+x*24,16+ledsrow*24-y*24,24-8,24-8))
        pygame.display.update ()

    def color(self,color):
        self.c = color
        self.draw ()

#
# Main
#

pygame.init()                                                            # test
screen = pygame.display.set_mode ((64+numrows*24,32+64+ledsrow*24),0,32) # test
screen.fill ((255,255,255))                                              # test
pygame.display.set_caption ('WeatherLamp')                               # test


#stick = Adafruit_NeoPixel(numleds, ledpin, 800000, 5, False, 255)
#stick.begin()
stick=1

minTempRange, maxTempRange = colorRange()

temp_low,temp_high = weatherForecast(YourKey)
hour_rain, hour_snow = weatherHourly(YourKey)
weatherLamp = Lamp (stick, minTempRange, maxTempRange)


temp_now, wind_kph, wind_dir, real_rain=weatherConditions(YourKey)

print (temp_now, wind_kph, wind_dir, real_rain)

led = WS2812 (weatherLamp.backArray,screen)
time.sleep (2)

wind_dir   = 180 # test
wins_speed = 8

weatherLamp.hourRain=2 #testvalue
for x in range (10):
    weatherLamp.windMoveDir(wind_dir, wind_kph)
#   weatherLamp.showLeds (weatherLamp.rainArray)
    led.color (weatherLamp.windArray)
    pygame.image.save(screen, "screenshot"+str(x)+".png")

    time.sleep (.2)

weatherLamp.hourRain=0
for x in range (20):
    weatherLamp.windMoveDir(wind_dir, wind_kph)
#   weatherLamp.showLeds (weatherLamp.rainArray)
    led.color (weatherLamp.windArray)
    pygame.image.save(screen, "screenshot"+str(x+10)+".png")
    time.sleep (.2)

