# -*- coding: utf-8 -*-
# Elisa - Home multimedia server
# Copyright (C) 2006-2008 Fluendo Embedded S.L. (www.fluendo.com).
# All rights reserved.
#
# This file is available under one of two license agreements.
#
# This file is licensed under the GPL version 3.
# See "LICENSE.GPL" in the root of this distribution including a special
# exception to use Elisa with Fluendo's plugins.
#
# The GPL part of Elisa is also available under a commercial licensing
# agreement from Fluendo.
# See "LICENSE.Elisa" in the root directory of this distribution package
# for details on that license.


__maintainer__ = 'Benjamin Kampmann <benjamin@fluendo.com>'

from elisa.core.common import application
from elisa.base_components.activity import Activity

from sun import suntime


from elisa.core.media_uri import MediaUri
from elisa.core import common

from weather_model import WeatherModel

import os
import time, calendar, datetime ## do we need all this
import csv ### and this?

try:
    from elisa.extern.metar import Metar
except ImportError:
    Metar = None

import string
#import rllib
import math



BASE_URL = "http://weather.noaa.gov/pub/data/observations/metar/stations"

class WeatherActivity(Activity):
    """ The weather activity is retrieving the weather informations with metar
    """
    config_doc = {'ICAO': 'Four letters designing your location; ' \
                           'a complete list can be found at ' \
                           'http://en.wikipedia.org/wiki/ICAO_airport_code'
                  }

    default_config = {"ICAO": "LEBL"
                      }


    # translation table between weather indications returned by pymetar to
    # custom pixmaps; these are in data/weather/ and supposed to be png files
    weather_to_pixmap = {"day": {
                            "sun": "clear",
                            "suncloud": "clear_cloud",
                            "cloud": "cloud",
                            "clear": "clear",
                            "fog": "fog",
                            "storm": "storm",
                            "rain": "rain",
                            "snow": "snow",
                            "unknown": "clear"
                            },
                        "night": {
                            "sun": "night_clear",
                            "suncloud": "night_clear_cloud",
                            "cloud": "night_cloud",
                            "clear": "night_clear",
                            "fog": "night_fog",
                            "storm": "night_storm",
                            "rain": "night_rain",
                            "snow": "night_snow",
                            "unknown": "night_clear"
                            }
                        }
    def initialize(self):
        Activity.initialize(self)
        self._station_code = self.config["ICAO"]
        stations_path = self.plugin.get_resource_file('/data/stations.csv')

        self._location = "couldn't look it up"
        # If there is no location name found, we've to display it
        self._latitude = 0
        self._longitude = 0
        # FIXME: do not check each time when weather config is made
        try:
            stations = csv.reader(open(stations_path, 'rb'))
            for row in stations:
                if len(row) > 7:
                    if (row[3] == self._station_code): # Looking up the location name
                        self._location = row[2] + ',' + row[0]
                        self._latitude = float(row[6])
                        self._longitude = float(row[7])
                        break
        except:
            self.warning("The location couldn't be looked up."\
                    "May be the station file %s is corrupt..." %
                            stations_path)

    def get_model(self):
        # Create a MenuNodeModel first
        registry = common.application.plugin_registry
        menu_node = registry.create_component('base:menu_node_model')
        menu_node.text = "Weather"
        menu_node.theme_icon = "weather_icon"
        menu_node.activity = self

        return menu_node

    def retrieve_weather(self):
        """ Fetches the weather information on the Internet thanks to metar
            and fill in the weather report self._report
        """
        self._report = None
        url = "%s/%s.TXT" % (BASE_URL, self._station_code)
        handler = application.media_manager.open(MediaUri(url))

        if not handler:
            self.warning("No handler for http:// found")
            return

        report = ''
        for line in handler.read(-1).splitlines():
            if line.startswith(self._station_code):
                report = line.strip()
                self._report = Metar.Metar(line)
                break
        # FIXME: There is something needed

    def get_icon_from_weather(self, weather_report):
        """ Returns a string for a icon corresponding to a given weather and time

            weather_report: report to consider containing weather and time
        """

        t = datetime.datetime.now()

        rise_time = suntime('rise', float(self._latitude),
                            float(self._longitude), 1, time.localtime()[7])
        set_time = suntime('set', float(self._latitude),
                           float(self._longitude), 1, time.localtime()[7])
        current_time = time.localtime()[3:5]

        night_time = (current_time > set_time) or (current_time < rise_time)

        weather = None

        for i in self._report.sky:
            for j in i:
                if (j == "SKC") or (j == "CLR"):
                    sky_weather = "sun"
                elif (j == "FEW") or (j == "SCT"):
                    sky_weather = "suncloud"
                elif (j == "FEW") or (j == "SCT"):
                    weather = "cloud"
                    break

        for i in self._report.weather:
            for j in i:
                if (j == "TS"):
                    weather = "storm"
                elif (j == "DZ") or (j == "RA"):
                    weather = "rain"
                    break
                elif (j == "SN") or (j == "SG") or (j == "IC") \
                            or (j == "PL") or (j == "GS"):
                    weather = "snow"
                    break
                elif (j == "BR") or (j == "FG") or (j == "FU"):
                    weather = "fog"

        if weather == None:
            weather = "unknown"

        if not night_time:
            pixmap = self.weather_to_pixmap["day"][weather]
        else:
            pixmap = self.weather_to_pixmap["night"][weather]

        return pixmap

    def get_weather_data(self):
        """ Show/Hide a WeatherWidget containing an updated weather report """
        self.retrieve_weather()

        # Labels initialisation
        model = application.plugin_registry.create_component("weather:weather_model")

        # Metar lib does not handle exceptions yet
        if not self._report or not hasattr(self._report.temp, "string"):
            return model

        model.location = self._location
        model.temp = self._report.temp.value(units='C')

        # compute humidity: http://www.faqs.org/faqs/meteorology/temp-dewpoint/
        dp  = self._report.dewpt.value(units="K")
        t = self._report.temp.value(units="K")
        e = 6.11 * math.exp((2500000 / 461.5) * ((1 / 273.15) - (1 / dp)))
        es = 6.11 * math.exp((2500000 / 461.5) * ((1 / 273.15) - (1 / t)))
        model.relHumidity = float((e / es) * 100)

        if self._report.wind_speed is not None:
            model.wind_speed = self._report.wind_speed.value(units="KMH")

        if self._report.wind_dir is not None:
            model.wind_dir = self._report.wind_dir.value()

        if self._report.press is not None:
            model.pressure = self._report.press.value(units="HPA")

        model.dew = self._report.dewpt.value(units="C")

        model.sky = self._report.sky_conditions("")

        model.icon = self.get_icon_from_weather(self._report)

        return model
