

# TODO: use numpy
from math import acos, cos, degrees, radians, sin
from datetime import datetime

# define triogonometry with degrees
cos2 = lambda x: cos(radians(x))
sin2 = lambda x: sin(radians(x))
acos2 = lambda x: degrees(acos(x))


def calculate(utc, latitude, longitude):
    '''\
    Returns the solar zenith angle (in degree)

    UTC         (as datetime.datetime Object)
    longitude   (in degree)
    latitude    (in degree)
    '''

    # parameter
    day_of_year = utc.timetuple().tm_yday
    leap_year_factor = (-0.375, 0.375, -0.125, 0.125)[utc.year % 4]
    utc_min = utc.hour * 60.0 + utc.minute + utc.second / 60.0
    J = 360.0 / 365.0 * (day_of_year + leap_year_factor + utc_min / 1440.0)

    # hour angle (using the time equation)
    average_localtime = utc_min + 4 * longitude
    true_solar_time = average_localtime + 0.0066 + 7.3525 * cos2(  J +  85.9) \
                                                 + 9.9359 * cos2(2*J + 108.9) \
                                                 + 0.3387 * cos2(3*J + 105.2)
    hour_angle = 15.0 * (720 - true_solar_time) / 60.0

    # sun declination (using DIN 5034-2)
    declination = 0.3948 - 23.2559 * cos2(  J + 9.1 ) \
                         -  0.3915 * cos2(2*J + 5.4 ) \
                         -  0.1764 * cos2(3*J + 26.0)

    # solar zenith angle
    return acos2( sin2(latitude) * sin2(declination) +
                  cos2(hour_angle) * cos2(latitude) * cos2(declination)
                )
