# -*- 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.

# Copyright 2006, Frank Scholz <coherence@beebits.net>

""" calculates sunrise or sunset for a given time and place
    the code is from the last millenium
    and as far as I can remember modeled after
    some formular in some book about astronomy
"""


import os,sys
import string
import math
import time

def normalize(z, d):
    if not d:
        raise ("Trying to normalize with zero offset")

    while z < 0:
        z = z + d
    while z >= d:
        z = z - d

    return z

def suntime(type, lat, lon, tz, yday):

    """ type = rise or set
        tz = diff from gmt
        date = time.localtime()
        yday = date[7]
    """

    a = 1.5708
    b = math.pi
    c = 4.71239
    d = 6.28319
    e = 0.0174533 * lat
    f = 0.0174533 * lon
    g = 0.261799 * tz

    """ Twilight (R)
        astronomical R = -.309017
        nautical R     = -.207912
        civil R        = -.104528
    """

    """ Sunrise/sunset """
    r = -.0145439

    if type == 'rise':
        j = a
    else:
        j = c

    k = yday + ((j - f) / d)
    l = (k * .017202) - .0574039 # solar mean anomaly
    m = l + .0334405 * math.sin (l)
    m = m + 4.93289 + 3.49066e-4 * math.sin (2 * l)

    m = normalize (m, d)

    if (m / a) - int (m/a) == 0:
        m = m + 4.84814e-6

    p = math.sin (m) / math.cos (m) # solar right ascension
    p = math.atan2 (.91746 * p, 1)

    if m > c:
        p = p + d
    elif m > a:
        p = p + b

    q = .39782 * math.sin (m) # solar declination
    q = q / math.sqrt (-q * q + 1)
    q = math.atan2 (q, 1)

    s = r - (math.sin(q) * math.sin (e))
    s = s / (math.cos (q) * math.cos (e))

    if abs (s) > 1:
        return None # Null phenomenon

    s = s / math.sqrt (-s * s + 1)
    s = a - math.atan2 (s, 1)

    if type == 'rise':
        s = d -s
    t = s + p - 0.0172028 * k - 1.73364 # local apparent time
    u = t - f
    v = u + g
    v = normalize (v, d)
    v = v*3.81972

    hour = int (v)
    min = int ((v - hour) * 60 + .5)

    return (hour, min)

if __name__ == "__main__":
    print time.localtime()
    s = suntime ('rise', 41.23, 2.11, 1, time.localtime()[7])
    print s
    s = suntime ('set', 41.23, 2.11, 1, time.localtime()[7])
    print s
