package mobile;

import com.sun.util.logging.Level;

import java.sql.Date;

import java.util.ArrayList;

import java.util.List;

import oracle.adfmf.framework.api.AdfmfJavaUtilities;
import oracle.adfmf.framework.api.GenericTypeBeanSerializationHelper;
import oracle.adfmf.framework.exception.AdfException;
import oracle.adfmf.framework.exception.AdfInvocationException;
import oracle.adfmf.java.beans.PropertyChangeListener;
import oracle.adfmf.java.beans.PropertyChangeSupport;
import oracle.adfmf.java.beans.ProviderChangeListener;
import oracle.adfmf.java.beans.ProviderChangeSupport;
import oracle.adfmf.util.GenericType;
import oracle.adfmf.util.Utility;
import oracle.adfmf.util.logging.Trace;

public class CityInformation {
    static CityForecast cityForecast = new CityForecast();
    static WeatherInformation weatherInfo = null;
    private transient ProviderChangeSupport providerChangeSupport = new ProviderChangeSupport(this);

    public CityInformation() {
        super();
        if (cityForecast == null) {
            cityForecast = new CityForecast();
        }
    }

    public void addProviderChangeListener(ProviderChangeListener l) {
        providerChangeSupport.addProviderChangeListener(l);
    }

    public void removeProviderChangeListener(ProviderChangeListener l) {
        providerChangeSupport.removeProviderChangeListener(l);
    }

    public void setCityForecast(CityForecast cf) {
        cityForecast = cf;
    }

    public CityForecast getCityForecast() {
        return cityForecast;
    }

    public void setWeatherInfo(WeatherInformation weatherInfo) {
        this.weatherInfo = weatherInfo;
    }

    public static WeatherInformation getWeatherInfo() {
        return weatherInfo;
    }

    /**
     * This method is called from the WeatherBean 
     * We use this method to invoke the Web Service from the DC and parse the results into a bean 
     **/ 
    public synchronized boolean retrieveForecast(String zip) {
        // First lets clear the cityForecast
        cityForecast.setSuccess((Boolean)Boolean.FALSE);
        cityForecast.setResponseText((String)"Running...");
        cityForecast.setCity((String)"");
        cityForecast.setState((String)"");
        cityForecast.setWeatherStationCity((String)"");
        cityForecast.clearForecast();
        
        ForecastWorker fw = new ForecastWorker(this, zip);
        Thread t = new Thread(fw);
        t.start();
        
        return true;
    }
    
    public synchronized boolean retrieveForecastAsync(String zip) {
        // Before we get any forecast, we get the WeatherInfo if it's not retrieved yet
        weatherInfo.retreiveWeatherInfo();

        boolean ret = false;

        List pnames = new ArrayList();
        List params = new ArrayList();
        List ptypes = new ArrayList();

        pnames.add("ZIP");
        ptypes.add(String.class);
        params.add(zip);

        try {
            // This calls the DC method and gives us the Return
            GenericType result =
                (GenericType)AdfmfJavaUtilities.invokeDataControlMethod("WeatherDC", null, "GetCityForecastByZIP",
                                                                        pnames, params, ptypes);

            // This will give us the CityForeCast object from the result
            GenericType cfgt = (GenericType)result.getAttribute(0);

            // Read the attributes from the GenericType returend from the getCityForecastByZip call            
            cityForecast.setSuccess((Boolean)cfgt.getAttribute("Success"));
            cityForecast.setResponseText((String)cfgt.getAttribute("ResponseText"));
            cityForecast.setCity((String)cfgt.getAttribute("City"));
            cityForecast.setState((String)cfgt.getAttribute("State"));
            cityForecast.setWeatherStationCity((String)cfgt.getAttribute("WeatherStationCity"));

            // This will give us the ForecastResult which is a collection of Forecast objects
            GenericType frgt = (GenericType)cfgt.getAttribute("ForecastResult");


            // fcgt is a collection of Forecast objects, get all those in a loop
            int count = frgt.getAttributeCount();
            for (int i = 0; i < count; i++) {
                // Get each individual WeatherDescription object
                GenericType fgt = (GenericType)frgt.getAttribute(i);

                // Now make a real WeatherDescription java object out of this GenericType
                Forecast f = (Forecast)GenericTypeBeanSerializationHelper.fromGenericType(Forecast.class, fgt);
                f.weatherInfo = weatherInfo;

                // Now get the Temperature subobject
                GenericType tempgt = (GenericType)fgt.getAttribute("Temperatures");

                // Now set the high and low temps
                f.setDaytimeHigh((String)tempgt.getAttribute(0));
                f.setMorningLow((String)tempgt.getAttribute(1));
                // Now add this to our holder of all WeatherDescriptions
                cityForecast.addForecast(f);
                
            }
            ret = true;
        } catch (AdfInvocationException e) {
            Trace.log(Utility.ApplicationLogger, Level.SEVERE, CityInformation.class, "retrieveForecastAsync",
                      ">>>>>> AdfInvocationException=" + e.getMessage());
            AdfException ex = new AdfException("Error Invoking Web Service.  Please try later", AdfException.WARNING);
            throw ex;

        } catch (Exception e2) {
            Trace.log(Utility.ApplicationLogger, Level.SEVERE, CityInformation.class, "retrieveForecastAsync",
                      ">>>>>> Exception=" + e2.getMessage());
            AdfException ex = new AdfException("Error Invoking Web Service.  Please try later", AdfException.WARNING);
            throw ex;
        }
        return ret;
    }
}
