package usda.weru.erosion;

import de.schlichtherle.io.File;
import de.schlichtherle.io.FileReader;
import de.schlichtherle.io.FileWriter;
import java.util.*;
import java.beans.*;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.PrintWriter;
import usda.weru.erosion.barriereditor.BarrierPolygon;
import usda.weru.erosion.barriereditor.FieldPolygon;

public class DataStore implements PropertyChangeListener {

    public static final String InputExt = ".in";

    public DataStore() {
        init();
    }
    private int lineNum = 0;
//	private int numSubr = 1;  // needed for future expansion
    // Global
    public static final String SimRegOrgX = "SimRegOrgX";
    public static final String SimRegOrgY = "SimRegOrgY";
    public static final String SimRegLenX = "SimRegLenX";
    public static final String SimRegLenY = "SimRegLenY";
    public static final String SimX1Y1 = "SimX1Y1";
    public static final String SimX2Y2 = "SimX2Y2";
//    public static final String  SimFld          = "SimFld";
    public static final String SimRegAngle = "SimRegAngle";
    public static final String SimField = "SimField";    // Accounting Regions - not currently displayed
    public static final String AccRegNum = "AccRegNum";
    public static final String AccRegOrgX = "AccRegOrgX";
    public static final String AccRegOrgY = "AccRegOrgY";
    public static final String AccRegLenX = "AccRegLenX";
    public static final String AccRegLenY = "AccRegLenY";    // Subregions - not currently displayed
    public static final String SubRegNum = "SubRegNum";
    public static final String SubRegOrgX = "SubRegOrgX";
    public static final String SubRegOrgY = "SubRegOrgY";
    public static final String SubRegLenX = "SubRegLenX";
    public static final String SubRegLenY = "SubRegLenY";    // Barriers
    public static final String BarriersNum = "BarriersNum";
    public static final String BarriersOrgX = "BarriersOrgX";
    public static final String BarriersOrgY = "BarriersOrgY";
    public static final String BarriersLenX = "BarriersLenX";
    public static final String BarriersLenY = "BarriersLenY";
    public static final String BarriersHgt = "BarriersHgt";
    public static final String BarriersPors = "BarriersPors";
    public static final String BarriersWid = "BarriersWid";
    public static final String BarriersObj = "BarriersObj";    // Biomass
    public static final String BiomassHgt = "BiomassHgt";
    public static final String BiomassRSAI = "BiomassRSAI";
    public static final String BiomassRLAI = "BiomassRLAI";
    public static final String BiomassFlat = "BiomassFlat";
    public static final String BiomassStanding = "BiomassStanding";	// not currently used
    public static final String BiomassTotal = "BiomassTotal";		// not currently used
    public static final String CropHgt = "CropHgt";
    public static final String CropGSAI = "CropGSAI";
    public static final String CropGLAI = "CropGLAI";
    public static final String CropRowSpacing = "CropRowSpacing";
    public static final String CropRowPlacemnt = "CropRowPlacemnt";
    public static final String SoilIFCName = "SoilIFCName";    // Soil layers	
    public static final String LayerOrigNum = "LayerOrigNum";
    public static final String LayerNum = "LayerNum";
    public static final String LayerThickness = "LayerThickness";
    public static final String LayerBD = "LayerBD";
    public static final String LayerSand = "LayerSand";
    public static final String LayerVFSand = "LayerVFSand";
    public static final String LayerSilt = "LayerSilt";
    public static final String LayerClay = "LayerClay";
    public static final String LayerRock = "LayerRock";
    public static final String LayerAggDen = "LayerAggDen";
    public static final String LayerAggSta = "LayerAggSta";
    public static final String LayerAggGMD = "LayerGMD";
    public static final String LayerAggMin = "LayerMinAggSiz";
    public static final String LayerAggMax = "LayerMaxAggSiz";
    public static final String LayerAggGSD = "LayerGSD";
    public static final String LayerWPWC = "LayerWPWC";
//	public static final String	HydroLayerWC	= "HydroLayerWC";

    // Soil surface
    public static final String SurfCrustFrac = "SurfCrustFrac";
    public static final String SurfCrustThk = "SurfCrustThk";
    public static final String SurfLMFrac = "SurfLMFrac";
    public static final String SurfLMMass = "SurfLMMass";
    public static final String SurfCrustDen = "SurfCrustDen";
    public static final String SurfCrustSta = "SurfCrustSta";
    public static final String SurfARR = "SurfARR";
    public static final String SurfRidgHgt = "SurfRidgHgt";
    public static final String SurfRidgSpacing = "SurfRidgSpacing";
    public static final String SurfRidgWid = "SurfRidgWid";
    public static final String SurfRidgOrient = "SurfRidgOrient";
    public static final String SurfDikeSpacing = "SurfDikeSpacing";
    public static final String SurfSnowDepth = "HydroSnowDepth";
    public static final String SurfWC = "HydroSurfWC";    // Weather
    public static final String WeaAirDen = "WeaAirDen";
    public static final String WeaWindDir = "WeaWindDir";
    public static final String WeaDailySteps = "WeaDailySteps";
    public static final String WeaAnemHgt = "WeaAnemHgt";
    public static final String WeaAeroRough = "WeaAeroRough";
    public static final String WeaZoLocFlg = "WeaZoLocFlg";
    public static final String WeaWindWeibull = "WeaWindWeibull";
    public static final String WeaCalmWind = "WeaCalmWind";
    public static final String WeaWeibullC = "WeaWeibullC";
    public static final String WeaWeibullK = "WeaWeibullK";
    public static final String WeaWindSpeeds = "WeaWindSpeeds";    // Plot flags
    public static final String PlotFlg = "PlotFlg";
    public static final String PlotFieldLen = "Plot-Length(m)";
    public static final String PlotBiomass = "Plot-bio_ht(m)";
    public static final String PlotSAI = "Plot-stem_area";
    public static final String PlotLAI = "Plot-lai_area";
    public static final String PlotFlatCover = "Plot-flat_cov";
    public static final String PlotVFSand = "Plot-vfsand";
    public static final String PlotSand = "Plot-sand";
    public static final String PlotSilt = "Plot-silt";
    public static final String PlotClay = "Plot-clay";
    public static final String PlotRock = "Plot-rock_vol";
    public static final String PlotAggStab = "Plot-ag_stab";
    public static final String PlotAggGMD = "Plot-ag_gmd";
    public static final String PlotAggMin = "Plot-ag_min";
    public static final String PlotAggMax = "Plot-ag_max";
    public static final String PlotAggStd = "Plot-ag_std";
    public static final String PlotCrustFrac = "Plot-crust_cv";
    public static final String PlotCrustThk = "Plot-crust_z(mm)";
    public static final String PlotLMFrac = "Plot-los_cv";
    public static final String PlotLMMass = "Plot-los(kg/m^2)";
    public static final String PlotCrustDen = "Plot-cr_den(Mg/m^3)";
    public static final String PlotCrustStab = "Plot-cr_se";
    public static final String PlotRandRough = "Plot-rr(mm)";
    public static final String PlotRidgeHgt = "Plot-z_rgh(mm)";
    public static final String PlotRidgeSpc = "Plot-x_rgs(mm)";
    public static final String PlotRidgeWid = "Plot-x_rgw(mm)";
    public static final String PlotRidgeOrient = "Plot-a_rgo(deg)";
    public static final String DataChanged = "DataChanged";
    public static final String SetFocus = "SetFocus";
    public static final String Commit = "Commit";
    public static final int MaxBarriers = 5;
    public static final int MaxLayers = 3;

    public void init() {

        ht = new Hashtable();

        // Global
        setData(SimRegOrgX, "0");
        setData(SimRegOrgY, "0");
        setData(SimRegLenX, "0");
        setData(SimRegLenY, "0");
        setData(SimRegAngle, "0");
        setData(SimField, new usda.weru.erosion.barriereditor.FieldPolygon());
        // Accounting Regions - not currently displayed
        setData(AccRegNum, "1");
        setData(AccRegOrgX, "0");
        setData(AccRegOrgY, "0");
        setData(AccRegLenX, "0");
        setData(AccRegLenY, "0");
        // Subregions - not currently displayed
        setData(SubRegNum, "1");
        setData(SubRegOrgX, "0");
        setData(SubRegOrgY, "0");
        setData(SubRegLenX, "0");
        setData(SubRegLenY, "0");
        // Barriers
        setData(BarriersNum, "0");
        for (int bdx = 0; bdx < MaxBarriers; bdx++) {
            // limit init to MaxBarriers barriers
            setData(BarriersOrgX + bdx, "0");
            setData(BarriersOrgY + bdx, "0");
            setData(BarriersLenX + bdx, "0");
            setData(BarriersLenY + bdx, "0");
            setData(BarriersHgt + bdx, "0");
            setData(BarriersPors + bdx, "0");
            setData(BarriersWid + bdx, "0");
        }
        for (int rdx = 0; rdx < 1; rdx++) {
            // go thru regions (currently 1)
            // Biomass
            setData(BiomassHgt + "+" + rdx, "0.0");
            setData(CropHgt + "+" + rdx, "0.0");
            setData(CropGSAI + "+" + rdx, "0.0");
            setData(CropGLAI + "+" + rdx, "0.0");
            setData(BiomassRSAI + "+" + rdx, "0.0");
            setData(BiomassRLAI + "+" + rdx, "0.0");
            setData(CropRowSpacing + "+" + rdx, "0.0");
            setData(CropRowPlacemnt + "+" + rdx, "0");
            setData(BiomassFlat + "+" + rdx, "0.0");
            setData(BiomassStanding + "+" + rdx, "0.0");
            setData(BiomassTotal + "+" + rdx, "0.0");
            // Soil layers
            setData(LayerNum + "+" + rdx, "0");
            for (int ldx = 0; ldx < MaxLayers; ldx++) {
                // go thru layers (max 3)
                setData(LayerThickness + ldx + "+" + rdx, "0.0");
                setData(LayerBD + ldx + "+" + rdx, "0.0");
                setData(LayerSand + ldx + "+" + rdx, "0.0");
                setData(LayerVFSand + ldx + "+" + rdx, "0.0");
                setData(LayerSilt + ldx + "+" + rdx, "0.0");
                setData(LayerClay + ldx + "+" + rdx, "0.0");
                setData(LayerRock + ldx + "+" + rdx, "0.0");
                setData(LayerAggDen + ldx + "+" + rdx, "0.0");
                setData(LayerAggSta + ldx + "+" + rdx, "0.0");
                setData(LayerAggGMD + ldx + "+" + rdx, "0.0");
                setData(LayerAggMin + ldx + "+" + rdx, "0.0");
                setData(LayerAggMax + ldx + "+" + rdx, "0.0");
                setData(LayerAggGSD + ldx + "+" + rdx, "0.0");
                setData(LayerWPWC + ldx + "+" + rdx, "0.0");
            }
            // Soil surface
            setData(SurfCrustFrac + "+" + rdx, "0.0");
            setData(SurfCrustThk + "+" + rdx, "1.0");
            setData(SurfLMFrac + "+" + rdx, "0.0");
            setData(SurfLMMass + "+" + rdx, "0.0");
            setData(SurfCrustDen + "+" + rdx, "1.8");
            setData(SurfCrustSta + "+" + rdx, "2.75");
            setData(SurfARR + "+" + rdx, "6.0");
            setData(SurfRidgHgt + "+" + rdx, "0.0");
            setData(SurfRidgSpacing + "+" + rdx, "10.0");
            setData(SurfRidgWid + "+" + rdx, "0.0");
            setData(SurfRidgOrient + "+" + rdx, "0.0");
            setData(SurfDikeSpacing + "+" + rdx, "0.0");
            setData(SurfSnowDepth + "+" + rdx, "0.0");
            for (int wdx = 0; wdx < 24; wdx++) {
                setData(SurfWC + wdx + "+" + rdx, "0.0");
            }
        }
        // Weather
        setData(WeaAirDen, "1.16");
        setData(WeaWindDir, "0.0");
        setData(WeaDailySteps, "0");
        setData(WeaAnemHgt, "10.0");
        setData(WeaAeroRough, "25.0");
        setData(WeaZoLocFlg, "0");
        setData(WeaWindWeibull, "1");
        setData(WeaCalmWind, "0.0");
        setData(WeaWeibullC, "0.0");
        setData(WeaWeibullK, "0.0");
        setData(WeaWindSpeeds, "");

        changes.firePropertyChange(DataChanged, "", "0");
    }

    private String getLine(BufferedReader in) throws IOException {
        String temp;
        while ((temp = in.readLine()) != null) {
            lineNum++;
            if (temp.length() == 0) {
                return temp;
            }
            if (temp.charAt(0) != '#') {
                return temp;
            }
        }
        return null;
    }

    private void parseLayerLine(String property, String inputStr, int numLayers, int subReg) {
        StringTokenizer st = new StringTokenizer(inputStr);
        for (int idx = 0; idx < numLayers; idx++) {
            setData(property + idx + "+" + subReg, st.nextToken(), true);
        }
    }

    public void readTextFile(File inpFile) {
        clearBarriers();

        lineNum = 0;
        init();
        try {
            BufferedReader in = new BufferedReader(new FileReader(inpFile));

            // Global

//			setData(DebugCode		, getLine(in), true); 
//			setData(InitFlg			, getLine(in), true); 
//			setData(PrintFlg		, getLine(in), true);
            getLine(in);            // skip debug code
            getLine(in);            // skip init flag
            getLine(in);            // skip print flag
            String inputStr = getLine(in);
            StringTokenizer st = new StringTokenizer(inputStr, ", ");
            String x1 = st.nextToken();
//			setData(SimRegOrgX		, inputX, true); 
            String y1 = st.nextToken();
//			setData(SimRegOrgY		, inputY, true); 
//            setData(SimX1Y1, new OrderedPair(inputX, inputY));
            String x2 = st.nextToken();
            String y2 = st.nextToken();
//            setData(SimX2Y2, new OrderedPair(inputX, inputY));
            setData(SimField, new FieldPolygon(x1, y1, x2, y2));
//			setData(SimRegLenX		, st.nextToken(), true); 
//			setData(SimRegLenY		, st.nextToken(), true); 
            setData(SimRegAngle, getLine(in), true);

            // Accounting Regions - not currently displayed

            inputStr = getLine(in);
            setData(AccRegNum, inputStr, true);
            int cnt = Integer.parseInt(inputStr.trim());
            for (int idx = 0; idx < cnt; idx++) {
                inputStr = getLine(in);
                st = new StringTokenizer(inputStr, ", ");
                setData(AccRegOrgX + "+" + idx, st.nextToken(), true);
                setData(AccRegOrgY + "+" + idx, st.nextToken(), true);
                setData(AccRegLenX + "+" + idx, st.nextToken(), true);
                setData(AccRegLenY + "+" + idx, st.nextToken(), true);
            }

            // Barriers

            inputStr = getLine(in);
            setData(BarriersNum, inputStr, true);
            cnt = Integer.parseInt(inputStr.trim());
            for (int idx = 0; idx < cnt; idx++) {
                inputStr = getLine(in);
                st = new StringTokenizer(inputStr, ", ");
                String tmp1 = st.nextToken();
                String tmp2 = st.nextToken();
                String tmp3 = st.nextToken();
                String tmp4 = st.nextToken();
                String tmp8 = (st.hasMoreTokens()) ? st.nextToken("") : "Barrier " + (idx + 1);
                //setData(BarriersOrgX+idx, tmp1, true); 
                //setData(BarriersOrgY+idx, tmp2, true); 
                //setData(BarriersLenX+idx, tmp3, true); 
                //setData(BarriersLenY+idx, tmp4, true); 
                inputStr = getLine(in);
                st = new StringTokenizer(inputStr, ", ");
                String tmp5 = st.nextToken();
                String tmp6 = st.nextToken();
                String tmp7 = st.nextToken();
                String tmp9 = (st.hasMoreTokens()) ? st.nextToken("") : "Barrier " + (idx + 1);

                //setData(BarriersHgt	+idx, tmp5, true); 
                //setData(BarriersPors+idx, tmp6, true); 
                //setData(BarriersWid	+idx, tmp7, true);
                setData(BarriersObj + "-" + tmp8, new BarrierPolygon(tmp1, tmp2, tmp3, tmp4,
                        tmp5, tmp6, tmp7, tmp8, tmp9));
            }

            // Subregions - only 1 currently displayed (must be whole area)

            inputStr = getLine(in);
//			setData(SubRegNum 		, inputStr, true); 
            cnt = Integer.parseInt(inputStr.trim());
            for (int idx = 0; idx < cnt; idx++) {
                inputStr = getLine(in);
                st = new StringTokenizer(inputStr, ", ");
                setData(SubRegOrgX + "+" + idx, st.nextToken(), true);
                setData(SubRegOrgY + "+" + idx, st.nextToken(), true);
                setData(SubRegLenX + "+" + idx, st.nextToken(), true);
                setData(SubRegLenY + "+" + idx, st.nextToken(), true);

                // Biomass

                inputStr = getLine(in);
                setData(BiomassHgt + "+" + idx, inputStr /*getLine(in)*/, true);
                inputStr = getLine(in);
                setData(CropHgt + "+" + idx, inputStr /*getLine(in)*/, true);
                inputStr = getLine(in);
                st = new StringTokenizer(inputStr, ", ");
                setData(CropGSAI + "+" + idx, st.nextToken(), true);
                setData(CropGLAI + "+" + idx, st.nextToken(), true);
                inputStr = getLine(in);
                st = new StringTokenizer(inputStr, ", ");
                setData(BiomassRSAI + "+" + idx, st.nextToken(), true);
                setData(BiomassRLAI + "+" + idx, st.nextToken(), true);
                inputStr = getLine(in);
                st = new StringTokenizer(inputStr, ", ");
                setData(CropRowSpacing + "+" + idx, st.nextToken(), true);
                setData(CropRowPlacemnt + "+" + idx, st.nextToken(), true);
                inputStr = getLine(in);
                st = new StringTokenizer(inputStr, ", ");
                setData(BiomassFlat + "+" + idx, st.nextToken(), true); // not used
                //		setData(BiomassStanding+"+"+idx	, st.nextToken(), true); // not used
                //		setData(BiomassTotal+"+"+idx		, st.nextToken(), true);

                // Soil layers

                inputStr = getLine(in);
                st = new StringTokenizer(inputStr, ", ");
                String layStr = st.nextToken();
                setData(LayerNum + "+" + idx, layStr, true);
                int numLayers = Integer.parseInt(layStr.trim());
                if (numLayers > MaxLayers) {
                    numLayers = 3;
                }
                parseLayerLine(LayerThickness, getLine(in), numLayers, idx);
                parseLayerLine(LayerBD, getLine(in), numLayers, idx);
                parseLayerLine(LayerSand, getLine(in), numLayers, idx);
                parseLayerLine(LayerVFSand, getLine(in), numLayers, idx);
                parseLayerLine(LayerSilt, getLine(in), numLayers, idx);
                parseLayerLine(LayerClay, getLine(in), numLayers, idx);
                parseLayerLine(LayerRock, getLine(in), numLayers, idx);
                parseLayerLine(LayerAggDen, getLine(in), numLayers, idx);
                parseLayerLine(LayerAggSta, getLine(in), numLayers, idx);
                parseLayerLine(LayerAggGMD, getLine(in), numLayers, idx);
                parseLayerLine(LayerAggMin, getLine(in), numLayers, idx);
                parseLayerLine(LayerAggMax, getLine(in), numLayers, idx);
                parseLayerLine(LayerAggGSD, getLine(in), numLayers, idx);

                // Soil surface

                inputStr = getLine(in);
                st = new StringTokenizer(inputStr, ", ");
                setData(SurfCrustFrac + "+" + idx, st.nextToken(), true);
                setData(SurfCrustThk + "+" + idx, st.nextToken(), true);
                setData(SurfLMFrac + "+" + idx, st.nextToken(), true);
                setData(SurfLMMass + "+" + idx, st.nextToken(), true);
                setData(SurfCrustDen + "+" + idx, st.nextToken(), true);
                setData(SurfCrustSta + "+" + idx, st.nextToken(), true);
                setData(SurfARR + "+" + idx, getLine(in), true);
                inputStr = getLine(in);
                st = new StringTokenizer(inputStr, ", ");
                setData(SurfRidgHgt + "+" + idx, st.nextToken(), true);
                setData(SurfRidgSpacing + "+" + idx, st.nextToken(), true);
                setData(SurfRidgWid + "+" + idx, st.nextToken(), true);
                setData(SurfRidgOrient + "+" + idx, st.nextToken(), true);
                setData(SurfDikeSpacing + "+" + idx, getLine(in), true);

                // Hydrology

                setData(SurfSnowDepth + "+" + idx, getLine(in), true);
//				setData(HydroWPWC+"+"+idx		, getLine(in), true);
//				setData(HydroLayerWC+"+"+idx			, getLine(in), true);
                parseLayerLine(LayerWPWC, getLine(in), numLayers, idx);
                inputStr = getLine(in);			// skip layer WCs
//				st = new StringTokenizer(inputStr, ", ");
//				setData(HydroLayerWC+"+"+idx			, st.nextToken(), true);
//				setData(HydroSurfWC+"1"+"+"+idx			, getLine(in), true);
//				setData(HydroSurfWC+"2"+"+"+idx			, getLine(in), true);
                inputStr = getLine(in);
                st = new StringTokenizer(inputStr, ", \t");
                for (int wdx = 0; wdx < 24; wdx++) {		// 24 hours/day
                    if (!st.hasMoreTokens()) {
                        inputStr = getLine(in);
                        st = new StringTokenizer(inputStr, ", \t");
                    }
                    setData(SurfWC + wdx + "+" + idx, st.nextToken(), true);
                }
            }

            // Weather

            setData(WeaAirDen, getLine(in), true);
            setData(WeaWindDir, getLine(in), true);
            inputStr = getLine(in);
            setData(WeaDailySteps, inputStr, true);
            int numSteps = Integer.parseInt(inputStr.trim());
            inputStr = getLine(in);
            st = new StringTokenizer(inputStr, ", ");
            setData(WeaAnemHgt, st.nextToken(), true);
            setData(WeaAeroRough, st.nextToken(), true);
            setData(WeaZoLocFlg, st.nextToken(), true);
            inputStr = getLine(in);
//			setData(WeaWindWeibull	, inputStr, true);
            if (inputStr.trim().startsWith("0")) {  // old style file
                inputStr = getLine(in);
                st = new StringTokenizer(inputStr, ", ");
                setData(WeaCalmWind, st.nextToken(), true);
                setData(WeaWeibullC, st.nextToken(), true);
                setData(WeaWeibullK, st.nextToken(), true);
            } else {
                String[] inpElms = inputStr.trim().split("\\s+");
                if (inpElms.length == 4) {
                    setData(WeaCalmWind, inpElms[1], true);
                    setData(WeaWeibullC, inpElms[2], true);
                    setData(WeaWeibullK, inpElms[3], true);
                }
                StringBuffer sb = new StringBuffer();
                inputStr = getLine(in);
                st = new StringTokenizer(inputStr, ", \t");
                for (int wdx = 0; wdx < numSteps; wdx++) {
                    if (!st.hasMoreTokens()) {
                        inputStr = getLine(in);
                        st = new StringTokenizer(inputStr, ", \t");
                    }
                    sb.append(st.nextToken());
                    sb.append(" ");
                }
                setData(WeaWindSpeeds, sb.toString(), true);
            }

            // Plot flags
            // set up default values in case file lies about having plot flags
            setData(PlotFieldLen, "1", true);
            setData(PlotBiomass, "1", true);
            setData(PlotSAI, "1", true);
            setData(PlotLAI, "1", true);
            setData(PlotFlatCover, "1", true);
            setData(PlotVFSand, "1", true);
            setData(PlotSand, "1", true);
            setData(PlotSilt, "1", true);
            setData(PlotClay, "1", true);
            setData(PlotRock, "1", true);
            setData(PlotAggStab, "1", true);
            setData(PlotAggGMD, "1", true);
            setData(PlotAggMin, "1", true);
            setData(PlotAggMax, "1", true);
            setData(PlotAggStd, "1", true);
            setData(PlotCrustFrac, "1", true);
            setData(PlotCrustThk, "1", true);
            setData(PlotLMFrac, "1", true);
            setData(PlotLMMass, "1", true);
            setData(PlotCrustDen, "1", true);
            setData(PlotCrustStab, "1", true);
            setData(PlotRandRough, "1", true);
            setData(PlotRidgeHgt, "1", true);
            setData(PlotRidgeSpc, "1", true);
            setData(PlotRidgeWid, "1", true);
            setData(PlotRidgeOrient, "1", true);

            String plotFlg = getLine(in).trim();

            setData(PlotFlg, plotFlg, true);
            if (!plotFlg.equals("-1")) {
                setData(PlotFieldLen, getLine(in), true);
                getLine(in);
                setData(PlotBiomass, getLine(in), true);
                getLine(in);
                setData(PlotSAI, getLine(in), true);
                getLine(in);
                setData(PlotLAI, getLine(in), true);
                getLine(in);
                setData(PlotFlatCover, getLine(in), true);
                getLine(in);
                setData(PlotVFSand, getLine(in), true);
                getLine(in);
                setData(PlotSand, getLine(in), true);
                getLine(in);
                setData(PlotSilt, getLine(in), true);
                getLine(in);
                setData(PlotClay, getLine(in), true);
                getLine(in);
                setData(PlotRock, getLine(in), true);
                getLine(in);
                setData(PlotAggStab, getLine(in), true);
                getLine(in);
                setData(PlotAggGMD, getLine(in), true);
                getLine(in);
                setData(PlotAggMin, getLine(in), true);
                getLine(in);
                setData(PlotAggMax, getLine(in), true);
                getLine(in);
                setData(PlotAggStd, getLine(in), true);
                getLine(in);
                setData(PlotCrustFrac, getLine(in), true);
                getLine(in);
                setData(PlotCrustThk, getLine(in), true);
                getLine(in);
                setData(PlotLMFrac, getLine(in), true);
                getLine(in);
                setData(PlotLMMass, getLine(in), true);
                getLine(in);
                setData(PlotCrustDen, getLine(in), true);
                getLine(in);
                setData(PlotCrustStab, getLine(in), true);
                getLine(in);
                setData(PlotRandRough, getLine(in), true);
                getLine(in);
                setData(PlotRidgeHgt, getLine(in), true);
                getLine(in);
                setData(PlotRidgeSpc, getLine(in), true);
                getLine(in);
                setData(PlotRidgeWid, getLine(in), true);
                getLine(in);
                setData(PlotRidgeOrient, getLine(in), true);
                getLine(in);
            }
            in.close();
        } catch (IOException f) {
            //System.err.println("DS_rTF: " + lineNum + " " + f);
            f.printStackTrace();
        } catch (java.util.NoSuchElementException g) {
            //System.err.println("DS_rTF: " + lineNum + " " + g);
            g.printStackTrace();
        }
        changes.firePropertyChange(DataChanged, "", "0");
    }
    public String[] validateMsgs = {
        "No error",
        "Crust fraction not equal 0 and crust thickness equals 0",
        "Crust fraction not equal 0 and crust density equals 0",
        "Crust fraction not equal 0 and crust stability equals 0",
        "Loose material fraction not 0 and loose material mass equals 0"
    };
    public String[] validateFields = {
        "",
        SurfCrustThk,
        SurfCrustDen,
        SurfCrustSta,
        SurfLMMass
    };

    public int validate() {

        String subRegStr = (String) ht.get(SubRegNum);
        int numSubr = Integer.parseInt(subRegStr);

        for (int rdx = 0; rdx < numSubr; rdx++) {

            double crsFra = Double.parseDouble(getData(SurfCrustFrac + "+" + rdx, true));
            double crsThk = Double.parseDouble(getData(SurfCrustThk + "+" + rdx, true));
            double crsDen = Double.parseDouble(getData(SurfCrustDen + "+" + rdx, true));
            double crsSta = Double.parseDouble(getData(SurfCrustSta + "+" + rdx, true));
            if (crsFra != 0.0) {
                if (crsThk == 0.0) {
                    return 1;
                }
                if (crsDen == 0.0) {
                    return 2;
                }
                if (crsSta == 0.0) {
                    return 3;
                }
            }
            double looMat = Double.parseDouble(getData(SurfLMFrac + "+" + rdx, true));
            double looMas = Double.parseDouble(getData(SurfLMMass + "+" + rdx, true));
            if (looMat != 0.0) {
                if (looMas == 0.0) {
                    return 4;
                }
            }
        }
        return 0;
    }

    private String calBD(String rockStr, String lepStr, String bdStr, int numLayers) {
        StringTokenizer rst = new StringTokenizer(rockStr);
        StringTokenizer lst = new StringTokenizer(lepStr);
        StringTokenizer bst = new StringTokenizer(bdStr);
        StringBuffer sb = new StringBuffer();
        for (int idx = 0; idx < numLayers; idx++) {
            double rf = Double.parseDouble(rst.nextToken());
            double lep = Double.parseDouble(lst.nextToken());
            double bd = Double.parseDouble(bst.nextToken());
            double dbd = 0;

            if (rf == 0.0) {
                dbd = bd * java.lang.Math.pow((lep / 100) + 1, 3);
            } else {
                dbd = bd * java.lang.Math.pow((lep / (100 * (1 - rf))) + 1, 3);
            }
            sb.append(dbd);
            sb.append(" ");
        }
        return sb.toString();
    }

    /**
     * loads soil data from an IFC file
     */
    public void readIFCFile(File inpFile, int subrIdx) {
        lineNum = 0;
        try {
            BufferedReader in = new BufferedReader(new FileReader(inpFile));

            getLine(in);	// skip version
            setData(SoilIFCName + "+" + subrIdx, getLine(in), true);
            getLine(in);	// skip local phase
            getLine(in);	// skip soil order
            getLine(in);	// skip soil loss tolerance
            getLine(in);	// skip albedo
            getLine(in);	// skip slope
            getLine(in);	// skip surface fragment cover
            getLine(in);	// skip bedrock
            getLine(in);	// skip root restricting

            // Soil layers

            String inputStr = getLine(in);
            int numLayers = Integer.parseInt(inputStr.trim());
            if (numLayers > MaxLayers) {
                numLayers = 3;
            }
            setData(LayerNum + "+" + subrIdx, "" + numLayers, true);
            parseLayerLine(LayerOrigNum, " 1 2 3", numLayers, subrIdx);
            parseLayerLine(LayerThickness, getLine(in), numLayers, subrIdx);
            parseLayerLine(LayerSand, getLine(in), numLayers, subrIdx);
            parseLayerLine(LayerSilt, getLine(in), numLayers, subrIdx);
            parseLayerLine(LayerClay, getLine(in), numLayers, subrIdx);
            String rockStr = getLine(in);
            parseLayerLine(LayerRock, rockStr, numLayers, subrIdx);
            getLine(in);	// skip sand very coarse
            getLine(in);	// skip sand coarse
            getLine(in);	// skip sand medium
            getLine(in);	// skip sand fine
            parseLayerLine(LayerVFSand, getLine(in), numLayers, subrIdx);
//			parseLayerLine(LayerBD			, getLine(in), numLayers, subrIdx); 
            String bdStr = getLine(in);
            getLine(in);	// skip organic matter
            getLine(in);	// skip soil ph
            getLine(in);	// skip CaCO3
            getLine(in);	// skip CEC
//			getLine(in);	// skip linear ext
            String lepStr = getLine(in);
            String dbdStr = calBD(rockStr, lepStr, bdStr, numLayers);
            parseLayerLine(LayerBD, dbdStr, numLayers, subrIdx);
            parseLayerLine(LayerAggGMD, getLine(in), numLayers, subrIdx);
            parseLayerLine(LayerAggGSD, getLine(in), numLayers, subrIdx);
            parseLayerLine(LayerAggMax, getLine(in), numLayers, subrIdx);
            parseLayerLine(LayerAggMin, getLine(in), numLayers, subrIdx);
            parseLayerLine(LayerAggDen, getLine(in), numLayers, subrIdx);
            parseLayerLine(LayerAggSta, getLine(in), numLayers, subrIdx);

            // Soil crust

            setData(SurfCrustThk + "+" + subrIdx, getLine(in), true);
            setData(SurfCrustDen + "+" + subrIdx, getLine(in), true);
            setData(SurfCrustSta + "+" + subrIdx, getLine(in), true);
            setData(SurfCrustFrac + "+" + subrIdx, getLine(in), true);
            setData(SurfLMMass + "+" + subrIdx, getLine(in), true);
            setData(SurfLMFrac + "+" + subrIdx, getLine(in), true);
            setData(SurfARR + "+" + subrIdx, getLine(in), true);
            setData(SurfRidgOrient + "+" + subrIdx, getLine(in), true);
            setData(SurfRidgHgt + "+" + subrIdx, getLine(in), true);
            setData(SurfRidgSpacing + "+" + subrIdx, getLine(in), true);
            setData(SurfRidgWid + "+" + subrIdx, getLine(in), true);
            setData(SurfDikeSpacing + "+" + subrIdx, "0.0", true);


            getLine(in);	// skip init BD
            getLine(in);				// skip wc
            getLine(in);	// skip saturated SWC
            getLine(in);	// skip field capacity SWC
            parseLayerLine(LayerWPWC, getLine(in), numLayers, subrIdx);

            in.close();
        } catch (IOException f) {
            //System.err.println("DS_rTF: " + lineNum + " " + f);
            f.printStackTrace();
        } catch (java.util.NoSuchElementException g) {
            //System.err.println("DS_rTF: " + lineNum + " " + g);
            g.printStackTrace();
        }
    }

    private void writeLayer(PrintWriter outprt, String prop, int sdx, int numLay) {
        for (int idx = 0; idx < numLay; idx++) {
            outprt.print(" " + ht.get(prop + idx + "+" + sdx));
        }
        outprt.println();
    }

    Vector makeBarVec() {
        Vector barVec = new Vector();
        for (Iterator hti = ht.values().iterator(); hti.hasNext();) {
            Object obj = hti.next();
            if (obj instanceof BarrierPolygon) {
                BarrierPolygon bp = (BarrierPolygon) obj;
//                if (bp.getX1() == 0.0 && bp.getX2() == 0.0 &&
//                        bp.getY1() == 0.0 && bp.getY2() == 0.0) continue;
                barVec.add(obj);
            }
        }
        return barVec;
    }

    public void clearBarriers() {
        List<String> keys = new Vector<String>();
        for (Iterator ki = ht.keySet().iterator(); ki.hasNext();) {
            Object key = ki.next();
            Object obj = ht.get(key);
            if (obj instanceof BarrierPolygon) {
                //ki.remove();
                keys.add(key.toString());
            }
        }
        for (String key : keys) {
            setData(key, null);
        }
    }

    public void writeTextFile(File outFile) {

        try {
            String fileName = outFile.getCanonicalPath();
            if (!fileName.endsWith(DataStore.InputExt)) {		// add .in if needed
                fileName += DataStore.InputExt;
                outFile = new File(fileName);
            }
            PrintWriter outprt = new PrintWriter(new BufferedWriter(new FileWriter(outFile)));

            outprt.println("#****************************************************************");
            outprt.println("#  File name  " + outFile.getName() + "  Creation timestamp  " + new java.sql.Timestamp(System.currentTimeMillis()));
            outprt.println("#****************************************************************");
            outprt.println("#");
            outprt.println("#     +++ PURPOSE +++");
            outprt.println("#");
            outprt.println("#     Input file which is read by subroutine erodin.for");
            outprt.println("#");
            outprt.println("#     All lines beginning with a '#' character are assumed to");
            outprt.println("#     be comment lines and are skipped.");
            outprt.println("#");
            outprt.println("#     +++ DEFINITIONS +++");
            outprt.println("#");
            outprt.println("#     * = inputs NOT presently used by erosion");
            outprt.println("#         (most of these are expected to be used in the future)");
            outprt.println("#     All other input values must be correctly specified.");
            outprt.println("#");
            outprt.println("#     All comments prior to each line of data input");
            outprt.println("#     in this template input file have the following format:");
            outprt.println("#");
            outprt.println("#     Variable_Name, Var_type, (src include file)  Text Definition");
            outprt.println("#");
            outprt.println("#     where Var_type is: I = integer L = logical R = real");
            outprt.println("#");
            outprt.println("#");
            outprt.println("# +++ DEBUG STUFF +++");
            outprt.println("#");
            outprt.println("#     debugflg - debug flag for providing different levels of debug info");
            outprt.println("#                value of 0 will print no debug information");
            outprt.println("#                value of 1 will print out and number all input lines");
            outprt.println("#                value of 2 will print out and number all data input lines");
            outprt.println("#                value of 3 will do both 1 and 2 input line debug output");
//			outprt.println(" 0");
            outprt.println(" 3");
//			outprt.println(" " + ht.get(DebugCode));
            outprt.println("#");
            outprt.println("#");
            outprt.println("# +++ INIT STUFF +++");
            outprt.println("#");
            outprt.println("#     am0eif, L, (m1flag.inc) EROSION initialization flag");
            outprt.println(" .TRUE.");
//			outprt.println(" " + ht.get(InitFlg));
            outprt.println("#     am0efl, L, (m1flag.inc) EROSION 'print' flag");
            outprt.println(" 1");
//			outprt.println(" " + ht.get(PrintFlg));
            outprt.println("#");
            outprt.println("# +++ SIMULATION REGION +++");
            outprt.println("#");
            outprt.println("#     amxsim(x,y), R, (m1geo.inc) Simulation Region diag. coordinates (m)");
            outprt.println("#                     Input x,y coordinates in this form: x1,y1  x2,y2");
//			outprt.println("  0.0, 0.0, 1000.0, 200.0");

            FieldPolygon fp = (FieldPolygon) ht.get(SimField);
////System.out.println("DS_wTF: " + fp);            
            outprt.printf("%10.1f %10.1f %10.1f %10.1f\n", fp.getX1(), fp.getY1(), fp.getX2(), fp.getY2());
//			outprt.println(" " + ht.get(SimRegOrgX) + " " +ht.get(SimRegOrgY) + " "
//						   + ht.get(SimRegLenX) + " " + ht.get(SimRegLenY) + " ");
//			
            outprt.println("#");
            outprt.println("#     amasim, R, (m1geo.inc) Simulation Region orientation angle (deg. from North)");
            outprt.println(" " + ht.get(SimRegAngle));
//			outprt.println(" 0.0");
            outprt.println("#");
            outprt.println("# +++ ACCOUNTING REGIONS +++");
            outprt.println("#");
            outprt.println("#     nacctr, I, (m1geo.inc) Number of accounting regions (must be 1 for now)");
            outprt.println(" 1");
            outprt.println("#");
            outprt.println("#     amxar(x,y,a), R, (m1geo.inc) Accounting Region diag. coordinates (m)");
            outprt.println("#                     Input x,y coordinates in this form: x1,y1  x2,y2");
            outprt.println("#                     for each accounting region specified (nacctr)");
            // just use sim region for accounting region for now
            outprt.printf("%10.1f %10.1f %10.1f %10.1f\n", fp.getX1(), fp.getY1(), fp.getX2(), fp.getY2());
//
//            outprt.println(" " + ht.get(SimRegOrgX) + " " +ht.get(SimRegOrgY) + " "
//						   + ht.get(SimRegLenX) + " " + ht.get(SimRegLenY) + " ");
//			outprt.println(" 0.0, 0.0, 1000.0, 200.0");
            outprt.println("#");
            outprt.println("# +++ BARRIERS +++");
            outprt.println("#");
            outprt.println("#     nbr, I, (m1geo.inc) Number of barriers (0-5)");
            Vector barVec = makeBarVec();
            int barCnt = barVec.size();
////System.out.println("DS_wTF: barrier count " + barCnt);     
            outprt.println("" + barCnt);
//			String barriersStr = (String) ht.get(BarriersNum);
//			int numBarriers = Integer.parseInt(barriersStr);
//
//			outprt.println("  " + barriersStr);
            outprt.println("#     NOTE: Remaining BARRIER inputs are repeated for each barrier specified");
            outprt.println("#     If no barriers specified (nbr=0), then no BARRIER inputs will be here");
            outprt.println("#");
//			for (int bdx = 0; bdx < numBarriers; bdx++) {
            for (Iterator bvi = barVec.iterator(); bvi.hasNext();) {
                outprt.println("#     amxbr(x,y,b), R, (m1geo.inc) Barrier linear coordinates (m)");
                outprt.println("#                     Input x,y coordinates in this form: x1,y1  x2,y2");
                outprt.println("#                     for each barrier specified (nbr)");
                BarrierPolygon bp = (BarrierPolygon) bvi.next();
                outprt.printf("%10.1f %10.1f %10.1f %10.1f %s\n", bp.getX1(), bp.getY1(),
                        bp.getX2(), bp.getY2(), bp.getName());
//				outprt.println(" 0.0 0.0 0.0 200.0");
//				outprt.print(" " + ht.get(BarriersOrgX+bdx));
//				outprt.print(" " + ht.get(BarriersOrgY+bdx));
//				outprt.print(" " + ht.get(BarriersLenX+bdx));
//				outprt.print(" " + ht.get(BarriersLenY+bdx));
//				outprt.println();
                outprt.println("#       amzbr(b), R, (m1geo.inc) Barrier height (m)");
                outprt.println("#       ampbr(b), R, (m1geo.inc) Barrier porosity (m^2/m^2)");
                outprt.println("#       amxbrw(b), R, (m1geo.inc) Barrier width (m)");
                outprt.printf("%10.3f %10.3f %10.3f %s\n", bp.getHgt(), bp.getPorosity(),
                        bp.getWid(), bp.getType());
//				outprt.print(" " + ht.get(BarriersHgt+bdx));
//				outprt.print(" " + ht.get(BarriersPors+bdx));
//				outprt.print(" " + ht.get(BarriersWid+bdx));
//				outprt.println();
//				outprt.println(" 0.2 0.5 15.0");
                outprt.println("#");
            }

            outprt.println("# +++ SUBREGION REGIONS +++");
            outprt.println("#");
            outprt.println("#     nsubr, I, (m1subr.inc) Number of subregions (1-5)");

            String subRegStr = (String) ht.get(SubRegNum);
            int numSubr = Integer.parseInt(subRegStr);

//			outprt.println(" 1");
            outprt.println(" " + subRegStr);
            outprt.println("#");
            outprt.println("#     NOTE: Remaining SUBREGION inputs (BIOMASS, SOIL, and HYDROLOGY,");
            outprt.println("#     ie. variables defined by subregion) are repeated for nsubr");
            outprt.println("#     subregions specified");
            outprt.println("#");
            outprt.println("#");
            for (int rdx = 0; rdx < numSubr; rdx++) {
                outprt.println("#     amxsr(x,y,s), R, (m1subr.inc) Subregion diag. coordinates (m)");
                outprt.println("#                     Input x,y coordinates in this form: x1,y1  x2,y2");
                outprt.println("#                     for each subregion specified (subr)");
//				outprt.println(" 0.0, 0.0, 1000.0, 200.0");
                // just use sim region for accounting region for now
//				outprt.println(" " + ht.get(SimRegOrgX) + " " +ht.get(SimRegOrgY) + " "
//							   + ht.get(SimRegLenX) + " " + ht.get(SimRegLenY) + " ");
                outprt.printf("%10.1f %10.1f %10.1f %10.1f\n", fp.getX1(), fp.getY1(), fp.getX2(), fp.getY2());
                outprt.println("#     +++ BIOMASS +++");
                outprt.println("#");
                outprt.println("#       abzht(s), R, (b1glob.inc) Overall biomass height (m)");
//			outprt.println(" 0.21");
                outprt.println(" " + ht.get(BiomassHgt + "+" + rdx));
                outprt.println("#");
                outprt.println("#       aczht(s), R, (c1glob.inc) Crop height (m)");
//			outprt.println(" 0");
                outprt.println(" " + ht.get(CropHgt + "+" + rdx));
                outprt.println("#");
                outprt.println("#       acrsai(s), R, (c1glob.inc) Crop stem area index (m^2/m^2)");
                outprt.println("#       acrlai(s), R, (c1glob.inc) Crop leaf area index (m^2/m^2)");
//			outprt.println(" 0 0");
                outprt.println(" " + ht.get(CropGSAI + "+" + rdx) + " " + ht.get(CropGLAI + "+" + rdx));
                outprt.println("#");
                outprt.println("#       adrsaitot(s), R, (d1glob.inc) Residue stem area index (m^2/m^2)");
                outprt.println("#       adrlaitot(s), R, (d1glob.inc) Residue leaf area index (m^2/m^2)");
//			outprt.println(" 0.02  0.00");
                outprt.println(" " + ht.get(BiomassRSAI + "+" + rdx) + " " + ht.get(BiomassRLAI + "+" + rdx));
                outprt.println("#");
                outprt.println("#      acxrow(s), R, (c1gen.inc) crop row spacing (m), 0=broadcast");
                outprt.println("#      ac0rg(s) , I, (c1gen.inc) seed location (0=furrow,1=ridge)");
//			outprt.println("  0.3, 0");
                outprt.println(" " + ht.get(CropRowSpacing + "+" + rdx) + " " + ht.get(CropRowPlacemnt + "+" + rdx));
                outprt.println("# These are not implemented within EROSION");
                outprt.println("#       abrsaz(h,s), R, (b1geom.inc) Biomass stem area index by ht (1/m)");
                outprt.println("# (should be 5 values here when used)");
                outprt.println("#       abrlaz(h,s), R, (b1geom.inc) Biomass leaf area index by ht (1/m)");
                outprt.println("# (should be 5 values here when used)");
                outprt.println("#");
                outprt.println("# Only abffcv(s) is currently implemented within EROSION");
                outprt.println("#       abffcv(s), R, (b1geom.inc) Flat biomass cover (m^3/m^3)");
                outprt.println("#       abfscv(s), R, (b1geom.inc) Standing biomass cover (m^3/m^3)");
                outprt.println("#       abftcv(s), R, (b1geom.inc) Total biomass cover (m^3/m^3)");
                outprt.println("# (should be 3 values here when abffcv(s) and abfscv(s) get used in the future)");
                outprt.println("# 0.098 with residue");
//			outprt.println(" 0.0 no residue");
//				outprt.println(" " + ht.get(BiomassTotal+"+"+rdx));
                outprt.println(" " + ht.get(BiomassFlat + "+" + rdx));
                outprt.println("#");
                outprt.println("#     +++ SOIL +++");
                outprt.println("#");
                outprt.println("#     nslay(s), I, (s1layr.inc) Number of soil layers (1-10)");
                String soilIFCName = (String) ht.get(SoilIFCName + "+" + rdx);
                outprt.println(" " + ht.get(LayerNum + "+" + rdx) + "  " + ((soilIFCName == null) ? "User created" : soilIFCName));
                int numLay = Integer.parseInt(((String) ht.get(LayerNum + "+" + rdx)).trim());
                if (numLay == 0) {
                    numLay = 1;
//				outprt.println(" 1");
                }
                outprt.println("#");
                outprt.println("#     NOTE: Remaining SOIL inputs are repeated for each layer specified");
                outprt.println("#");
                outprt.println("#     aszlyt(l,s), R, (s1layr.inc) Soil layer thickness (mm)");
//				outprt.println(" 1000.0");
                writeLayer(outprt, LayerThickness, rdx, numLay);
                outprt.println("#");
                outprt.println("#     asdblk(l,s), R, (s1phys.inc) Soil layer bulk density (Mg/m^3)");
                writeLayer(outprt, LayerBD, rdx, numLay);
//				outprt.println(" 1.8");
                outprt.println("#");
                outprt.println("#     asfsan(l,s), R, (s1dbh.inc) Soil layer sand content (Mg/Mg)");
                writeLayer(outprt, LayerSand, rdx, numLay);
//				outprt.println(" 0.90");
                outprt.println("#     asfvfs(l,s), R  (s1dbh.inc) Soil layer very fine sand(Mg/Mg)");
                writeLayer(outprt, LayerVFSand, rdx, numLay);
//				outprt.println(" 0.21");
                outprt.println("#     asfsil(l,s), R, (s1dbh.inc) Soil layer silt content (Mg/Mg)");
                writeLayer(outprt, LayerSilt, rdx, numLay);
//				outprt.println(" 0.08");
                outprt.println("#     asfcla(l,s), R, (s1dbh.inc) Soil layer clay content (Mg/Mg)");
                writeLayer(outprt, LayerClay, rdx, numLay);
//				outprt.println(" 0.02");
                outprt.println("#");
                outprt.println("#     asvroc(l,s), R, (s1dbh.inc) Soil layer rock volume (m^3/m^3)");
                writeLayer(outprt, LayerRock, rdx, numLay);
//				outprt.println(" 0.30");
                outprt.println("#");
                outprt.println("#     asdagd(l,s), R, (s1agg.inc) Soil layer agg density (Mg/m^3)");
                writeLayer(outprt, LayerAggDen, rdx, numLay);
//				outprt.println(" 1.8");
                outprt.println("#     aseags(l,s), R, (s1agg.inc) Soil layer agg stability ln(J/kg)");
                writeLayer(outprt, LayerAggSta, rdx, numLay);
//				outprt.println(" 2.50");
                outprt.println("#     aslagm(l,s), R, (s1agg.inc) Soil layer GMD (mm)");
                writeLayer(outprt, LayerAggGMD, rdx, numLay);
//				outprt.println(" 0.47");
                outprt.println("#     aslagn(l,s), R, (s1agg.inc) Soil layer minimum agg size (mm)");
                writeLayer(outprt, LayerAggMin, rdx, numLay);
//				outprt.println(" 0.043");
                outprt.println("#     aslagx(l,s), R, (s1agg.inc) Soil layer maximum agg size (mm)");
                writeLayer(outprt, LayerAggMax, rdx, numLay);
//				outprt.println(" 89.8");
                outprt.println("#     as0ags(l,s), R, (s1agg.inc) Soil layer GSD (mm/mm)");
                writeLayer(outprt, LayerAggGSD, rdx, numLay);
//				outprt.println(" 12.0");
                outprt.println("#");
                outprt.println("#");
                outprt.println("#     asfcr(s), R, (s1surf.inc) Surface crust fraction (m^2/m^2)");
                outprt.println("#     aszcr(s), R, (s1surf.inc) Surface crust thickness (mm)");
                outprt.println("#     asflos(s), R, (s1surf.inc) Fraction of loose material on surface (m^2/m^2)");
                outprt.println("#     asmlos(s), R, (s1surf.inc) Mass of loose material on crust (kg/m^2)");
                outprt.println("#     asdcr(s), R, (s1surf.inc) Soil crust density (Mg/m^3)");
                outprt.println("#     asecr(s), R, (s1surf.inc) Soil crust stability ln(J/kg)");
                outprt.print(" " + ht.get(SurfCrustFrac + "+" + rdx));
                outprt.print(" " + ht.get(SurfCrustThk + "+" + rdx));
                outprt.print(" " + ht.get(SurfLMFrac + "+" + rdx));
                outprt.print(" " + ht.get(SurfLMMass + "+" + rdx));
                outprt.print(" " + ht.get(SurfCrustDen + "+" + rdx));
                outprt.print(" " + ht.get(SurfCrustSta + "+" + rdx));
                outprt.println();
//				outprt.println(" 0.6 7.0 0.2 0.4 0.1 1.0");
                outprt.println("#");
                outprt.println("#");
                outprt.println("#");
                outprt.println("#     aslrr(s), R, (s1sgeo.inc) Allmaras random roughness (mm)");
                outprt.println(" " + ht.get(SurfARR + "+" + rdx));
//				outprt.println(" 5.0");
                outprt.println("#     aszrgh(s), R, (s1sgeo.inc) Ridge height (mm)");
                outprt.println("#     asxrgs(s), R, (s1sgeo.inc) Ridge spacing (mm)");
                outprt.println("#     asxrgw(s), R, (s1sgeo.inc) Ridge width (mm)");
                outprt.println("#     asxrgo(s), R, (s1sgeo.inc) Ridge orientation (deg)");
//				outprt.println(" 0.0 0.0 0.0 0");
                outprt.print(" " + ht.get(SurfRidgHgt + "+" + rdx));
                outprt.print(" " + ht.get(SurfRidgSpacing + "+" + rdx));
                outprt.print(" " + ht.get(SurfRidgWid + "+" + rdx));
                outprt.print(" " + ht.get(SurfRidgOrient + "+" + rdx));
                outprt.println();
                outprt.println("#     asxdks(s), R, (s1sgeo.inc) Dike spacing (mm)");
                outprt.println(" " + ht.get(SurfDikeSpacing + "+" + rdx));
//				outprt.println(" 0.0");
                outprt.println("#");
                outprt.println("#     +++ HYDROLOGY +++");
                outprt.println("#");
                outprt.println("#     ahzsnd(s), R, (s1sgeo.inc) Snow depth (mm)");
                outprt.println(" " + ht.get(SurfSnowDepth + "+" + rdx));
//				outprt.println(" 0.0");
                outprt.println("#");
                outprt.println("#     ahrwcw(l,s), R, (h1db1.inc) Soil layer wilting point water content (Mg/Mg)");
//				outprt.println(" " + ht.get(HydroWPWC+"+"+rdx) + " 0.0 0.0");
                writeLayer(outprt, LayerWPWC, rdx, numLay);
//				outprt.println(" 0.077");
                outprt.println("#");
                outprt.println("#     ahrwca(l,s), R, (h1db1.inc) Soil layer water content (Mg/Mg)");
//				outprt.println(" " + ht.get(HydroLayerWC+"+"+rdx));
                outprt.println("  0.0 0.0 0.0");
//				outprt.println(" 0.0");
                outprt.println("#");
                outprt.println("#     ahrwc0(h,s), R, (h1db1.inc) Surface layer water content (Mg/Mg)");
                outprt.println("#                  NOTE: the near surface water content is specified on an");
                outprt.println("#                        hourly basis.  We read in the hrly water content");
                outprt.println("#                        on two lines, with 12 values in each line.");
                for (int jdx = 0; jdx < 24; jdx++) {
                    outprt.print(" " + ht.get(SurfWC + jdx + "+" + rdx));
                    if ((jdx % 12) == 11) {
                        outprt.println();
                    }
                }
//				outprt.println(" 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0");
//				outprt.println(" 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0");
                outprt.println("#");
            }

            outprt.println("#");
            outprt.println("# NOTE: This is the end of the SUBREGION variables");
            outprt.println("#");
            outprt.println("#     +++ WEATHER +++");
            outprt.println("#");
            outprt.println("#     awdair, R, (w1pavg.inc) Air density (kg/m^3)");
//			outprt.println(" 1.2");
            outprt.println(" " + ht.get(WeaAirDen));
            outprt.println("#");
            outprt.println("#     awadir, R, (w1wind.inc) Wind direction (deg)");
            outprt.println(" " + ht.get(WeaWindDir));
//			outprt.println(" 270");
            outprt.println("#");
            outprt.println("#     ntstep, I, (local variable) Number of intervals/day to run EROSION");
            outprt.println(" " + ht.get(WeaDailySteps));
//			outprt.println(" 24");
            outprt.println("#");
            outprt.println("#     anemht, R  anemometer height (m)");
            outprt.println("#     awzzo,  R  aerodynamic roughness at anemometer site (mm)");
            outprt.println("#     wzoflg, I (global variable) zo location flag");
            outprt.println("#               (flag =0 - zo fixed at wx sta. location)");
            outprt.println("#               (flag = 1 - zo variable at field location)");
            outprt.print(" " + ht.get(WeaAnemHgt));
            outprt.print(" " + ht.get(WeaAeroRough));
            outprt.print(" " + ht.get(WeaZoLocFlg));
            outprt.println();
//			outprt.println("    10.0,  10.00  0");
            outprt.println("#     wflg, I, (local variable) Wind/Weibull flag");
            outprt.println("#              (0 - read in Weibull parameters, 1 - read in wind speeds)");
//			String weiFlg = (String) ht.get(WeaWindWeibull);
//			outprt.println(" 1");
////System.out.println("DS_wTF: " + weiFlg);			
//			if (weiFlg.trim().equals("0")) {
//    			outprt.println(" " + weiFlg);
//				outprt.println("#");
//				outprt.println("# NOTE: This is only present when (wflg=0)");
//				outprt.println("#     wfcalm, R, (local variable) Fraction of time winds are calm (hr/hr)");
//				outprt.println("#     wuc, R, (local variable) Weibull 'c' factor (m/s)");
//				outprt.println("#     w0k, R, (local variable) Weibull 'k' factor (unitless)");
//				outprt.println("#");
//				outprt.println(" " + ht.get(WeaCalmWind) + " " + ht.get(WeaWeibullC) + " " + ht.get(WeaWeibullK));
//			} else {
            outprt.println(" " + "1" + " " + ht.get(WeaCalmWind) + " " + ht.get(WeaWeibullC) + " " + ht.get(WeaWeibullK));
            outprt.println("# NOTE: The remaining data is only present when (wflg=1)");
            outprt.println("#");
            outprt.println("#     awu(i), R, (w1wind) Wind speed for (ntstep) intervals (m/s)");
            outprt.println("# I think I can read multiple lines with variable number of values");
            outprt.println("# We will try and see - LEW  ( Note: no blank lines allowed - LH)");
            String windStr = (String) ht.get(WeaWindSpeeds);
            StringTokenizer wst = new StringTokenizer(windStr);
            for (int wdx = 0; wst.hasMoreTokens(); wdx++) {
                outprt.print(wst.nextToken() + (((wdx % 6) == 5) ? "\n" : "\t"));
            }
//				outprt.println(ht.get(WeaWindSpeeds));
//				outprt.println("8.181	4.068	4.068	4.426	5.052	5.052	");
//				outprt.println("4.739	4.292	4.515	3.353	3.621	2.280	");
//				outprt.println("5.275	6.750	7.242	7.868	9.835	13.814	");
//				outprt.println("17.211	12.651	11.712	12.964	10.014	8.583	");
            outprt.println("#");
//			}
            outprt.println("#    + + + DATA TO PLOT + + +");
            outprt.println("#");
            outprt.println("#    names and values to input for plot");
            outprt.println("# place 1 flag in 1st line after #-name line for variables to include in plot");
            outprt.println("#");
            outprt.println("#  initial xplot value,I, (-1=no plot, 0 = output indep.variables with 1 flag)");
			outprt.println(" -1");
//            outprt.println(" " + ht.get(PlotFlg));
//            outprt.println("####");
//            outprt.println("#    xin(i), R, (field length)");
////			outprt.println("   1");
//            outprt.println(" " + ht.get(PlotFieldLen));
//            outprt.println("  Length(m)");
//            outprt.println("# abzht, R, (biomass ht.(m))");
////			outprt.println("   1");
//            outprt.println(" " + ht.get(PlotBiomass));
//            outprt.println(" bio_ht(m)");
//            outprt.println("# abrsai, R (stem area index)");
////			outprt.println("  1");
//            outprt.println(" " + ht.get(PlotSAI));
//            outprt.println(" stem_area");
//            outprt.println("#   abrlai(s), R, (b1geom.inc) Biomass leaf area index (m^2/m^2)");
////			outprt.println("  1");
//            outprt.println(" " + ht.get(PlotLAI));
//            outprt.println(" lai_area");
//            outprt.println("# abffcv, R,( biomass flat fraction cover)");
////			outprt.println("  0");
//            outprt.println(" " + ht.get(PlotFlatCover));
//            outprt.println(" flat_cov");
//            outprt.println("#     asfvfs(1,s), R, (soil fraction very fine sand in layer 1)");
////			outprt.println("  0");
//            outprt.println(" " + ht.get(PlotVFSand));
//            outprt.println("  vfsand");
//            outprt.println("#     asfsan(1,s), R, (soil fraction sand in layer 1)");
////			outprt.println("  1");
//            outprt.println(" " + ht.get(PlotSand));
//            outprt.println("   sand");
//            outprt.println("#     asfsil(1,s), R (soil fraction silt in layer 1)");
////			outprt.println("  0");
//            outprt.println(" " + ht.get(PlotSilt));
//            outprt.println("  silt");
//            outprt.println("#     asfcla(1,s), R (soil fraction clay in layer 1)");
////			outprt.println("  0");
//            outprt.println(" " + ht.get(PlotClay));
//            outprt.println("  clay");
//            outprt.println("#     asvoc(1,s), R (soil volume roc in layer 1)(m^3/m^3)");
////			outprt.println("  0");
//            outprt.println(" " + ht.get(PlotRock));
//            outprt.println("  rock_vol");
//            outprt.println("#     aseags(1,s), R (soil aggregate stability) (ln J/m^3)");
////			outprt.println("  0");
//            outprt.println(" " + ht.get(PlotAggStab));
//            outprt.println("  ag_stab");
//            outprt.println("#     aslagm(1,s), R (soil aggregate geom. mean dia.) (mm)");
////			outprt.println("  0");
//            outprt.println(" " + ht.get(PlotAggGMD));
//            outprt.println("  ag_gmd");
//            outprt.println("#     aslagn(1,s), R (soil aggregate min. dia.) (mm)");
////			outprt.println("  0");
//            outprt.println(" " + ht.get(PlotAggMin));
//            outprt.println("  ag_min");
//            outprt.println("#     aslagx(1,s), R (soil aggregate max. dia.) (mm)");
////			outprt.println("  0");
//            outprt.println(" " + ht.get(PlotAggMax));
//            outprt.println("  ag_max");
//            outprt.println("#     as0ags(1,s), R (soil aggregate geo. std. dev.)");
////			outprt.println("  0");
//            outprt.println(" " + ht.get(PlotAggStd));
//            outprt.println("  ag_std");
//            outprt.println("#     asfcr(s), R, (s1surf.inc) Surface crust fraction (m^2/m^2)");
////			outprt.println("  0");
//            outprt.println(" " + ht.get(PlotCrustFrac));
//            outprt.println("  crust_cv");
//            outprt.println("#     aszcr(s), R, (s1surf.inc) Surface crust thickness (mm)");
////			outprt.println("  0");
//            outprt.println(" " + ht.get(PlotCrustThk));
//            outprt.println(" crust_z(mm)");
//            outprt.println("#     asflos(s), R, (s1surf.inc) Fraction of loose material on surface (m^2/m^2)");
////			outprt.println("  0");
//            outprt.println(" " + ht.get(PlotLMFrac));
//            outprt.println("  los_cv");
//            outprt.println("#     asmlos(s), R, (s1surf.inc) Mass of loose material on crust (kg/m^2)");
////			outprt.println("  0");
//            outprt.println(" " + ht.get(PlotLMMass));
//            outprt.println("  los(kg/m^2)");
//            outprt.println("#     asdcr(s), R, (s1surf.inc) Soil crust density (Mg/m^3)");
////			outprt.println("  0");
//            outprt.println(" " + ht.get(PlotCrustDen));
//            outprt.println("  cr_den(Mg/m^3)");
//            outprt.println("#     asecr(s), R, (s1surf.inc) Soil crust stability ln(J/kg)");
////			outprt.println("  0");
//            outprt.println(" " + ht.get(PlotCrustStab));
//            outprt.println("  cr_se");
//            outprt.println("#     aslrr(s), R, (s1sgeo.inc) Allmaras random roughness (mm)");
////			outprt.println("  0");
//            outprt.println(" " + ht.get(PlotRandRough));
//            outprt.println("  rr(mm)");
//            outprt.println("#     aszrgh(s), R, (s1sgeo.inc) Ridge height (mm)");
////			outprt.println("  0");
//            outprt.println(" " + ht.get(PlotRidgeHgt));
//            outprt.println("  z_rgh(mm)");
//            outprt.println("#     asxrgs(s), R, (s1sgeo.inc) Ridge spacing (mm)");
////			outprt.println("  0");
//            outprt.println(" " + ht.get(PlotRidgeSpc));
//            outprt.println("  x_rgs(mm)");
//            outprt.println("#     asxrgw(s), R, (s1sgeo.inc) Ridge width (mm)");
////			outprt.println("  0");
//            outprt.println(" " + ht.get(PlotRidgeWid));
//            outprt.println("  x_rgw(mm)");
//            outprt.println("#     asxrgo(s), R, (s1sgeo.inc) Ridge orientation (deg)");
////			outprt.println("  0");
//            outprt.println(" " + ht.get(PlotRidgeOrient));
//            outprt.println("  a_rgo(deg)");
//            outprt.println("#");
//            outprt.println("");
            outprt.close();
        } catch (java.io.IOException e) {
            //System.err.println("E_wF: " + e);
            e.printStackTrace();
        }
        changes.firePropertyChange(DataChanged, "", "0");

    }
    /****** Data store methods ******/
    Hashtable ht = new Hashtable(200);

    private String getData(String idxstr, boolean flag) {
        String s = (String) ht.get(idxstr);
        if (flag) {
            if (s == null) {
                s = "";
            }
            if (s.trim().length() == 0) {
                s = "0.0";
            }
        }
        return s;
    }

    private void setData(String idxstr, String newData) {
        setData(idxstr, newData, true);
    }

    private void setData(String idxstr, String newData, boolean trimNewData) {

        String oldData = "";

        if (newData == null) {
            ht.remove(idxstr);
        } else {
            if (trimNewData) {
                newData = newData.trim();      //1148, only trim when told to.
            }
            oldData = (String) ht.get(idxstr);
            if (newData.equals(oldData)) {
                return;
            }
            ht.put(idxstr, newData);
        }
        changes.firePropertyChange(idxstr, oldData, newData);
        changes.firePropertyChange(DataChanged, "", "1");
    }

    private void setData(String idxstr, Object newData) {

        Object oldData = null;

        if (newData == null) {
            ht.remove(idxstr);
        } else {
            oldData = ht.get(idxstr);
//            if (newData instanceof BarrierPolygon || newData instanceof FieldPolygon) {
//                ht.put(idxstr, newData);
//            } else {
            if (newData.equals(oldData)) {
                return;
            }
            ht.put(idxstr, newData);
//            }

        }
        changes.firePropertyChange(idxstr, oldData, newData);
        changes.firePropertyChange(DataChanged, "", "1");
    }

    /**
     *  method to blank current record -- currently not implemented
     */
    public void reset() {
        clearBarriers();
        init();
    }
    /****** Property change support methods *****/
    /**
     * RunFileData throws a property change each time setData is called.
     * Wrapper classes listen to determine if the the event is relevant to
     * them.
     */
    private PropertyChangeSupport changes = new PropertyChangeSupport(this);

    /**
     * Allows the container to add or register some other components to recognize the changes that occur
     * on this component.
     * @param l The listener that listens and reacts towards the the changes to be reflected.
     */
    public void addPropertyChangeListener(PropertyChangeListener l) {
        changes.addPropertyChangeListener(l);
    }

    /**
     * Allows the container to remove or de-register some other components and stop recognizing the
     * changes that occur on this component.
     * @param l The listener that does not listen and react towards the the changes to be reflected.
     */
    public void removePropertyChangeListener(PropertyChangeListener l) {
        changes.removePropertyChangeListener(l);
    }

    /**
     * Recognizes and takes appropriate actions on registered properties from different
     * screens to update and synchronize data and GUI screens as needed.
     * @param e The event itself that is responsible for triggering the change required for registered
     * properties/components.
     */
    public void propertyChange(PropertyChangeEvent e) {

        String property = e.getPropertyName();
        if (property.equals(this.SetFocus)) {
            changes.firePropertyChange(e);
            return;
        }
        try {
            String value = (String) e.getNewValue();
////System.out.println("DS_pC: " + property + " >> " + value);		
            setData(property, value, true);
        } catch (ClassCastException f) {
            //System.out.println("DS_pC: " + property + " " + e.getNewValue());
            if (e.getSource() == this) {
                return;
            }
            setData(property, e.getNewValue());
        }
    }
}
