#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# System modules
from datetime import datetime, timedelta

# Third-party modules
import numpy as np
from pyvantagepro import VantagePro2
from pyvantagepro.device import NoDeviceException

# Custom modules
from utils import check
from utils.logger import log


class Meteo:
    def __init__(self, url):
        self.url = url
        self.error = None
        self.station = None
        
    @check.telnet_errors
    def connect(self):
            self.station = VantagePro2.from_url(self.url)

    @property
    def original(self):
        self.connect()

        if self.station:
            try:
                current = self.station.get_current_data()
                params = {k: current[k] for k in current.keys()}
            except BrokenPipeError as e:
                params = None
            except NoDeviceException:
                params = None
                
        else:
            params = None
            
        return params

    @property
    def data(self):
        params = self.original
        if not params:
            conv = None

        else:
            tempout = round((params['TempOut']-32)*5./9, 1)
            humout = params['HumOut']
            dewpoint = round(tempout - ((100. - humout)/5), 1)
            
            inches_to_mm = 25.4
            mph_to_kmh = 1.60934
            
            conv = {  # Come conversion in SI units
                "Datetime": params["Datetime"].isoformat()[:-7],
                # °F to °C
                "Temperature_first_floor": round((params['TempIn']-32)*5./9, 1),
                "Humidity_first_floor": params["HumIn"],
                "Temperature_meteo_station":  tempout,  # °F to °C
                "Humidity_meteo_station": humout,
                "Dewpoint": dewpoint,
                # inHg to hPa
                "Barometer": round(params["Barometer"] * 33.8638, 1),
                "Barometric_trend":  params["BarTrend"],
                # mph to Km/h
                "Wind_speed": round(params["WindSpeed"]*mph_to_kmh, 1),
                # mph to Km/h
                "Wind_speed_last_10_min": round(params["WindSpeed10Min"]*mph_to_kmh, 1),
                "Wind_direction": params["WindDir"],
                "Rain_rate": params["RainRate"],
                "UV": params["UV"],
                "Solar_radiation": params["SolarRad"],
                "Rain_storm": params["RainStorm"]*inches_to_mm,
                "Storm_start_date": params["StormStartDate"],
                "Rain_day": params["RainDay"],
                "Rain_month": params["RainMonth"],
                "Rain_year": params["RainYear"],
                "ET_day": round(params["ETDay"] * inches_to_mm, 0),  # inches to mm
                # inches to mm
                "ET_month": round(params["ETMonth"] * inches_to_mm, 0),
                # inches to mm
                "ET_year": round(params["ETYear"] * inches_to_mm, 0),
                "Battery_status": params["BatteryStatus"],
                "Battery_volts": round(params["BatteryVolts"], 2),
                "Forecast_icon": params["ForecastIcon"],
                "Forecast_rule_number": params["ForecastRuleNo"],
                "Sun_rise": params["SunRise"],
                "Sun_set": params["SunSet"],
            }
            
        return conv

    def summary(self):
        params0 = self.data
        print(f"Summary:")
        print(f"Datetime  { params0['Datetime']}")
        print(f"Dew Point { params0['Dewpoint'] :.1f}°")
        print(f"TempIn    { params0['TempIn'] :.1f}°")
        print(f"TempOut   { params0['TempOut'] :.1f}°")
        print(f"HumIn     { params0['HumIn'] }%")
        print(f"HumOut    { params0['HumOut'] }%")
        print(f"WindSpeed { params0['WindSpeed'] :.1f} km/h")
        print(f"Barometer { params0['Barometer'] :.1f} hPa")

    @property
    def time(self):
        self.connect()
        current = self.station.gettime().isoformat()
        return current

    def synctime(self):
        self.connect()
        now = datetime.now()
        print(now)
        self.station.settime(now)

    def archive(self):
        now = datetime.now()
        now = datetime(year=now.year, month=now.month,
                       day=now.day, hour=now.hour)
        older = now - timedelta(days=4, hours=22)  # max 4 days, 22:00:00

        self.connect()
        archive = self.station.get_archives(older, now)  # takes some seconds
        params = {k: np.array([a[k] for a in archive])
                  for k in archive[0].keys()}

        return params


def main():

    now = datetime.now()
    now = datetime(year=now.year, month=now.month, day=now.day, hour=now.hour)
    older = now - timedelta(days=4, hours=22)  # max 4 days, 22:00:00

    m = Meteo("tcp:meteo.orsa.unige.net:5001")
    m.summary()

    # System modules
    import json
    print(f"All data:")
    print(json.dumps(m.data, indent=4))

    # params = m.archive() # takes some seconds
    #params = { k: np.array([a[k] for a in archive ]) for k in archive[0].keys() }

    # from matplotlib import pyplot as plt
    # params = m.archive() # takes some seconds
    # params = { k: np.array([a[k] for a in archive ]) for k in archive[0].keys() }

    # fig, axs = plt.subplots(2, 2)

    # date = params["Datetime"]

    # axs[0,0].title.set_text('Temperature out/in/dewpoint')
    # axs[0,0].plot(date, (params["TempOut"]-32)*5./9.)
    # axs[0,0].plot(date, (params["TempIn"]-32)*5./9.)
    # dewplot = ( (params['TempOut']-32)*5./9.) - ((100. - params['HumOut'])/5.)
    # axs[0,0].plot(date, dewplot)
    # axs[0,0].set(ylabel='°C')

    # axs[0,1].title.set_text('Humidity out/in')
    # axs[0,1].plot(date, params["HumOut"])
    # axs[0,1].plot(date, params["HumIn"])
    # axs[0,1].set(ylabel='%')

    # axs[1,0].title.set_text('Wind speed avg/hi')
    # axs[1,0].plot(date, params['WindAvg']*mph_to_kmh)
    # axs[1,0].plot(date, params['WindHi']*mph_to_kmh)
    # axs[1,0].set(ylabel='Km/h')

    # axs[1,1].title.set_text('Pressure')
    # axs[1,1].plot(date, params['Barometer']*33.8638)
    # axs[1,1].set(ylabel='hPa')

    # for ax in axs.flat:
    #     ax.set(xlabel='Date')

    # # # Hide x labels and tick labels for top plots and y ticks for right plots.
    # # for ax in axs.flat:
    # #     ax.label_outer()

    # plt.show()


if __name__ == "__main__":
    main()


#############################################################

# dic = ['Datetime', 'TempOut', 'TempOutHi', 'TempOutLow', 'RainRate', 'RainRateHi', 'Barometer', 'SolarRad', 'WindSamps', 'TempIn', 'HumIn', 'HumOut', 'WindAvg', 'WindHi', 'WindHiDir', 'WindAvgDir', 'UV', 'ETHour', 'SolarRadHi', 'UVHi', 'ForecastRuleNo']

# datadict = {
#     "Datetime": "date",
#     "TempOut": "outside temp (°F)",
#     "TempOutHi": "outside temp high (°F)",
#     "TempOutLow": "outside temp low (°F)",
#     "RainRate": "rainfall (clicks)", 1 click = 0.2mm?? "by stefano90"
#     "RainRateHi": "highest rain rate (clicks/hr)",
#     "Barometer": "barometer (inches Hg)",
#     "SolarRad": "average solar radiation (W/m^2)",
#     "WindSamps": "number of wind samples",
#     "TempIn": "insideTemp (°F)",
#     "HumIn": "inside humidity (%)",
#     "HumOut": "outside humidity (%)",
#     "WindAvg": "average wind speed (mph)",
#     "WindHi": "highest wind speed (mph)",
#     "WindHiDir": "highest wind direction (°)",
#     "WindAvgDir": "prevailing wind direction (°)",
#     "UV": "average uv index",
#     "ETHour": "accumulated et (in)", EvapoTranspiration (ET)
#     "SolarRadHi": "maximum solar radiation (W/m^2)",
#     "UVHi": "max uv",
#     "ForecastRuleNo": "forecast at end of period",
# }
