/* ======================================================================
   Parts Copyright 2006 University of Leeds, Oxford University, University of the Highlands and Islands.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

====================================================================== */

package org.bodington.server.resources;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.log4j.Logger;

/**
 * Class used to cache external Feeds. The cache is only around as long as
 * the original resource is cached by the Bodington SoftCache.
 * This is an UGLY hack.
 * @author buckett
 */
public class FeedCache
{
    private Logger log = Logger.getLogger(FeedCache.class);
    
    private String data = "";
    private long lastChecked = 0;
    private long lastFailed = 0;
    private String url = "";
    private FeedResource resource;
    private HttpClient httpClient = new HttpClient();
    
    private static long CHECK_INTERVAL = 1800000;
    // Only check failing URLs every 20 minutes.
    private static long FAIL_INTERVAL= 1200000;
    
    /**
     * Create a new FeedCache. We need a referece to the
     * resource so we can get the URL we should be visiting.
     * @param resource The resource this is a cache of.
     */
    public FeedCache(FeedResource resource)
    {
        this.resource = resource;
    }
    
    /**
     * This returns the data from the URL.
     * @return String representation of the feed.
     */
    public String getData()
    {
        return data;
    }
    
    /**
     * Attempt to update the data.
     */
    public synchronized void update()
    {
        long now = System.currentTimeMillis();
        String url = resource.getURL();
        
        if ( (! this.url.equals(url)) || now - lastChecked > CHECK_INTERVAL && now - lastFailed > FAIL_INTERVAL)
        {
            this.url = url;
            try
            {
                fastCheck(url);
                lastChecked = now;
                lastFailed = 0;
            }
            catch (Exception e)
            {
                log.warn("Failed to get: "+ url);
                lastFailed = now;
            }
        }
    }
    
    private void fastCheck(String url) throws Exception
    {

        HttpMethod method = new GetMethod(url);
        httpClient.setConnectionTimeout(1000);
        httpClient.setTimeout(2000);
        httpClient.executeMethod(method);
        switch (method.getStatusCode())
        {
            case HttpStatus.SC_OK:
                data = method.getResponseBodyAsString();
            case HttpStatus.SC_NOT_MODIFIED:
                break;
            default:
                 throw new HttpException("Request wasn't sucessfull, code: "+ method.getStatusCode());
        }
    }

}
