package usda.weru.weps;

import gov.usda.ars.eweru.tools.propertyboilerplate.PropertyBoilerPlate;
import java.beans.PropertyVetoException;
import java.util.Date;
import javax.measure.Measurable;
import javax.measure.quantity.Duration;
import javax.measure.quantity.Length;
import javolution.text.Text;
import org.apache.log4j.Logger;
import org.jscience.geography.coordinates.LatLong;
import usda.weru.util.ExceptionEventQueue;
import usda.weru.util.PropertyStackContext;
import usda.weru.weps.location.ElevationMode;
import usda.weru.weps.location.LatLongSiteController;
import usda.weru.weps.location.Site;
import usda.weru.weps.location.Station;
import usda.weru.weps.location.StationMode;
import usda.weru.weps.location.StationModeSelectionController;

/**
 * This bean class is for transitioning away from the web of PropertyChangeEvents
 * used to set and get values with RunFileData.  This bean is also strictly typed.
 * This means that instead of using Strings for every value, the bean allows for
 * getting and setting objects.
 *
 * To simplify writing the property code, RunFileBean uses the PropertyBoilerPlate
 * annotation.  Public static String constants (used for the property names) that
 * are annotated will cause getter/setter code to be generated at compile time in
 * the RunFileBean_PropertyBoilerPlate class. RunFileBeanPersistenceHandler.java
 * is also generated here.
 *
 * @author Joseph Levin <joelevin@weru.ksu.edu>
 */
public class RunFileBean extends RunFileBean_PropertyBoilerPlate {

    /**
     *
     */
    @PropertyBoilerPlate(valueClass = Site.class, valueGenericClasses = {})
    public static final String PROP_SITE = "site";

    /**
     *
     */
    @PropertyBoilerPlate(valueClass = ElevationMode.class, hook = true)
    public static final String PROP_ELEVATION_MODE = "elevationMode";

    /**
     *
     */
    @PropertyBoilerPlate(valueClass = Measurable.class, valueGenericClasses = {Length.class})
    public static final String PROP_ELEVATION = "elevation";

    /**
     *
     */
    @PropertyBoilerPlate(valueClass = StationMode.class, hook = true)
    public static final String PROP_CLIGEN_STATION_MODE = "cligenStationMode";

    /**
     *
     */
    @PropertyBoilerPlate(valueClass = Station.class)
    public static final String PROP_CLIGEN_STATION = "cligenStation";

    /**
     *
     */
    @PropertyBoilerPlate(valueClass = StationMode.class, hook = true)
    public static final String PROP_WINDGEN_STATION_MODE = "windgenStationMode";

    /**
     *
     */
    @PropertyBoilerPlate(valueClass = Station.class)
    public static final String PROP_WINDGEN_STATION = "windgenStation";

    /**
     *
     */
    @PropertyBoilerPlate(valueClass = LatLong.class)
    public static final String PROP_LATLONG = "latLong";

    /**
     *
     */
    @PropertyBoilerPlate(valueClass = Text.class)
    public static final String PROP_NOTES = "notes";

    /**
     *
     */
    @PropertyBoilerPlate(valueClass = String.class)
    public static final String PROP_CLIENT_NAME = "clientName";

    /**
     *
     */
    @PropertyBoilerPlate(valueClass = String.class)
    public static final String PROP_CLIENT_FARM = "clientFarm";

    /**
     *
     */
    @PropertyBoilerPlate(valueClass = String.class)
    public static final String PROP_CLIENT_TRACT = "clientTract";

    /**
     *
     */
    @PropertyBoilerPlate(valueClass = String.class)
    public static final String PROP_CLIENT_FIELD = "clientField";

    /**
     *
     */
    @PropertyBoilerPlate(valueClass = RunMode.class)
    public static final String PROP_RUN_MODE = "runMode";

    /**
     *
     */
    @PropertyBoilerPlate(valueClass = Measurable.class, valueGenericClasses = {Duration.class})
    public static final String PROP_ROTATION_LENGTH = "rotationLength";

    /**
     *
     */
    @PropertyBoilerPlate(valueClass = Integer.class)
    public static final String PROP_CYCLE_COUNT = "cycleCount";

    /**
     *
     */
    @PropertyBoilerPlate(valueClass = Date.class)
    public static final String PROP_SIMULATION_START_DATE = "simulationStartDate";

    /**
     *
     */
    @PropertyBoilerPlate(valueClass = Date.class)
    public static final String PROP_SIMULATION_END_DATE = "simulationEndDate";

    /**
     *
     */
    @PropertyBoilerPlate(valueClass = Integer.class)
    public static final String PROP_TIME_STEPS = "timeSteps";

    //class variables
    private static final Logger LOGGER = Logger.getLogger(RunFileBean.class);

    /**
     * Required for this to be a true Bean
     */
    public RunFileBean() {
        LatLongSiteController.install(this);
        StationModeSelectionController.install(this);
    }

    //ELEVATION
    /**
     *
     * @param oldValue
     * @param newValue
     */
    @Override
    protected void hookElevationMode(ElevationMode oldValue, ElevationMode newValue) {
        if (oldValue != null) {
            oldValue.uninstallModel(this);
        }
        if (newValue != null) {
            newValue.installModel(this);
        }
    }
    //END ELEVATION

    //CLIGEN
    /**
     *
     * @param oldValue
     * @param newValue
     */
    @Override
    protected void hookCligenStationMode(StationMode oldValue, StationMode newValue) {
        if (oldValue != null) {
            oldValue.uninstallModel(this, StationType.Cligen);
        }
        if (newValue != null) {
            newValue.installModel(this, StationType.Cligen);
        }
    }
    //END CLIGEN

    //WINDGEN
    /**
     *
     * @param oldValue
     * @param newValue
     */
    @Override
    protected void hookWindgenStationMode(StationMode oldValue, StationMode newValue) {
        if (oldValue != null) {
            oldValue.uninstallModel(this, StationType.Windgen);
        }
        if (newValue != null) {
            newValue.installModel(this, StationType.Windgen);
        }
    }
    //END WINDGEN

    /**
     *
     * @param propertyName
     */
    @Override
    protected void enterSetter(String propertyName) {
        PropertyStackContext.enter(this, propertyName);
    }

    /**
     *
     * @param propertyName
     */
    @Override
    protected void exitSetter(String propertyName) {
        PropertyStackContext.exit(this, propertyName);
    }

    /**
     *
     * @param pve
     */
    @Override
    protected void handlePropertyVeto(PropertyVetoException pve) {
        if (pve instanceof Runnable) {
            Runnable task = (Runnable) pve;
            ExceptionEventQueue.invokeLater(task);
        }
    }

    /**
     *
     */
    public void clear() {
        clear(false);
    }

    /**
     * The default values for the RunFile.  Used when the user creates a new RunFile
     */
    public void initilizeDefaultValues() {

    }

    /**
     *
     */
    public static enum StationType {

        /**
         *
         */
        Cligen("Cligen"),
        /**
         *
         */
        Windgen("Windgen");

        private final String c_displayName;

        private StationType(String displayName) {
            c_displayName = displayName;
        }

        /**
         *
         * @return
         */
        public String getDisplayName() {
            return c_displayName;
        }

    }

}
