var residential_max = 2600;
var park_rate = 0.126;
var fire_rate = 0.076;

function round(input) {
    return Math.round(input * 100) / 100;
    // return input.toHR();
}

function dict_length(d) {
    var rv = 0;
    for(var i in d) {
        rv += 1;
    }
    return rv;
}

function getElement(id) {
    id = id.replace(/ /g, "_");
    return document.getElementById(id);
}

function smartParseFloat(n)
{
    return parseFloat(n.replace(/,/g, ""));
}

String.prototype.format = function ()
{
    var str = this;

    for(var i = 0; i < arguments.length; i++) {
        var re = new RegExp("\\{" + (i) + "\\}","gm");
        str = str.replace(re,arguments[i]);
    }

    return str;
}

Number.prototype.toHR = function() {
    var str = this.toString();
    var parts = str.split('.');
    var tail = parts[0];
    var head = '';

    if(parts[1] && parts[1].toString().length == 1) {
        parts[1] = parts[1].toString() + '0';
    }

    var decpart = parts[1] ? "." + parts[1] : '';

    if(parts[0].length > 3) {
        tail = "," + parts[0].substr(parts[0].length - 3);
        head = parseFloat(parts[0].substr(0, parts[0].length - 3)).toHR().replace(/[.]\d+/, "");
    }

    var rv = head + tail + decpart;

    if(!/[.]\d+$/.exec(rv)) {
        rv = rv + '.00';
    }

    rv = rv.replace(/([.]\d\d)\d+$/, '$1');

    return rv;
}

String.prototype.toFixed = function (places)
{
    var fl = smartParseFloat(this);
    return fl.toFixed(places);
}

function popup(url, width, height) {
    if(!width)
        width=600;
    if(!height)
        height=400;

    window.open(url,"window1","width=" + width + ",height=" + height + ",scrollbars=yes,resizable=yes,menubar=yes,toolbar=yes");
}

function has_value(id) 
{
    var e = getElement(id);

    if(e.type == "select-one") {
        return e.options[e.selectedIndex].value;
    }

    return e.value;
}

function make_report(btn) 
{
    /*
    var required = [ 'Property Owner', 'Job Address', 'Impact Fee District'];
    for(var i in required) {

        var val = has_value(required[i]);

        if(!val) {
            alert(required[i] + " is required.  Please fill it out and re-submit");
            return;
        }

    }

    if(!has_value('Property Owner').match(/[^\d]/)) {
        alert("number not allowed for Property Owner");
        return;
    }

    if(!has_value("Job Address").match(/[^\d]/)) {
        alert("number not allowed for Job Address");
        return;
    }

    if(!has_value("Impact Fee District").match(/^(1|2|3)$/)) {
        alert("Impact Fee District must contain a number (1, 2, or 3)");
        return;
    }

    if(has_value("Permit Type").match(/^\d+$/)) {
        alert("Permit Type cannot be a number");
        return;
    }

    if(has_value("Contractor").match(/^\d+$/)) {
        alert("Contractor cannot be a number");
        return;
    }

    if(!has_value("Permit Reference Number").match(/^\d*$/)) {
        alert("Permit Reference Number must be a number");
        return;
    }

    if(!has_value("Property ID Number").match(/^\d*$/)) {
        alert("Property ID Number must be a number");
        return;
    }

    var nru = getElement("Number of Units");
    var val = parseFloat(nru.value);

    if(isNaN(val) || val <= 0) {
        alert("Number of Units must be a number greater than 0");
        return;
    }
    */

    btn.form.submit();
} 

function toggle_visibility(elm_id,checkbox) {
    var e = getElement(elm_id);
    if(checkbox) {
        e.style.display = checkbox.checked ? '' : 'none';;
    } else {
        e.style.display = e.style.display == 'none' ? '' : 'none';
    }
    return true;
}

function map(fn,input) {
    var rv = new Array();
    for(var i in input) {
        rv.push(input[i]);
    }

    return rv;
}

function get_land_use(id) {
    for(var i in land_uses) {
        if(land_uses[i].id == id)
            return land_uses[i];
    }
}

function land_use_options () {
    return map(function (use) {
        return new Option(use.Description, use.id);
    }, land_uses);
}

function populate_land_uses (e) {
    e.options.length = 0;
    for(var i in land_uses) {
        var option = new Option(land_uses[i].Description, land_uses[i].id);
        e.options[i] = option;
    }
}

function setup_selector (selector_id, units_id) {
    var select = getElement(selector_id);
    var units = getElement(units_id);
    
    populate_land_uses(select);
    units.innerHTML = land_uses[0].Units;

    select.onchange = function () {
        var id = select.value;
        var use = get_land_use(id);
        units.innerHTML = use.Units;
    }
}

var total_fire = 0;
var total_park = 0;
var total_trans = 0;

var counters = {};

var existing_uses = {};
var proposed_uses = {};
var edit_funcs = {};

function send_to_summary() {
    // alert(existing_uses);

    function dict2query (prefix,dict) {
        var params = new Array();
        for(var i in dict) {
            params.push("{0}{1}={2}".format(prefix,i,dict[i]));
        }

        return params.join("&");
    }

    if(!dict_length(proposed_uses)) {
        if(has_value("land_use_intensity"))
            alert("Please click the \"Calculate Fees\" button after choosing your land use from the dropdown box");
        else
            alert("Please select at least one Proposed Land Use and click the \"Calculate Fees\" button");
        return;
    }

    var params = dict2query("ExistingUse", existing_uses) + (existing_uses ? '&' : '') + dict2query("ProposedUse", proposed_uses);
    window.location = "summary.php?{0}".format(params);
}

function add_to_totals(_fire, _park, _trans) 
{
    total_trans = round(total_trans + _trans);
    total_fire = round(total_fire + _fire);
    total_park = round(total_park + _park);

    getElement('total_fire').innerHTML = '$' + (total_fire > 0 ? total_fire : 0).toHR();
    getElement('total_park').innerHTML = '$' + (total_park > 0 ? total_park : 0).toHR();
    getElement('total_trans').innerHTML = '$' + (total_trans > 0 ? total_trans : 0).toHR();
}

function append_land_use(table_id, button, multiplier, prefix) {

    if(!counters[table_id]) {
        counters[table_id] = 0;
    }

    if(!prefix)
        prefix = '';

    var land_use = get_land_use(getElement(prefix + "land_use_select").value);
    var intensity = smartParseFloat(getElement(prefix + "land_use_intensity").value);

    if(land_use.minIntensity != 0 && land_use.minIntensity > intensity) {
        alert("Nr. Units is too low, please enter a number >= " + land_use.minIntensity.toString());
        return;
    }

    if(land_use.maxIntensity != 0 && land_use.maxIntensity < intensity) {
        alert("Nr. Units is too high, please enter a number <= " + land_use.maxIntensity.toString());
        return;
    }

    if(edit_funcs[prefix + land_use.id.toString()]) {
        return edit_funcs[prefix + land_use.id.toString()]();
    }

    if(!intensity || intensity <= 0) {
        if(isNaN(intensity))
            alert("Please enter Nr of Units per Square Feet before you click the Calculate Fees button");
        else
            alert("Please enter a number > 0 in the intensity");

        return
    }

    if(land_use.isResidential > 0 && intensity > residential_max) {
        // alert("isResidential: " + land_use.isResidential);
        intensity = residential_max;
    }

    if(!multiplier) {
        multiplier = 1;
    }

    if(!intensity) {
        alert("Must specify an intensity");
        return;
    }

    var msg = "Land Use [" + land_use.Description + "] already added.";

    if(multiplier < 0) { 
        if(existing_uses[land_use.id]) {
            alert(msg);
            return;
        }

        existing_uses[land_use.id] = existing_uses[land_use.id] ? smartParseFloat(existing_uses[land_use.id]) + smartParseFloat(intensity) : intensity;
    } else {
        if(proposed_uses[land_use.id]) {
            alert(msg);
            return;
        }

        proposed_uses[land_use.id] = proposed_uses[land_use.id] ? smartParseFloat(proposed_uses[land_use.id]) + smartParseFloat(intensity) : intensity;
    }

    var table = getElement(table_id);
    //table.style.visibility = 'visible';
	table.style.display = 'block';

    //button.value = "Add and Calculate Another Land Use";


    // var tr = document.createElement("tr");
    var tr = table.insertRow(-1);

    tr.style.backgroundColor = counters[table_id] % 2 == 0 ? '#f4f4f4' : '#dddddd';
    counters[table_id] += 1;

    var desc = tr.insertCell(-1);
    desc.innerHTML = land_use.Description;

    fire_total = round(((intensity > residential_max && land_use.isResidential > 0) ? residential_max : intensity) * fire_rate * land_use.applyFire * multiplier);
    park_total = round((intensity > residential_max ? residential_max : intensity) * park_rate * land_use.applyPark * multiplier);
    trans_total = round(((intensity > residential_max && land_use.isResidential > 0) ? residential_max : intensity) * land_use.Rate * multiplier);

    if(land_use.Units != "Sq. Ft.") {
        fire_total = Math.round(fire_total);
        park_total = Math.round(park_total);
        trans_total = Math.round(trans_total);
    }

    total_fire = round(total_fire + fire_total);
    total_park = round(total_park + park_total);
    total_trans = round(total_trans + trans_total);

    var mk_delete_func = function(fire, park, trans) {
        return function() {

            total_fire -= fire;
            total_park -= park;
            total_trans -= trans;

            getElement('total_fire').innerHTML = '$' + (total_fire > 0 ? total_fire : 0).toHR();
            getElement('total_park').innerHTML = '$' + (total_park > 0 ? total_park : 0).toHR();
            getElement('total_trans').innerHTML = '$' + (total_trans > 0 ? total_trans : 0).toHR();
            getElement(multiplier < 0 ? "ex_land_use_intensity" : "land_use_intensity").value = "";

            //tr.style.display = 'none';
            tr.parentNode.removeChild(tr);

            if(multiplier < 0)
                delete existing_uses[land_use.id];
            else
                delete proposed_uses[land_use.id];

            delete edit_funcs[prefix + land_use.id.toString()];
        }
    }

    var delete_func = mk_delete_func(fire_total, park_total, trans_total);

    //var intens = tr.insertCell(-1);
    //intens.innerHTML = intensity.toHR();
    var intens = tr.insertCell(-1);
    //var intens_i = document.createElement("input");
    //intens.appendChild(intens_i);

    var units = tr.insertCell(-1);
    units.innerHTML = land_use.Units

    var fire = tr.insertCell(-1);
    fire.innerHTML =  '$' + Math.abs(fire_total).toHR();
    fire.style.color = multiplier < 0 ? 'blue' : 'red';

    var park = tr.insertCell(-1);
    park.innerHTML =  '$' + Math.abs(park_total).toHR();
    park.style.color = multiplier < 0 ? 'blue' : 'red';

    var trans = tr.insertCell(-1);
    trans.innerHTML = '$' + Math.abs(trans_total).toHR();
    trans.style.color = multiplier < 0 ? 'blue' : 'red';

    var actioncell = tr.insertCell(-1);
    var deleteact = document.createElement("a");
    deleteact.innerHTML = "<img src='images/delete.gif' border=0 />";
    deleteact.href = '#';
    deleteact.onclick = function() { delete_func(); return false };
    actioncell.appendChild(deleteact);

    getElement('total_fire').innerHTML = '$' + (total_fire > 0 ? total_fire : 0).toHR();
    getElement('total_park').innerHTML = '$' + (total_park > 0 ? total_park : 0).toHR();
    getElement('total_trans').innerHTML = '$' + (total_trans > 0 ? total_trans : 0).toHR();

    var mk_edit_func = function(_fire, _park, _trans, element) 
    {
        return function() {

            var new_intensity = smartParseFloat(element.value);
            if(isNaN(new_intensity) || new_intensity < 0) {
                alert("Please enter a number that is >= 0");
                return;
            }

            if(multiplier > 0)
                proposed_uses[land_use.id] = new_intensity;
            else
                existing_uses[land_use.id] = new_intensity;

            var fire_total = round(((new_intensity > residential_max && land_use.isResidential > 0) ? residential_max : new_intensity) * fire_rate * land_use.applyFire * multiplier);
            var park_total = round((new_intensity > residential_max ? residential_max : new_intensity) * park_rate * land_use.applyPark * multiplier);
            var trans_total = round(((new_intensity > residential_max && land_use.isResidential > 0) ? residential_max : new_intensity) * land_use.Rate * multiplier);

            var fdiff = fire_total - _fire;
            var pdiff = park_total - _park;
            var tdiff = trans_total - _trans;

            /* 
             * the above calls to round() only round to 2 decimal places, but non sq ft uses should
             * round to the nearest integer
             */
            if(land_use.Units != "Sq. Ft.") 
            {
                fire_total = Math.round(fire_total);
                park_total = Math.round(park_total);
                trans_total = Math.round(trans_total);
            }

            fire.innerHTML = '$' + (fire_total * multiplier).toHR();
            park.innerHTML = '$' + (park_total * multiplier).toHR();
            trans.innerHTML = '$' + (trans_total * multiplier).toHR();
            intens.innerHTML = new_intensity.toHR();

            add_to_totals(fdiff, pdiff, tdiff);
            //element.onchange = mk_edit_func(fire_total, park_total, trans_total, element);
            edit_funcs[prefix + land_use.id.toString()] = mk_edit_func(fire_total, park_total, trans_total, element);
            deleteact.onclick = mk_delete_func(fire_total, park_total, trans_total);

        }
    }

    //intens_i.type = "text";
    intens.innerHTML = intensity.toHR();
    edit_funcs[prefix + land_use.id.toString()] = mk_edit_func(fire_total, park_total, trans_total, getElement(prefix + "land_use_intensity"));
    //intens_i.onchange = mk_edit_func(fire_total, park_total, trans_total, intens_i);
}

function find_float(id) {
    var e = getElement(id);
    var rv = round(smartParseFloat(e.value));
    e.value = rv.toHR();
    return rv;
}

function set(id, val, disable) {
    var e = getElement(id);
    e.disabled = disable;
    e.value = val.toHR();
    return smartParseFloat(e.value);
}

function setz(id, val, disable) {
    return set(id, val < 0 ? 0.00 : round(val));
}

function recalc_summary() {
    /*
    var res_sf = find_float("Square Feet of Residential Heated Area");
    var nonres_sf = find_float("Gross Square Feet of Non-Residential Floor Area");

    setz("Heated Area SF", res_sf);
    setz("Residential - Heated Area SF", res_sf);

    setz("Park and Recreation Impact Fee", res_sf * park_rate, true);
    */
    var fire_fee = find_float("Fire Impact Fee");
    var fire_credits = find_float("Fire Credits Applied");
    var fire = setz("Net Fire Impact Fees", fire_fee - fire_credits, true);

    var park_fee = find_float("Park and Recreation Impact Fee");
    var park_credits = find_float("Park and Recreation Credits Applied");
    var park = setz("Net Park and Recreation Impact Fees", park_fee - park_credits, true);

    var trans_fee = find_float("Transportation Impact Fees");
    var trans_credits = find_float("Transportation Credits Applied");
    var trans = setz("Net Transportation Impact Fees", trans_fee - trans_credits, true);

    var total = setz("Total Fees", fire + park + trans, true);
}
