#!/usr/bin/env python3
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GObject, GdkPixbuf, Gdk, Pango
from threading import Thread
import time
import weathertools as wt
import cairo
import subprocess
import getweather as gw
import os


"""
Budgie WeatherShow
Author: Jacob Vlijm
Copyright © 2017-2018 Ubuntu Budgie Developers
Website=https://ubuntubudgie.org
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or any later version. This
program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details. You
should have received a copy of the GNU General Public License along with this
program.  If not, see <http://www.gnu.org/licenses/>.
"""


# set key / city
key = wt.getkey()
currlang = wt.get_currlang()


try:
    citydata = wt.getcity()
except TypeError:
    city = 2643741
    cityname = "London, GB"
else:
    city = citydata[0]
    cityname = citydata[1]


# set_color
color = wt.hexcolor(wt.read_color(wt.textcolor))
transparency = wt.get_transparency()
# refresh cycle (seconds)
refresh_time = 15


# lists
w_icons = wt.w_icons
small_icons = wt.small_icons
markers = wt.markers
arrows = wt.arrows


font = wt.get_font()


class WeatherShow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self)

        # window props
        self.set_type_hint(Gdk.WindowTypeHint.DESKTOP)
        self.set_keep_below(True)
        self.set_position()
        # transparency
        screen = self.get_screen()
        visual = screen.get_rgba_visual()
        if all([visual, screen.is_composited()]):
            self.set_visual(visual)
        self.set_app_paintable(True)
        self.connect("draw", self.area_draw)
        # destroy
        self.connect("destroy", Gtk.main_quit)
        # maingrid
        self.maingrid = Gtk.Grid()
        self.add(self.maingrid)
        # add some space on the leftside
        left_toimage = Gtk.Label("\t")
        self.maingrid.attach(left_toimage, 0, 0, 1, 1)
        # weather image
        self.weather_image = Gtk.Image()
        self.maingrid.attach(self.weather_image, 1, 0, 1, 10)
        # add some space on the right of the image, on top of datashow
        right_toimage = Gtk.Label("\t")
        self.maingrid.attach(right_toimage, 2, 0, 1, 1)
        # data grid
        self.wshow_grid = Gtk.Grid()
        self.wshow_grid.set_row_spacing(3)
        citylabel = Gtk.Label(cityname, xalign=0)
        citylabel.modify_fg(Gtk.StateFlags.NORMAL, Gdk.color_parse(color))
        citylabel.modify_font(Pango.FontDescription(font + " 20"))
        self.maingrid.attach(citylabel, 3, 0, 2, 1)
        # wshow data content
        self.skylabel = Gtk.Label("---", xalign=0)
        self.templabel = Gtk.Label("---", xalign=0)
        self.windlabel = Gtk.Label("---", xalign=0)
        self.humidlabel = Gtk.Label("---", xalign=0)
        # grid the data in wshow
        n = 1
        for item in [
            self.skylabel, self.templabel, self.windlabel, self.humidlabel,
        ]:
            self.wshow_grid.attach(item, 0, n, 1, 1)
            n = n + 1
        # add wshow to grid
        self.maingrid.attach(self.wshow_grid, 3, 1, 1, 1)
        # set initial update time
        self.last_updated = 0
        # add some space at the end
        right_marge = Gtk.Label("\t")
        self.maingrid.attach(right_marge, 10, 0, 1, 1)
        self.maingrid.show_all()
        self.show_all()
        self.update = Thread(target=self.run_cycle)
        # daemonize the thread to make the indicator stopable
        self.update.setDaemon(True)
        self.update.start()

    def set_position(self):
        pos = wt.get_position()
        self.move(pos[1], pos[2])

    def update_ifdata(self):
        currweather = wt.get_weatherdata(key, str(city))
        if currweather:
            self.refresh(currweather)
        else:
            self.weather_image.set_from_pixbuf(w_icons[-1])

    def run_cycle(self):
        self.refresh()
        while True:
            time.sleep(refresh_time)
            curr_time = time.time()
            if curr_time - self.last_updated > 600:
                self.refresh()
                self.last_updated = curr_time

    def set_icon(self, index):
        self.weather_image.set_from_pixbuf(w_icons[index])

    def set_smallicon(self, index):
        # combine with above
        self.weather_image.set_from_pixbuf(w_icons[index])

    def set_labeltext(self, label, newtext):
        label.set_text(newtext)
        label.modify_fg(Gtk.StateFlags.NORMAL, Gdk.color_parse(color))
        label.modify_font(Pango.FontDescription(font + " 13"))

    def update_label(self, label, newlabel):
        GObject.idle_add(
            self.set_labeltext, label, newlabel,
            priority=GObject.PRIORITY_DEFAULT,
        )

    def refresh(self):
        # in any case, newdata includes all relevant keys, but val can be None
        # refresh image
        newdata = gw.get_fields(key, city, currlang)
        iconref = newdata["icon"]
        weathercode = newdata["weather_code"]
        if all([weathercode, iconref]):
            icon_id = wt.get_iconmapping(str(weathercode)) + iconref[-1]
            iconindex = markers.index(icon_id)
        else:
            iconindex = -1
        # refresh skylabel
        newsky = wt.validate_val(newdata["sky"])
        self.update_label(self.skylabel, newsky)
        # refresh temp label
        newtemp = wt.convert_temp(newdata["temp"])
        self.update_label(self.templabel, newtemp)
        # refresh / keep wind direction
        newdeg = newdata["wind_deg"]
        newdeg = arrows[round(newdeg / 45)] if newdeg else ""
        # refresh / keep wind speed
        newspeed = newdata["wind_speed"]
        newspeed = str(newspeed) + " m/s" if newspeed else ""
        # so, refresh windlabel
        new_windlabel = wt.prepare_windlabel(newdata)
        self.update_label(self.windlabel, new_windlabel)
        # update humidity
        newhumid = wt.prepare_humidlabel(newdata)
        self.update_label(self.humidlabel, newhumid)
        GObject.idle_add(
            self.set_icon, iconindex,
            priority=GObject.PRIORITY_DEFAULT,
        )

    def area_draw(self, widget, cr):
        # set transparent color
        cr.set_source_rgba(0.2, 0.2, 0.2, transparency)
        cr.set_operator(cairo.OPERATOR_SOURCE)
        cr.paint()
        cr.set_operator(cairo.OPERATOR_OVER)


WeatherShow()
GObject.threads_init()
Gtk.main()
