package es.tid.smartsteps.dispersion.data;

import java.math.BigDecimal;
import java.math.MathContext;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import net.sf.json.JSONObject;

/**
 * TrafficCountsEntry
 *
 * holds all counts per sociodemographic variable in a traffic log line, plus a
 * cell ID and location information.
 *
 * @author  logc
 */
public class TrafficCountsEntry implements FieldsEntry {

    public static final String[] EXPECTED_POIS = {"HOME", "NONE", "WORK",
                                                  "OTHER", "BILL"};  
    private static final int HOURLY_SLOTS = 25;

    public String cellId;
    public String date;
    public double latitude;
    public double longitude;
    public HashMap<String, ArrayList<BigDecimal>> counts;
    public ArrayList<Integer> poiFive = new ArrayList<Integer>(HOURLY_SLOTS);
    public HashMap<String, ArrayList<Integer>> pois;
    public String microgridId;
    public String polygonId;

    public TrafficCountsEntry(String[] countFields) {
        this.pois = new HashMap<String, ArrayList<Integer>>();
        this.pois.put("HOME", new ArrayList<Integer>(HOURLY_SLOTS));
        this.pois.put("WORK", new ArrayList<Integer>(HOURLY_SLOTS));
        this.pois.put("NONE", new ArrayList<Integer>(HOURLY_SLOTS));
        this.pois.put("OTHER", new ArrayList<Integer>(HOURLY_SLOTS));
        this.pois.put("BILL", new ArrayList<Integer>(HOURLY_SLOTS));
        this.counts = new HashMap<String, ArrayList<BigDecimal>>();
        for (String countField : countFields) {
            this.counts.put(countField, new ArrayList<BigDecimal>());
        }
    }
    
    @Override
    public String getKey() {
        if (this.polygonId != null && !this.polygonId.isEmpty()) {
            return this.polygonId;
        } else if (this.microgridId != null && !this.microgridId.isEmpty()) {
            return this.microgridId;
        } else {
            return this.cellId;
        }
    }

    @Override
    public List<Object> getFields() {
        ArrayList<Object> ans = new ArrayList<Object>();
        ans.add(this.date);
        ans.add(this.latitude);
        ans.add(this.longitude);
        ans.add(this.counts);
        ans.add(this.poiFive);
        ans.add(this.pois);
        ans.add(this.microgridId);
        ans.add(this.polygonId);
        return ans;
    }

    public void scale(BigDecimal factor) {
        this.counts = this.scaleCounts(factor);
    }
    
    private HashMap<String, ArrayList<BigDecimal>> scaleCounts(
            BigDecimal factor) {
        HashMap<String, ArrayList<BigDecimal>> scaledCounts =
                new HashMap<String, ArrayList<BigDecimal>>();
        for (String countField : this.counts.keySet()) {
            final ArrayList<BigDecimal> countsForField =
                    this.counts.get(countField);
            ArrayList<BigDecimal> scaledCountsForField =
                    new ArrayList<BigDecimal>();
            for (int i = 0; i < countsForField.size(); i++) {
                scaledCountsForField.add(countsForField.get(i)
                        .multiply(factor));
            }
            scaledCounts.put(countField, scaledCountsForField);
        }
        return scaledCounts;
    }
    
    public HashMap<String, ArrayList<BigDecimal>> roundCounts() {
        HashMap<String, ArrayList<BigDecimal>> roundedCounts =
                new HashMap<String, ArrayList<BigDecimal>>();
        for (String countField : this.counts.keySet()) {
            final ArrayList<BigDecimal> countsForField =
                    this.counts.get(countField);
            ArrayList<BigDecimal> roundedCountsForField =
                    new ArrayList<BigDecimal>();
            for (int i = 0; i < roundedCounts.size(); i++) {
                roundedCountsForField.add(i, countsForField.get(i).round(
                        MathContext.UNLIMITED));
            }
            roundedCounts.put(countField, roundedCountsForField);
        }
        return roundedCounts;
    }

    public JSONObject toJSON(){
        final JSONObject obj = new JSONObject();
        obj.put("cellId", this.cellId);
        obj.put("date", this.date);
        obj.put("lat", this.latitude);
        obj.put("long", this.longitude);
        for (String field : this.counts.keySet()) {
            obj.put(field, this.counts.get(field));
        }
        obj.put("poi_5", this.poiFive);
        obj.put("pois", this.pois);
        obj.put("microgrid_id", this.microgridId);
        obj.put("polygon_id", this.polygonId);
        return obj;
    }
}

@@ -907,23 +907,26 @@
 rayList%3C
-Integer
+BigDecimal
 %3E%3E pois;
@@ -1091,23 +1091,26 @@
 rayList%3C
-Integer
+BigDecimal
 %3E%3E();%0A  
@@ -1143,39 +1143,42 @@
 , new ArrayList%3C
-Integer
+BigDecimal
 %3E(HOURLY_SLOTS))
@@ -1215,39 +1215,42 @@
 , new ArrayList%3C
-Integer
+BigDecimal
 %3E(HOURLY_SLOTS))
@@ -1287,39 +1287,42 @@
 , new ArrayList%3C
-Integer
+BigDecimal
 %3E(HOURLY_SLOTS))
@@ -1360,39 +1360,42 @@
 , new ArrayList%3C
-Integer
+BigDecimal
 %3E(HOURLY_SLOTS))
@@ -1432,39 +1432,42 @@
 , new ArrayList%3C
-Integer
+BigDecimal
 %3E(HOURLY_SLOTS))
@@ -2889,99 +2889,275 @@
     
-ArrayList%3CBigDecimal%3E scaledCountsForField =%0A                    new ArrayList%3CBigDecimal%3E(
+for (int i = 0; i %3C countsForField.size(); i++) %7B%0A                countsForField.set(i, countsForField.get(i).multiply(factor));%0A            %7D%0A        %7D%0A        for (String poi : this.pois.keySet()) %7B%0A            ArrayList%3CBigDecimal%3E countsForPoi = this.pois.get(poi
 );%0A 
@@ -3188,37 +3188,35 @@
 0; i %3C countsFor
-Field
+Poi
 .size(); i++) %7B%0A
@@ -3231,31 +3231,25 @@
         
-scaledC
+c
 ountsFor
 Field.ad
@@ -3240,26 +3240,27 @@
 ountsFor
-Field.add(
+Poi.set(i, 
 countsFo
@@ -3264,45 +3264,18 @@
 sFor
-Field
+Poi
 .get(i)
-%0A                        
 .mul
@@ -3308,72 +3308,8 @@
   %7D%0A
-            scaledCounts.put(countField, scaledCountsForField);%0A
     

Scale pois