<?php

/* Disable block if not configured. */
if (!empty($GLOBALS['conf']['weatherdotcom']['partner_id']) &&
    !empty($GLOBALS['conf']['weatherdotcom']['license_key'])) {
    $block_name = _("weather.com");
}

/**
 * The Horde_Block_weatherdotcom class provides an applet for the
 * portal screen to display weather and forecast data from weather.com
 * for a specified location.
 *
 * $Horde: horde/lib/Block/weatherdotcom.php,v 1.37.4.8 2005/09/30 03:12:01 selsky Exp $
 *
 * @package Horde_Block
 */
class Horde_Block_Horde_weatherdotcom extends Horde_Block {

    var $_app = 'horde';

    /**
     * The title to go in this block.
     *
     * @return string   The title text.
     */
    function _title()
    {
        return _("Weather Forecast");
    }

    /**
     * The parameters to go with this block.
     *
     * @return array  An array containing the parameters.
     */
    function _params()
    {
        if (!@include_once 'Services/Weather.php') {
            Horde::logMessage('The weather.com block will not work without Services_Weather from PEAR. Run pear install Services_Weather.',
                              __FILE__, __LINE__, PEAR_LOG_ERR);
            $params = array(
                'error' => array(
                    'type' => 'error',
                    'name' => _("Error"),
                    'default' => _("The weather.com block is not available.")
                )
            );
        } elseif (!ini_get('allow_url_fopen')) {
            Horde::logMessage('The weather.com block will not work without allow_url_fopen enabled in the PHP configuration.',
                              __FILE__, __LINE__, PEAR_LOG_ERR);
            $params = array(
                'error' => array(
                    'type' => 'error',
                    'name' => _("Error"),
                    'default' => _("The weather.com block is not available.")
                )
            );
        } else {
            $params = array(
                'location' => array(
                    // 'type' => 'weatherdotcom',
                    'type' => 'text',
                    'name' => _("Location"),
                    'default' => 'Boston, MA'
                ),
                'units' => array(
                    'type' => 'enum',
                    'name' => _("Units"),
                    'default' => 'standard',
                    'values' => array(
                        'standard' => _("Standard"),
                        'metric' => _("Metric")
                    )
                ),
                'days' => array(
                    'type' => 'enum',
                    'name' => _("Forecast Days (note that the returned forecast returns both day and night; a large number here could result in a wide block)"),
                    'default' => '3',
                    'values' => array(
                        '1' => '1',
                        '2' => '2',
                        '3' => '3',
                        '4' => '4',
                        '5' => '5',
                        '6' => '6',
                        '7' => '7',
                        '8' => '8'
                    )
                ),
            );
        }

        return $params;
    }

    /**
     * The content to go in this block.
     *
     * @return string   The content
     */
    function _content()
    {
        if (!@include_once 'Services/Weather.php') {
            Horde::logMessage('The weather.com block will not work without Services_Weather from PEAR. Run pear install Services_Weather.',
                              __FILE__, __LINE__, PEAR_LOG_ERR);
            return _("The weather.com block is not available.");
        } elseif (!ini_get('allow_url_fopen')) {
            Horde::logMessage('The weather.com block will not work without allow_url_fopen enabled in the PHP configuration.',
                              __FILE__, __LINE__, PEAR_LOG_ERR);
            return _("The weather.com block is not available.");
        }

        global $conf;

        $cacheDir = Horde::getTempDir();
        $html = '';

        if (empty($this->_params['location'])) {
            return _("No location is set.");
        }


        $weatherDotCom = &Services_Weather::service('WeatherDotCom');

        $weatherDotCom->setAccountData(
            (isset($conf['weatherdotcom']['partner_id']) ? $conf['weatherdotcom']['partner_id'] : ''),
            (isset($conf['weatherdotcom']['license_key']) ? $conf['weatherdotcom']['license_key'] : ''));
        if (!$cacheDir) {
            return PEAR::raiseError(_("No temporary directory available for cache."), 'horde.error');
        } else {
            $weatherDotCom->setCache('file', array('cache_dir' => ($cacheDir . '/')));
        }
        $weatherDotCom->setDateTimeFormat('m.d.Y', 'H:i');
        $weatherDotCom->setUnitsFormat($this->_params['units']);
        $units = $weatherDotCom->getUnitsFormat();

        // If the user entered a zip code for the location, no need to
        // search (weather.com accepts zip codes as location IDs).
        // The location ID should already have been validated in
        // getParams.
        $search = (preg_match('/\b(?:\\d{5}(-\\d{5})?)|(?:[A-Z]{4}\\d{4})\b/',
            $this->_params['location'], $matches) ?
            $matches[0] :
            $weatherDotCom->searchLocation($this->_params['location']));
        if (is_a($search, 'PEAR_Error')) {
            switch ($search->getCode()) {
            case SERVICES_WEATHER_ERROR_SERVICE_NOT_FOUND:
                return _("Requested service could not be found.");
            case SERVICES_WEATHER_ERROR_UNKNOWN_LOCATION:
                return _("Unknown location provided.");
            case SERVICES_WEATHER_ERROR_WRONG_SERVER_DATA:
                return _("Server data wrong or not available.");
            case SERVICES_WEATHER_ERROR_CACHE_INIT_FAILED:
                return _("Cache init was not completed.");
            case SERVICES_WEATHER_ERROR_DB_NOT_CONNECTED:
                return _("MetarDB is not connected.");
            case SERVICES_WEATHER_ERROR_UNKNOWN_ERROR:
                return _("An unknown error has occured.");
            case SERVICES_WEATHER_ERROR_NO_LOCATION:
                return _("No location provided.");
            case SERVICES_WEATHER_ERROR_INVALID_LOCATION:
                return _("Invalid location provided.");
            case SERVICES_WEATHER_ERROR_INVALID_PARTNER_ID:
                return _("Invalid partner id.");
            case SERVICES_WEATHER_ERROR_INVALID_PRODUCT_CODE:
                return _("Invalid product code.");
            case SERVICES_WEATHER_ERROR_INVALID_LICENSE_KEY:
                return _("Invalid license key.");
            default:
                return $search->getmessage();
            }
        }

        if (is_array($search)) {
            // Several locations returned due to imprecise location
            // parameter.
            $html = _("Several locations possible with the parameter: ") .
                $this->_params['location'] .
                '<br /><ul>';
            foreach ($search as $id_weather=>$real_location) {
                $html .= "<li>$real_location ($id_weather)</li>\n";
            }
            $html .= '</ul>';
            return $html;
        }

        $location = $weatherDotCom->getLocation($search);
        if (is_a($location, 'PEAR_Error')) {
            return $location->getmessage();
        }
        $weather = $weatherDotCom->getWeather($search);
        if (is_a($weather, 'PEAR_Error')) {
            return $weather->getmessage();
        }
        $forecast = $weatherDotCom->getForecast($search, $this->_params['days']);
        if (is_a($forecast, 'PEAR_Error')) {
            return $forecast->getmessage();
        }

        // Location and local time.
        $html .= '<div class="control">' .
            '<b>' . $location['name'] . '</b> ' . _("Local time: ") . $location['time'] .
            '</div>';

        // Sunrise/sunset.
        $html .= '<b>' . _("Sunrise: ") . '</b>' .
            Horde::img('block/sunrise/sunrise.png', _("Sunrise")) .
            $location['sunrise'];
        $html .= ' <b>' . _("Sunset: ") . '</b>' .
            Horde::img('block/sunrise/sunset.png', _("Sunset")) .
            $location['sunset'];

        // Temperature.
        $html .= '<br /><b>' . _("Temperature: ") . '</b>' .
            round($weather['temperature']) . '&deg;' . String::upper($units['temp']);

        // Dew point.
        $html .= ' <b>' . _("Dew point: ") . '</b>' .
            round($weather['dewPoint']) . '&deg;' . String::upper($units['temp']);

        // Feels like temperature.
        $html .= ' <b>' . _("Feels like: ") . '</b>' .
            round($weather['feltTemperature']) . '&deg;' . String::upper($units['temp']);

        // Pressure and trend.
        $html .= '<br /><b>' . _("Pressure: ") . '</b>';
        $trend = $weather['pressureTrend'];
        $html .= sprintf(_("%d %s and %s"),
                         round($weather['pressure']), $units['pres'],
                         _($trend));

        // Wind.
        $html .= '<br /><b>' . _("Wind: ") . '</b>';
        if ($weather['windDirection'] == 'VAR') {
            $html .= _("Variable");
        } elseif ($weather['windDirection'] == 'CALM') {
            $html .= _("Calm");
        } else {
            $html .= _("From the ") . $weather['windDirection'] .
                ' (' . $weather['windDegrees'] . ')';
        }
        $html .= _(" at ") . round($weather['wind']) . ' ' . $units['wind'];

        // Humidity.
        $html .= '<br /><b>' . _("Humidity: ") . '</b>' .
            $weather['humidity'] . '%';

        // Visibility.
        $html .= ' <b>' . _("Visibility: ") . '</b>' .
            is_numeric($weather['visibility']) ?
                round($weather['visibility']) . ' ' . $units['vis'] :
                $weather['visibility'];

        // UV index.
        $html .= ' <b>' . _("U.V. index: ") . '</b>';
        $uv = $weather['uvText'];
        $html .= $weather['uvIndex'] . ' - ' . _($uv);

        // Current condition.
        $condition = implode(' / ', array_map('_', explode(' / ', $weather['condition'])));
        $html .= '<br /><b>' . _("Current condition: ") . '</b>' .
            Horde::img('block/weatherdotcom/32x32/' .
                       ($weather['conditionIcon'] == '-' ? 'na' : $weather['conditionIcon']) . '.png',
                       $condition,
                       'align="middle"') .
            ' ' . $condition;

        // Do the forecast now.
        $html .= '<div class="control" style="text-align:center"><b>' . sprintf(_("%d-day forecast"), $this->_params['days'])
            . '</b></div>';
        $futureDays = 0;
        $html .= '<table cellspacing="3" cellpadding="1" width="100%"><tr>';
        foreach ($forecast['days'] as $which => $day) {
            $html .= '<td align="center" style="vertical-align:top; border:1px solid #dddddd; width:' . round(100 / count($forecast['days'])) . '%;">';

            // Day name.
            $html .= '<b>';
            if ($which == 0) {
                $html .= _("Today");
            } elseif ($which == 1) {
                $html .= _("Tomorrow");
            } else {
                $html .= strftime('%A', mktime(0, 0, 0, date('m'), date('d') + $futureDays, date('Y')));
            }
            $html .= '</b><br />';
            $futureDays++;

            // High/low temp. If after 2 p.m. local time, the "day"
            // forecast is no longer valid.
            if ($which > 0 || ($which == 0 &&
                (strtotime($location['time']) < strtotime('14:00')))) {
                $html .= '<span style="color:red">' . round($day['temperatureHigh']) .
                    '&deg;' . String::upper($units['temp']) . '</span>/';
            }
            $html .= '<span style="color:blue">' . round($day['temperatureLow']) .
                '&deg;' . String::upper($units['temp']) . '</span>';

            $html .= '<div>';

            // Day forecast.
            $html .= '<span style="text-align:center; float:left; width:50%;">';
            if ($which > 0 || ($which == 0 &&
                               (strtotime($location['time']) < strtotime('14:00')))) {
                $condition = implode(' / ', array_map('_', explode(' / ', $day['day']['condition'])));
                $html .= '<b><i>' . _("Day") . '</i></b><br />' .
                    Horde::img('block/weatherdotcom/23x23/' .
                               ($day['day']['conditionIcon'] == '-' ? 'na' : $day['day']['conditionIcon']) . '.png',
                               $condition) .
                    '<br />' . $condition;
            } else {
                $html .= '&nbsp;';
            }
            $html .= '</span>';

            // Night forecast.
            $html .= '<span style="text-align:center; float:right; width:50%;">' .
                '<b><i>' . _("Night") . '</i></b><br />';
            $night = implode(' / ', array_map('_', explode(' / ', $day['night']['condition'])));
            $html .= Horde::img('block/weatherdotcom/23x23/' .
                                ($day['night']['conditionIcon'] == '-' ? 'na' : $day['night']['conditionIcon']) . '.png',
                                $night) .
                '<br />' . $night .
                '</span>';

            $html .= '</div></td>';
        }
        $html .= '</tr></table>';

        // Display a bar at the bottom of the block with the required
        // attribution to weather.com and the logo, both linked to
        // weather.com with the partner ID.
        $html .= '<div style="text-align:right;" class="linedRow">' .
            _("Weather data provided by") . ' ' .
            Horde::link('http://www.weather.com/?prod=xoap&amp;par=' .
                        $weatherDotCom->_partnerID,
                        'weather.com', '', '_blank', '', 'weather.com') .
            '<i>weather.com</i>&reg; ' .
            Horde::img('block/weatherdotcom/32x32/TWClogo_32px.png',
                       'weather.com logo', 'align="middle"') .
            '</a></div>';

        return $html;
    }

}
