/*
 * Copyright (C) 2009 JavaRosa
 * 
 * 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.javarosa.core.model.data;

import org.javarosa.core.model.data.helper.Selection;
import org.javarosa.core.model.utils.DateUtils;
import org.javarosa.core.util.externalizable.DeserializationException;
import org.javarosa.core.util.externalizable.ExtUtil;
import org.javarosa.core.util.externalizable.PrototypeFactory;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Vector;


/**
 * A response to a question requesting an GeoPoint Value.
 *
 * @author Yaw Anokwa
 */
public class GeoPointData implements IAnswerData {

    private double[] gp = new double[4];
    private int len = 2;


    /**
     * Empty Constructor, necessary for dynamic construction during
     * deserialization. Shouldn't be used otherwise.
     */
    public GeoPointData() {

    }


    public GeoPointData(double[] gp) {
        this.fillArray(gp);
    }


    private void fillArray(double[] gp) {
        len = gp.length;
        for (int i = 0; i < len; i++) {
            this.gp[i] = gp[i];
        }
    }


    public IAnswerData clone() {
        return new GeoPointData(gp);
    }


    /*
     * (non-Javadoc)
     * 
     * @see org.javarosa.core.model.data.IAnswerData#getDisplayText()
     */
    public String getDisplayText() {
        String s = "";
        for (int i = 0; i < len; i++) {
            s += gp[i] + " ";
        }
        return s.trim();

    }


    /*
     * (non-Javadoc)
     * 
     * @see org.javarosa.core.model.data.IAnswerData#getValue()
     */
    public double[] getValue() {
        return gp;
    }


    public void setValue(Object o) {
        if (o == null) {
            throw new NullPointerException("Attempt to set an IAnswerData class to null.");
        }
        this.fillArray((double[])o);
    }


    public void readExternal(DataInputStream in, PrototypeFactory pf) throws IOException,
            DeserializationException {
        len = (int)ExtUtil.readNumeric(in);
        for (int i = 0; i < len; i++) {
            gp[i] = ExtUtil.readDecimal(in);
        }
    }


    public void writeExternal(DataOutputStream out) throws IOException {
        ExtUtil.writeNumeric(out, len);
        for (int i = 0; i < len; i++) {
            ExtUtil.writeDecimal(out, gp[i]);
        }
    }


    public UncastData uncast() {
        return new UncastData(getDisplayText());
    }

    public GeoPointData cast(UncastData data) throws IllegalArgumentException {
        double[] ret = new double[4];

        Vector<String> choices = DateUtils.split(data.value, " ", true);
        int i = 0;
        for (String s : choices) {
            double d = Double.parseDouble(s);
            ret[i] = d;
            ++i;
        }
        return new GeoPointData(ret);
    }
}

@@ -1037,16 +1037,45 @@
 Vector;%0A
+import java.math.BigDecimal;%0A
 %0A%0A/**%0A *
@@ -1278,16 +1278,130 @@
 n = 2;%0A%0A
+    // data points stored will contain this many decimal points:%0A    private final int MAX_DECIMAL_ACCURACY = 1;%0A%0A
 %0A    /**
@@ -1638,24 +1638,169 @@
 p);%0A    %7D%0A%0A%0A
+    /**%0A     * Copy data in argument array into local geopoint array.%0A     * @param gp double array of max size 4 representing geopoints%0A     */%0A
     private 
@@ -1919,21 +1919,60 @@
 gp%5Bi%5D = 
-gp%5Bi%5D
+truncateDecimal(gp%5Bi%5D, MAX_DECIMAL_ACCURACY)
 ;%0A      
@@ -3694,11 +3694,774 @@
 );%0A    %7D
+%0A%0A    /**%0A     * Truncate double to have the given number of decimals.%0A     * @param x double to be truncated%0A     * @param numberofDecimals number of decimals that should present in result%0A     */%0A    private static double truncateDecimal(double x, int numberofDecimals) %7B%0A        // via:%0A        // https://stackoverflow.com/questions/7747469/how-can-i-truncate-a-double-to-only-two-decimal-places-in-java/21468258#21468258%0A        BigDecimal decimal;%0A        if (x %3E 0) %7B%0A            decimal = new BigDecimal(String.valueOf(x)).setScale(numberofDecimals, BigDecimal.ROUND_FLOOR);%0A        %7D else %7B%0A            decimal = new BigDecimal(String.valueOf(x)).setScale(numberofDecimals, BigDecimal.ROUND_CEILING);%0A        %7D%0A        return decimal.doubleValue();%0A    %7D
 %0A%7D%0A

Truncate GeoPoint doubles to 1 decimal place.