/**
 * class SumAndAverage
 *
 * @version    1.3.3
 * @author  Dr Victor
 *
 * @see          NumberFormat.js
 * @requires     NumberFormat.js
 * @requires     validations.js
 */

function SumAndAverage(nameMask, sumFieldId, avgFieldId, countFieldId, decimalPlaces) {
    
    // attributes
    this.nameMask = nameMask;
    this.sumField = (sumFieldId != "") 
                    ? document.getElementById(sumFieldId) 
                    : null;
    this.avgField = (avgFieldId != "") 
                    ? document.getElementById(avgFieldId) 
                    : null;
    this.countField = (countFieldId != "") 
                    ? document.getElementById(countFieldId) 
                    : null;
    this.decimalPlaces = (!isNaN(parseInt(decimalPlaces)))
                    ? parseInt(decimalPlaces)
                    : 2;
    this.sum = 0;
    this.avg = 0;
    this.count = 0;

    // create NumberFormat instance and set number of decimals
    this.numberFormat = new NumberFormat(0);
    this.numberFormat.setPlaces(this.decimalPlaces);

    // methods
    this.calculateSum = calculateSum;
    this.calculateAvg = calculateAvg;
    this.calculateCount = calculateCount;
    this.printValue = printValue;
    this.doAll = doAll;

    // store input fields controlled by this instance
    // - this avoids repeated iterations over all form elements
    this.includedFields = new Array();
    ind = 0;
    elements = document.forms[0].elements;
    for (i = 0; i < elements.length; i++) {
        if (elements[i].name.search(this.nameMask) >= 0) {
            this.includedFields[ind++] = elements[i];
        }
    }
}

function calculateSum() {
    this.sum = 0;
    elements = this.includedFields;
    
    for (i = 0; i < elements.length; i++) {
        
        // check if field contains valid number
        if (isNaN(parseNumber(elements[i].value))) {

            // if the first  parsing failed, check if the field contains a formatted number
            sep = this.numberFormat.separatorValue;
            val = parseNumber(elements[i].value.replace((sep == "," ? /\,/gi :/\./gi),""));
            if (!isNaN(val)) {
                this.sum += val;
            }

            // if there's no number in the field (nor formatted one), go2 next
            continue;
        }
        this.sum += parseNumber(elements[i].value);
    }
    return this.sum;
}

function calculateAvg(recalc) {
    this.avg = 0;

    if (recalc) {
        this.calculateSum();
        this.calculateCount();
    }
    
    this.avg = this.sum / this.count;
    return this.avg;
}

function calculateCount() {
    this.count = this.includedFields.length;  
    return this.count;
}

function printValue(field, value) {
    this.numberFormat.setNumber(value);
    
    // average values are always with 2 decimals 
    if (this.avgField == field) {
        this.numberFormat.setPlaces(2);
    }
    
    if (field.tagName == "INPUT" || field.tagName == "input") {
        field.value = this.numberFormat.toFormatted(); 
    } else {
        field.innerText = this.numberFormat.toFormatted();
    }

    // set number of decimals back to the initial value
    this.numberFormat.setPlaces(this.decimalPlaces);
}

function doAll() {
    this.calculateSum();
    this.calculateCount();
    this.calculateAvg(false);
    
    if (this.sumField && this.sumField != null) {
        this.printValue(this.sumField, this.sum);
    }
    if (this.avgField && this.avgField != null) {
        this.printValue(this.avgField, this.avg);
    }
    if (this.countField && this.countField != null) {
        this.printValue(this.countField, this.count);
    }
}
