#!/usr/bin/env python3

from urllib.request import urlopen
from datetime import date
from neopixel import *

import json, time, sys, random, colour, string

YourKey = ''

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.hourRain = 2

        self.ColorMap()
        self.initRain()
        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):
        print ("rainInit")
        for i in range (self.xleds * self.yleds):
            self.rainArray.append (i)
            self.rainArray[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 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

#
# Main
#

stick = Adafruit_NeoPixel(numleds, ledpin, 800000, 5, False, 255)
stick.begin()

minTempRange, maxTempRange = colorRange()

temp_low,temp_high = weatherForecast(YourKey)
hour_rain, hour_snow = weatherHourly(YourKey)
weatherLamp = Lamp (stick, minTempRange, maxTempRange)

weatherLamp.hourRain=2 #testvalue
for x in range (100):
    weatherLamp.rainMoveDown()
    weatherLamp.showLeds (weatherLamp.rainArray)
    time.sleep (.2)

weatherLamp.hourRain=0
for x in range (20):
    weatherLamp.rainMoveDown()
    weatherLamp.showLeds (weatherLamp.rainArray)
    time.sleep (.2)
