(function( $ ) {
    "use strict";

function destroy(arr, val) {
    for (var i = 0; i < arr.length; i++) if (arr[i] === val) arr.splice(i, 1);
    return arr;
}

function toggle_spec_fields(element) {
    // When a service checkbox is clicked, this is used to display
    // or remove the specification inputs.
    if (!$("#bika_setup").attr("EnableARSpecs")) {
        return;
    }
    var column = $(element).attr("column");
    var spec_uid = $("#ar_" + column + "_Specification_uid").val();
    var service_uid = $(element).attr("value");
    var min_name = "ar." + column + ".min." + service_uid;
    var max_name = "ar." + column + ".max." + service_uid;
    var error_name = "ar." + column + ".error." + service_uid;
    if ($(element).prop("checked") && $(element).siblings().filter("[name='" + min_name + "']").length === 0) {
        //var to know if analysis need specification
        var allowspec = true;
        //Search if current analysis's service allows specification
        var request_allowspec = {
            catalog_name: "uid_catalog",
            UID: service_uid
        };
        window.bika.lims.jsonapi_read(request_allowspec, function (result) {
            if (result.objects && result.objects.length > 0) {
                var allowspec = result.objects[0].ResultOptions == null || result.objects[0].ResultOptions.length == 0;
                // To force the next if statments part to be syncron
                if ((spec_uid !== "") && allowspec) {
                    var request_data = {
                        catalog_name: "uid_catalog",
                        UID: spec_uid
                    };
                    window.bika.lims.jsonapi_read(request_data, function (data) {
                        var min_val = "";
                        var max_val = "";
                        var error_val = "";
                        if (data.objects && data.objects.length > 0) {
                            var rr = data.objects[0].ResultsRange;
                            for (var i in rr) {
                                if (!(rr.hasOwnProperty(i))) {
                                    continue;
                                }
                                if (rr[i].keyword == $(element).attr("keyword")) {
                                    min_val = rr[i].min;
                                    max_val = rr[i].max;
                                    error_val = rr[i].error;
                                    break;
                                }
                            }
                        }
                        var min = $("<input class='spec_bit min' type='text' size='3' uid='" + service_uid + "' value='" + min_val + "' name='" + min_name + "' keyword='" + $(element).attr("keyword") + "' autocomplete='off' placeholder='&gt;'/>");
                        var max = $("<input class='spec_bit max' type='text' size='3' uid='" + service_uid + "' value='" + max_val + "' name='" + max_name + "' keyword='" + $(element).attr("keyword") + "' autocomplete='off' placeholder='&lt;'/>");
                        var error = $("<input class='spec_bit error' type='text' size='3' uid='" + service_uid + "' value='" + error_val + "' name='" + error_name + "' keyword='" + $(element).attr("keyword") + "' autocomplete='off' placeholder='%'/>");
                        $(element).after(error).after(max).after(min);
                    });
                }
                else if (allowspec) {
                    var min = $("<input class='spec_bit min' type='text' size='3' uid='" + service_uid + "' value='' name='" + min_name + "' keyword='" + $(element).attr("keyword") + "' autocomplete='off' placeholder='&gt;'/>");
                    var max = $("<input class='spec_bit max' type='text' size='3' uid='" + service_uid + "' value='' name='" + max_name + "' keyword='" + $(element).attr("keyword") + "' autocomplete='off' placeholder='&lt;'/>");
                    var error = $("<input class='spec_bit error' type='text' size='3' uid='" + service_uid + "' value='' name='" + error_name + "' keyword='" + $(element).attr("keyword") + "' autocomplete='off' placeholder='%'/>");
                    $(element).after(error).after(max).after(min);
                }
            }
        });
    }
    else {
        $("input[name='" + min_name + "']").remove();
        $("input[name='" + max_name + "']").remove();
        $("input[name='" + error_name + "']").remove();
    }
}

function reset_spec_field_values(column) {
    // When a spec is selected, all existing spec fields are cleared and reset
    if (!$("#bika_setup").attr("EnableARSpecs")) {
        return;
    }
    var spec_uid = $("#ar_" + column + "_Specification_uid").val();
    if (spec_uid !== "") {
        var request_data = {
            catalog_name: "uid_catalog",
            UID: spec_uid
        };
        window.bika.lims.jsonapi_read(request_data, function (data) {
            // empty all specification inputs.
            var min_name = "[name^='ar." + column + ".min']";
            var max_name = "[name^='ar." + column + ".max']";
            var error_name = "[name^='ar." + column + ".error']";
            $(min_name).val("");
            $(max_name).val("");
            $(error_name).val("");
            // set specification values in all supported services.
            if (data.objects && data.objects.length > 0) {
                var rr = data.objects[0].ResultsRange;
                for (var i in rr) {
                    var this_min = "[name='ar." + column + ".min\\." + rr[i].uid + "']";
                    var this_max = "[name='ar." + column + ".max\\." + rr[i].uid + "']";
                    var this_error = "[name='ar." + column + ".error\\." + rr[i].uid + "']";
                    if ($(this_min)) {
                        $(this_min).val(rr[i].min);
                        $(this_max).val(rr[i].max);
                        $(this_error).val(rr[i].error);
                    }
                }
            }
        });
    }
}

function validate_spec_field_entry(element) {
    var column = $(element).attr("name").split(".")[1];
    var uid = $(element).attr("uid");
    $("[name^='ar\\."+column+"\\.Specification']").val("");
    $("[name^='ar\\."+column+"\\.Specification_uid']").val("");
    var min_element = $("[name='ar."+column+".min."+uid+"']");
    var max_element = $("[name='ar."+column+".max."+uid+"']");
    var error_element = $("[name='ar."+column+".error."+uid+"']");
    var min = parseFloat($(min_element).val(), 10);
    var max = parseFloat($(max_element).val(), 10);
    var error = parseFloat($(error_element).val(), 10);
    if($(element).hasClass("min")){
        if(isNaN(min)) {
            $(min_element).val("");
        } else if ((!isNaN(max)) && min > max) {
            $(max_element).val("");
        }
    } else if($(element).hasClass("max")){
        if(isNaN(max)) {
            $(max_element).val("");
        } else if ((!isNaN(min)) && max < min) {
            $(min_element).val("");
        }
    } else if($(element).hasClass("error")){
        if(isNaN(error) || error < 0 || error > 100){
            $(error_element).val("");
        }
    }
}

function set_default_spec(column) {
    if(!$("#bika_setup").attr("EnableARSpecs")) { return; }
    // I use only the sampletype for looking up defaults.
    var sampletype_title = $("#ar_"+column+"_SampleType").val();
    var client_uid = $("#ar_"+column+"_Client_uid").val();
    if(sampletype_title !== ""){
        var bika_analysisspecs_uid = $("#bika_setup").attr("bika_analysisspecs_uid");
        var request_data = {
            catalog_name: "bika_setup_catalog",
            portal_type: "AnalysisSpec",
            getSampleTypeTitle: encodeURIComponent(sampletype_title),
            getClientUID: [client_uid, bika_analysisspecs_uid]
        };

        window.bika.lims.jsonapi_read(request_data, function(data) {
            var ob, obj;
            if (data.objects && data.objects.length > 0) {
                for(ob in data.objects){
                    if ((!data.objects.hasOwnProperty(ob))) { continue; }
                    obj = data.objects[ob];
                    if ((!obj.hasOwnProperty("getClientUID"))) { continue; }
                    if(client_uid == obj.getClientUID){
                        $("#ar_"+column+"_Specification").val(obj.title);
                        $("#ar_"+column+"_Specification_uid").val(obj.UID);
                        reset_spec_field_values(column);
                        return;
                    }
                }
                for(ob in data.objects){
                    if ((!data.objects.hasOwnProperty(ob))) { continue; }
                    obj = data.objects[ob];
                    if ((!obj.hasOwnProperty("getClientUID"))) { continue; }
                    if (obj.getClientUID != client_uid) {
                        $("#ar_"+column+"_Specification").val(obj.title);
                        $("#ar_"+column+"_Specification_uid").val(obj.UID);
                        reset_spec_field_values(column);
                        return;
                    }
                }
            }
        });

    }
}

function set_cc_contacts(column) {
    var contact_uid = $("#ar_"+column+"_Contact_uid").val();
    var fieldName = "ar."+column+".CCContact";
    // clear the CC widget
    $("input[name='"+fieldName+":record']").val("");
    $("input[name='"+fieldName+":record']").attr("uid", "");
    $("input[name='"+fieldName+"_uid']").val("");
    $("#ar_"+column+"_CCContact-listing").empty();
    if(contact_uid !== ""){
        var request_data = {
            portal_type: "Contact",
            UID: contact_uid
        };
        window.bika.lims.jsonapi_read(request_data, function(data) {
            if(data.objects && data.objects.length < 1) {
                return;
            }
            var ob = data.objects[0];
            var cc_titles = ob.CCContact;
            var cc_uids = ob.CCContact_uid;
            if(!cc_uids) {
                return;
            }
            $("input[name='"+fieldName+"_uid']").val(cc_uids.join(","));
            for (var i = 0; i < cc_uids.length; i++) {
                var title = cc_titles[i];
                var uid = cc_uids[i];
                var del_btn_src = window.portal_url+"/++resource++bika.lims.images/delete.png";
                var del_btn = "<img class='ar_deletebtn' src='"+del_btn_src+"' fieldName='"+fieldName+"' uid='"+uid+"'/>";
                var new_item = "<div class='reference_multi_item' uid='"+uid+"'>"+del_btn+title+"</div>";
                $("#ar_"+column+"_CCContact-listing").append($(new_item));
            }
        });
    }
}
function modify_Specification_field_filter(column) {
    // when a SampleType is selected I will allow only specs to be selected
    // which 1- (have the same Sample Types)
    // 2- (have no sample type at all)
    var sampletype_title = $("#ar_"+column+"_SampleType").val();
    var e = $("#ar_"+column+"_Specification");
    var query_str = $(e).attr("search_query");
    var query_obj = $.parseJSON(query_str);
    if (    query_obj.hasOwnProperty("getSampleTypeTitle") ){
        delete query_obj.getSampleTypeTitle;
    }
    query_obj.getSampleTypeTitle = [encodeURIComponent(sampletype_title), ""];
    query_str = $.toJSON(query_obj);
    $(e).attr("search_query", query_str);
}


function ar_set_tabindexes() {
    // Sets the tab index to the elements. Tab flow top to bottom instead of left
    // to right.
    // Keyboard tab flow top to bottom instead of left to right
    var index = 10;
    var count = $("input[id='col_count']").val();
    for (var i=0; i<count; i++) {
        var elements = $("td[column="+i+"]").find("input[type!=hidden]").not("[disabled]");
        for (var j=0; j<elements.length; j++) {
            $(elements[j]).attr("tabindex",index);
            index++;
        }
    }
}

// Configure the widgets that archetypes built:
// set id and name to ar-col-fieldName formats
// un-set the readonly attribute on the fields (so that we can search).
function ar_rename_elements(){
    var i, e, elements, column;
    elements = $("td[ar_add_column_widget]").find("input[type!='hidden']").not("[disabled]");
    for (i = elements.length - 1; i >= 0; i--) {
        e = elements[i];
        column = $($(e).parents("td")).attr("column");
        // not :ignore_empty, widgets each get submitted to their own form handlers
        $(e).attr("name", "ar."+column+"."+$(e).attr("name")+":record");
        $(e).attr("id", "ar_"+column+"_"+e.id);
        $(e).removeAttr("required");
    }
    elements = $("td[ar_add_column_widget]").find("input[type='hidden']");
    for (i = elements.length - 1; i >= 0; i--) {
        e = elements[i];
        column = $($(e).parents("td")).attr("column");
        $(e).attr("id", "ar_"+column+"_"+e.id);
        // not :ignore_empty, widgets each get submitted to their own form handlers
        $(e).attr("name", "ar."+column+"."+$(e).attr("name")+":record");
    }
    elements = $(".multiValued-listing");
    for (i = elements.length - 1; i >= 0; i--) {
        e = elements[i];
        var eid = e.id.split("-listing")[0];
        column = $($(e).parents("td")).attr("column");
        $(e).attr("id", "ar_"+column+"_"+eid+"-listing");
        // not :ignore_empty, widgets each get submitted to their own form handlers
        $(e).attr("name", "ar."+column+"."+eid+"-listing");
        $(e).attr("fieldName", "ar."+column+"."+eid);
    }
}

// The columnar referencewidgets that we reconfigure use this as their
// select handler.
function ar_referencewidget_select_handler(event, ui){
    /*jshint validthis:true */
    event.preventDefault();

    // Set form values in activated element (must exist in colModel!)
    var column = $(this).attr("id").split("_")[1];
    var fieldName = $(this).attr("name").split(".")[2].split(":")[0];
    var skip;

    var uid_element = $("#ar_"+column+"_"+fieldName+"_uid");
  var listing_div = $("#ar_"+column+"_"+fieldName+"-listing");
  if(listing_div.length > 0) {
      // Add selection to textfield value
      var existing_uids = $(uid_element).val().split(",");
            destroy(existing_uids,"");
            destroy(existing_uids,"[]");
      var selected_value = ui.item[$(this).attr("ui_item")];
      var selected_uid = ui.item.UID;
      if (existing_uids.indexOf(selected_uid) == -1) {
          existing_uids.push(selected_uid);
          $(this).val("");
          $(this).attr("uid", existing_uids.join(","));
          $(uid_element).val(existing_uids.join(","));
                    // insert item to listing
                    var del_btn_src = portal_url+"/++resource++bika.lims.images/delete.png";
                    var del_btn = "<img class='deletebtn' src='"+del_btn_src+"' fieldName='ar."+column+"."+fieldName+"' uid='"+selected_uid+"'/>";
                    var new_item = "<div class='reference_multi_item' uid='"+selected_uid+"'>"+del_btn+selected_value+"</div>";
                    $(listing_div).append($(new_item));
      }
      skip = $(element).attr("skip_referencewidget_lookup");
      if (skip !== true){
          $(this).trigger("selected", ui.item.UID);
      }
      $(element).removeAttr("skip_referencewidget_lookup");
      $(this).next("input").focus();
  } else {
      // Set value in activated element (must exist in colModel!)
      $(this).val(ui.item[$(this).attr("ui_item")]);
      $(this).attr("uid", ui.item.UID);
      $(uid_element).val(ui.item.UID);
      skip = $(element).attr("skip_referencewidget_lookup");
      if (skip !== true){
          $(this).trigger("selected", ui.item.UID);
      }
      $(element).removeAttr("skip_referencewidget_lookup");
      $(this).next("input").focus();
  }

  if(fieldName == "Contact"){
    set_cc_contacts(column);
  }
    if(fieldName == "SampleType"){
        // selecting a Sampletype - jiggle the SamplePoint element.
        var sp_element = $("#ar_"+column+"_SamplePoint");
        sp_element
            .removeClass( "cg-autocomplete-input" )
            .removeAttr( "autocomplete" )
            .removeAttr( "role" )
            .removeAttr( "aria-autocomplete" )
            .removeAttr( "aria-haspopup" );
        var new_sp_element = $(sp_element[0]).clone();
        var sp_parent_node = $(sp_element).parent();
        $(sp_element).remove();
        $(sp_parent_node).append(new_sp_element);
        sp_element = $("#ar_"+column+"_SamplePoint");
        // cut kwargs into the base_query
        var sp_base_query = $(sp_element).attr("base_query");
        sp_base_query = $.parseJSON(sp_base_query);
        sp_base_query = $.toJSON(sp_base_query);
        var sp_search_query = {"getSampleTypeTitle": encodeURIComponent(ui.item[$(this).attr("ui_item")])};
        sp_search_query = $.toJSON(sp_search_query);
        sp_element.attr("search_query", sp_search_query);
        ar_referencewidget_lookups(sp_element);
    }
    if(fieldName == "SamplePoint"){
        // selecting a Samplepoint - jiggle the SampleType element.
        var st_element = $("#ar_"+column+"_SampleType");
        st_element
            .removeClass( "cg-autocomplete-input" )
            .removeAttr( "autocomplete" )
            .removeAttr( "role" )
            .removeAttr( "aria-autocomplete" )
            .removeAttr( "aria-haspopup" );
        var new_st_element = $(st_element[0]).clone();
        var st_parent_node = $(st_element).parent();
        $(st_element).remove();
        $(st_parent_node).append(new_st_element);
        st_element = $("#ar_"+column+"_SampleType");
        // cut kwargs into the base_query
        var st_base_query = $(st_element).attr("base_query");
        st_base_query = $.parseJSON(st_base_query);
        st_base_query = $.toJSON(st_base_query);
        var st_search_query = {"getSamplePointTitle": ui.item[$(this).attr("ui_item")]};
        st_search_query = $.toJSON(st_search_query);
        st_element.attr("search_query", st_search_query);
        ar_referencewidget_lookups(st_element);
    }

    // Selected a Profile
    if(fieldName == "Profile"){
        unsetTemplate(column);
        setAnalysisProfile(column, $(this).val());
        calculate_parts(column);
    }

    // Selected a Template
    if(fieldName == "Template"){
        setTemplate(column, $(this).val());
    }

    // Selected a sample to create a secondary AR.
    if(fieldName == "Sample"){
        // var e = $("input[name^='ar\\."+column+"\\."+fieldName+"']");
        // var Sample = $("input[name^='ar\\."+column+"\\."+fieldName+"']").val();
        // var Sample_uid = $("input[name^='ar\\."+column+"\\."+fieldName+"_uid']").val();
        // Install the handler which will undo the changes I am about to make
        $(this).blur(function(){
            if($(this).val() === ""){
                // clear and un-disable everything
                var disabled_elements = $("[ar_add_column_widget] [id*='ar_"+column+"']:disabled");
                $.each(disabled_elements, function(x,disabled_element){
                    $(disabled_element).prop("disabled", false);
                    if($(disabled_element).attr("type") == "checkbox"){
                        $(disabled_element).prop("checked", false);
                    } else {
                        $(disabled_element).val("");
                    }
                });
            }
        });
        // Then populate and disable sample fields
        $.getJSON(window.location.href.replace("/ar_add","") + "/secondary_ar_sample_info",
            {
                "Sample_uid": $(this).attr("uid"),
                "_authenticator": $("input[name='_authenticator']").val()},
            function(data){
                for (var x = data.length - 1; x >= 0; x--) {
                    var fieldname = data[x][0];
                    var fieldvalue = data[x][1];
                    var uid_element = $("#ar_"+column+"_"+fieldname+"_uid");
                    $(uid_element).val("");
                    var sample_element = $("#ar_"+column+"_"+fieldname);
                    $(sample_element).val("").prop("disabled", true);
                    if($(sample_element).attr("type") == "checkbox" && fieldvalue){
                        $(sample_element).prop("checked", true);
                    } else {
                        $(sample_element).val(fieldvalue);
                    }
                }
            }
        );
    }

    // Selected a SampleType
    if(fieldName == "SampleType"){
        unsetTemplate(column);
        set_default_spec(column);
        modify_Specification_field_filter(column);
        calculate_parts(column);
    }

    // Selected a Specification
    if(fieldName == "Specification"){
        reset_spec_field_values(column);
    }

    // Triggers 'selected' event (as reference widget)
    $(this).trigger("selected", ui.item.UID);
}

function add_path_filter_to_spec_lookups(){
    for (var col=0; col<parseInt($("#col_count").val(), 10); col++) {
        var element = $("#ar_"+col+"_Specification");
        var bq = $.parseJSON($(element).attr("base_query"));
        bq.path = [$("#bika_setup").attr("bika_analysisspecs_path"),
				   $("#PhysicalPath").attr("here")];
        $(element).attr("base_query", $.toJSON(bq));
    }
}

// we do the referencewidget_lookups differently to the widget default.
// We also include a bunch of ar_add specific on-change stuff, since the
// popup widget takes over the .change event completely.
function ar_referencewidget_lookups(elements){
    add_path_filter_to_spec_lookups();
    var inputs;
    if(elements === undefined){
        inputs = $("input.referencewidget").not(".has_combogrid_widget");
    } else {
        inputs = elements;
    }
    for (var i = inputs.length - 1; i >= 0; i--) {
        var element = inputs[i];
        var options = $.parseJSON($(element).attr("combogrid_options"));
        if(options === "" || options === undefined){
            continue;
        }
        options.select = ar_referencewidget_select_handler;

        if(window.location.href.search("ar_add") > -1){
            options.url = window.location.href.split("/ar_add")[0] + "/" + options.url;
        }
        options.url = options.url + "?_authenticator=" + $("input[name='_authenticator']").val();
        options.url = options.url + "&catalog_name=" + $(element).attr("catalog_name");
        options.url = options.url + "&base_query=" + $(element).attr("base_query");
        options.url = options.url + "&search_query=" + $(element).attr("search_query");
        options.url = options.url + "&colModel=" + $.toJSON( $.parseJSON($(element).attr("combogrid_options")).colModel);
        options.url = options.url + "&search_fields=" + $.toJSON($.parseJSON($(element).attr("combogrid_options")).search_fields);
        options.url = options.url + "&discard_empty=" + $.toJSON($.parseJSON($(element).attr("combogrid_options")).discard_empty);
        $(element).combogrid(options);
        $(element).addClass("has_combogrid_widget");
        $(element).attr("search_query", "{}");
    }
}

function recalc_prices(column){
    if(column){
        // recalculate just this column
        var subtotal = 0.00;
        var discount_amount = 0.00;
        var vat = 0.00;
        var total = 0.00;
        var discount = parseFloat($("#member_discount").val());
        $.each($("input[name='ar."+column+".Analyses:list:ignore_empty:record']"), function(){
            var disabled = $(this).prop("disabled");
            // For some browsers, `attr` is undefined; for others, its false.  Check for both.
            if (typeof disabled !== "undefined" && disabled !== false) {
                disabled = true;
            } else {
                disabled = false;
            }
            if(!(disabled) && $(this).prop("checked")){
                var serviceUID = this.id;
                var form_price = parseFloat($("#"+serviceUID+"_price").val());
                var vat_amount = parseFloat($("#"+serviceUID+"_price").attr("vat_amount"));
                var price;
                if(discount){
                    price = form_price - ((form_price / 100) * discount);
                } else {
                    price = form_price;
                }
                subtotal += price;
                discount_amount += ((form_price / 100) * discount);
                vat += ((price / 100) * vat_amount);
                total += price + ((price / 100) * vat_amount);
            }
        });
        $("#ar_"+column+"_subtotal").val(subtotal.toFixed(2));
        $("#ar_"+column+"_subtotal_display").val(subtotal.toFixed(2));
        $("#ar_"+column+"_discount").val(discount_amount.toFixed(2));
        $("#ar_"+column+"_vat").val(vat.toFixed(2));
        $("#ar_"+column+"_vat_display").val(vat.toFixed(2));
        $("#ar_"+column+"_total").val(total.toFixed(2));
        $("#ar_"+column+"_total_display").val(total.toFixed(2));
    } else {
        // recalculate the entire form
        for (var col=0; col<parseInt($("#col_count").val(), 10); col++) {
            recalc_prices(String(col));
        }
    }
}

function changeReportDryMatter(){
    /*jshint validthis:true */
    var dm = $("#getDryMatterService");
    var uid = $(dm).val();
    var cat = $(dm).attr("cat");
    var poc = $(dm).attr("poc");
    var column = $(this).parents("td").attr("column");
    if ($(this).prop("checked")){
        // only play with service checkboxes when enabling dry matter
        unsetAnalysisProfile(column);
        $.ajaxSetup({async:false});
        toggleCat(poc, cat, column, [uid], true);
        $.ajaxSetup({async:true});
        var dryservice_cb = $("input[column='"+column+"']:checkbox").filter("#"+uid);
        $(dryservice_cb).prop("checked",true);
        calcdependencies([$(dryservice_cb)], true);
        calculate_parts(column);
    }
    recalc_prices();
}

function copy_service(copybutton){
    var e = $("input[column='0']").filter("#" + copybutton.id);
    var kw = $(e).attr("keyword");
    var service_uid = $(e).prop("value");
    // get column 0 values
    var first_val = $(e).prop("checked");
    var first_min = $("[name='ar.0.min." + service_uid + "']").prop("value");
    var first_max = $("[name='ar.0.max." + service_uid + "']").prop("value");
    var first_error = $("[name='ar.0.error." + service_uid + "']").prop("value");

    var col_count = parseInt($("#col_count").val(), 10);
    var affected_elements = [];
    // 0 is the first column; we only want to change cols 1 onward.
    for (var column = 1; column < col_count; column++) {
        unsetTemplate(column);
        unsetAnalysisProfile(column);
        var other_elem = $("input[column='" + column + "']").filter("#" + copybutton.id);
        if ((!other_elem.prop("disabled")) && (other_elem.prop("checked") != first_val)) {
            other_elem.prop("checked", first_val ? true : false);
            toggle_spec_fields(other_elem);
            affected_elements.push(other_elem);
        }
        if (first_val) {
            $(".spec_bit.min[column='" + column + "']").filter("[keyword='" + kw + "']")
                .prop("value", first_min);
            $(".spec_bit.max[column='" + column + "']").filter("[keyword='" + kw + "']")
                .prop("value", first_max);
            $(".spec_bit.error[column='" + column + "']").filter("[keyword='" + kw + "']")
                .prop("value", first_error);
        }
        calculate_parts(column);
    }
    calcdependencies(affected_elements, true);
    recalc_prices();
}

function copy_checkbox(copybutton){
    var fieldName = $(copybutton).attr("name");
    var first_val = $("input[name^='ar\\.0\\."+fieldName+"']").prop("checked");
  var col_count = parseInt($("#col_count").val(), 10);
    // col starts at 1 here; we don't copy into the the first row
    for (var col=1; col<col_count; col++) {
        var other_elem = $("#ar_" + col + "_" + fieldName);
        if ((other_elem.prop("checked")!=first_val)) {
            other_elem.prop("checked",first_val?true:false);
            other_elem.trigger("change");
        }
    }
    $("[id*='_" + fieldName + "']").change();
}

function copyButton(){
    /*jshint validthis:true */
    var fieldName = $(this).attr("name");
  var col_count = parseInt($("#col_count").val(), 10);

    if ($(this).parent().attr("class") == "service"){
        copy_service(this);
    }

    else if ($("input[name^='ar\\.0\\."+fieldName+"']").attr("type") == "checkbox") {
        copy_checkbox(this);
    }

    // Anything else

    else{
        var first_val = $("input[name^='ar\\.0\\."+fieldName+"']").filter("[type=text]").val();
        // Reference fields have a hidden *_uid field
        var first_uid = $("input[name^='ar\\.0\\."+fieldName+"_uid']").val();
        // multi-valued fields: selection is in {fieldname}-listing
        var first_multi_html = $("div[name^='ar\\.0\\."+fieldName+"-listing']").html();
        // col starts at 1 here; we don't copy into the the first row
        for (var col=1; col<col_count; col++) {
            var other_uid_elem = $("#ar_" + col + "_" + fieldName + "_uid");
            if (first_uid !== undefined && first_uid !== null){
                other_uid_elem.val(first_uid);
            }
            var other_multi_div = $("div[name^='ar\\."+col+"\\."+fieldName+"-listing']");
            if (first_multi_html !== undefined && first_multi_html !== null){
                other_multi_div.html(first_multi_html.replace(".0.", "."+col+"."));
            }
            // Actual field value
            var other_elem = $("#ar_" + col + "_" + fieldName);
            if (!(other_elem.prop("disabled"))) {
                $(other_elem).attr("skip_referencewidget_lookup", true);
                other_elem.val(first_val);
                other_elem.trigger("change");

                if(fieldName == "Contact") {
                    set_cc_contacts(col);
                }

                if(fieldName == "Profile"){
                    unsetTemplate(col);
                    setAnalysisProfile(col, first_val);
                    calculate_parts(col);
                }

                if(fieldName == "Template"){
                    setTemplate(col, first_val);
                }

                if(fieldName == "SampleType"){
                    unsetTemplate(col);
                    calculate_parts(col);
                }

                if(fieldName == "Specification"){
                    reset_spec_field_values(col);
                }

            }
        }
        //$('[id*=_' + fieldName + "]").change();
    }
}



function toggleCat(poc, category_uid, column, selectedservices, force_expand, disable) {
    // selectedservices and column are optional.
    // disable is used for field analyses - secondary ARs should not be able
    // to select these
    force_expand = force_expand || false;
    disable = disable || -1;
    if(!column && column !== 0) { column = ""; }

    var th = $("th[poc='"+poc+"']").filter("[cat='"+category_uid+"']");
    var tbody = $("#"+poc+"_"+category_uid);

    if($(tbody).hasClass("expanded")){
        // displaying an already expanded category:
        if(selectedservices){
            var rows = tbody.children();
            for(var i = 0; i < rows.length; i++){
                var service = rows[i];
                var service_uid = $(service).attr("id");
                if(selectedservices.indexOf(service_uid) > -1){
                    var cb = $("input[value="+service_uid+"]").filter("[column='"+column+"']");
                    $(cb).prop("checked",true);
                    toggle_spec_fields(cb);
                }
            }
            recalc_prices(column);
        } else {
            if (force_expand){ $(tbody).toggle(true); }
            else { $(tbody).toggle(); }
        }
    } else {
        if(!selectedservices) selectedservices = [];
        $(tbody).removeClass("collapsed").addClass("expanded");
        var options = {
            "selectedservices": selectedservices.join(","),
            "categoryUID": category_uid,
            "column": column,
            "disable": disable > -1 ? column : -1,
            "col_count": $("#col_count").attr("value"),
            "poc": poc
        };
        // possibly remove the fake ar context
        var url = window.location.href.split("/ar_add")[0] + "/analysisrequest_analysisservices";
        $(tbody).load(url, options, function(){
            // analysis service checkboxes
            $("input[name*='Analyses']").unbind();
            $("input[name*='Analyses']").bind("change", service_checkbox_change);
            if(selectedservices!=[]){
                recalc_prices(column);
                for(i=0;i<selectedservices.length;i++){
                    var service_uid = selectedservices[i];
                    var e = $("input[value=" + service_uid + "]").filter("[column='" + column + "']");
                    toggle_spec_fields(e);
                }
            }
        });
    }
}

function calc_parts_handler(column, data){
    // Set new part numbers in hidden form field
    var formparts = $.parseJSON($("#parts").val());
    var parts = data.parts;
    formparts[column] = parts;
    $("#parts").val($.toJSON(formparts));
    // write new part numbers next to checkboxes
    for(var p in parts) { if(!parts.hasOwnProperty(p)){ continue; }
        for (var s in parts[p].services) {
            if (!parts[p].services.hasOwnProperty(s)) { continue; }
            $(".partnr_"+parts[p].services[s]).filter("[column='"+column+"']").empty().append(p+1);
        }
    }
}

function calculate_parts(column) {
    // Template columns are not calculated
    if ($("#ar_"+column+"_Template").val() !== ""){
        return;
    }
    var st_uid = $("#ar_"+column+"_SampleType_uid").val();
    var checked = $("[name^='ar\\."+column+"\\.Analyses']").filter(":checked");
    var service_uids = [];
    for(var i=0;i<checked.length;i++){
        var uid = $(checked[i]).attr("value");
        service_uids.push(uid);
    }
    // if no sampletype or no selected analyses:  remove partition markers
    if (st_uid === "" || service_uids.length === 0) {
        $("[class*='partnr_']").filter("[column='"+column+"']").empty();
        return;
    }
    var request_data = {
            services: service_uids.join(","),
            sampletype: st_uid,
            _authenticator: $("input[name='_authenticator']").val()
    };
    window.jsonapi_cache = window.jsonapi_cache || {};
    var cacheKey = $.param(request_data);
    if (typeof window.jsonapi_cache[cacheKey] === "undefined") {
        $.ajax({
            type: "POST",
            dataType: "json",
            url: window.portal_url + "/@@API/calculate_partitions",
            data: request_data,
            success: function(data) {
                window.jsonapi_cache[cacheKey] = data;
                calc_parts_handler(column, data);
            }
        });
    } else {
        var data = window.jsonapi_cache[cacheKey];
        calc_parts_handler(column, data);
    }
}

function add_Yes(dlg, element, dep_services){
    /*jshint validthis:true */
    var column = $(element).attr("column");
    var key, json_key, dep, i;
    var keyed_deps = {};
    for(i = 0; i<dep_services.length; i++){
        dep = dep_services[i];
        key = {
            col: column,
            poc: dep.PointOfCapture,
            cat_uid: dep.Category_uid
        };
        json_key = $.toJSON(key);
        if(!keyed_deps[json_key]){
            keyed_deps[json_key] = [];
        }
        keyed_deps[json_key].push(dep.Service_uid);
    }

    var modified_cols = [];
    for(json_key in keyed_deps){
        if (!keyed_deps.hasOwnProperty(json_key)){ continue; }
        key = $.parseJSON(json_key);
        if(!modified_cols[key.col]){
            modified_cols.push(key.col);
        }
        var service_uids = keyed_deps[json_key];
        var tbody = $("#"+key.poc+"_"+key.cat_uid);
        if($(tbody).hasClass("expanded")) {
            // if cat is already expanded, manually select service checkboxes
            $(tbody).toggle(true);
            for(i=0; i<service_uids.length; i++){
                var service_uid = service_uids[i];
                var e = $("input[column='"+key.col+"']").filter("#"+service_uid);
                $(e).prop("checked",true);
                toggle_spec_fields(e);
            }
        } else {
            // otherwise, toggleCat will take care of everything for us
            $.ajaxSetup({async:false});
            toggleCat(key.poc, key.cat_uid, key.col, service_uids);
            $.ajaxSetup({async:true});
        }
    }
    recalc_prices();
    for(i=0; i<modified_cols.length; i+=1){
        calculate_parts(modified_cols[i]);
    }
    $(dlg).dialog("close");
    $("#messagebox").remove();


}

function add_No(dlg, element){
    /*jshint validthis:true */
    $(element).prop("checked",false);
    $(dlg).dialog("close");
    $("#messagebox").remove();
}

function calcdependencies(elements, auto_yes) {
    /*jshint validthis:true */
    auto_yes = auto_yes || false;
    jarn.i18n.loadCatalog('bika');
    var _ = window.jarn.i18n.MessageFactory("bika");

    var dep;
    var dep_i, cb;

    var lims = window.bika.lims;

    for(var elements_i = 0; elements_i < elements.length; elements_i++){
        var dep_services = [];  // actionable services
        var dep_titles = [];
        var element = elements[elements_i];
        var column = $(element).attr("column");
        var service_uid = $(element).attr("id");
        var modified_cols = [];
        // selecting a service; discover dependencies
        if ($(element).prop("checked")){
            var Dependencies = lims.AnalysisService.Dependencies(service_uid);
            for(dep_i = 0; dep_i<Dependencies.length; dep_i++) {
                dep = Dependencies[dep_i];
                if ($("input[column='"+column+"']").filter("#"+dep.Service_uid).prop("checked")){
                    continue; // skip if checked already
                }
                dep_services.push(dep);
                dep_titles.push(dep.Service);
            }

            if (dep_services.length > 0) {
                if(!modified_cols[column]){
                    modified_cols.push(column);
                }
                if (auto_yes) {
                    add_Yes(this, element, dep_services);
                } else {
                    var html = "<div id='messagebox' style='display:none' title='" + _("Service dependencies") + "'>";
                    html = html + _("<p>${service} requires the following services to be selected:</p>"+
                                                    "<br/><p>${deps}</p><br/><p>Do you want to apply these selections now?</p>",
                                                    {
                                                        service: $(element).attr("title"),
                                                        deps: dep_titles.join("<br/>")
                                                    });
                    html = html + "</div>";
                    $("body").append(html);
                    $("#messagebox").dialog({
                        width:450,
                        resizable:false,
                        closeOnEscape: false,
                        buttons:{
                            yes: function(){
                                add_Yes(this, element, dep_services);
                            },
                            no: function(){
                                add_No(this, element);
                            }
                        }
                    });
                }
            }
        }
        // unselecting a service; discover back dependencies
        else {
            var Dependants = lims.AnalysisService.Dependants(service_uid);
            if (Dependants.length > 0){
                for (i=0; i<Dependants.length; i++){
                    dep = Dependants[i];
                    cb = $("input[column='"+column+"']").filter("#"+dep.Service_uid);
                    if (cb.prop("checked")){
                        dep_titles.push(dep.Service);
                        dep_services.push(dep);
                    }
                }
                if(dep_services.length > 0){
                    if (auto_yes) {
                        for(dep_i=0; dep_i<dep_services.length; dep_i+=1) {
                            dep = dep_services[dep_i];
                            service_uid = dep.Service_uid;
                            cb = $("input[column='"+column+"']").filter("#"+service_uid);
                            $(cb).prop("checked", false);
                            toggle_spec_fields($(cb));
                            $(".partnr_"+service_uid).filter("[column='"+column+"']").empty();
                            if ($(cb).val() == $("#getDryMatterService").val()) {
                                $("#ar_"+column+"_ReportDryMatter").prop("checked",false);
                            }
                        }
                    } else {
                        $("body").append(
                            "<div id='messagebox' style='display:none' title='" + _("Service dependencies") + "'>"+
                            _("<p>The following services depend on ${service}, and will be unselected if you continue:</p><br/><p>${deps}</p><br/><p>Do you want to remove these selections now?</p>",
                                {service:$(element).attr("title"),
                                deps: dep_titles.join("<br/>")})+"</div>");
                        $("#messagebox").dialog({
                            width:450,
                            resizable:false,
                            closeOnEscape: false,
                            buttons:{
                                Yes: function(){
                                    for(dep_i=0; dep_i<dep_services.length; dep_i+=1) {
                                        dep = dep_services[dep_i];
                                        service_uid = dep.Service_uid;
                                        cb = $("input[column='"+column+"']").filter("#"+service_uid);
                                        $(cb).prop("checked", false);
                                        toggle_spec_fields($(cb));
                                        $(".partnr_"+service_uid).filter("[column='"+column+"']").empty();
                                        if ($(cb).val() == $("#getDryMatterService").val()) {
                                            $("#ar_"+column+"_ReportDryMatter").prop("checked",false);
                                        }
                                    }
                                    $(this).dialog("close");
                                    $("#messagebox").remove();
                                },
                                No:function(){
                                    $(element).prop("checked",true);
                                    toggle_spec_fields($(element));
                                    $(this).dialog("close");
                                    $("#messagebox").remove();
                                }
                            }
                        });
                    }
                }
            }
        }
        recalc_prices();
        for(var i=0; i<modified_cols.length; i+=1){
            calculate_parts(modified_cols[i]);
        }
    }
}

function unsetAnalyses(column){
    $.each($("input[name^='ar."+column+".Analyses']"), function(){
        if($(this).prop("checked")) {
            $(this).prop("checked",false);
            toggle_spec_fields($(this));
        }
        $(".partnr_"+this.id).filter("[column='"+column+"']").empty();
    });
}
// function uncheck_partnrs(column){
//  // all unchecked services have their part numbers removed
//  var ep = $("[class^='partnr_']").filter("[column='"+column+"']").not(":empty");
//  for(var i=0;i<ep.length;i++){
//      var em = ep[i];
//      var uid = $(ep[0]).attr("class").split("_")[1];
//      var cb = $("#"+uid);
//      if ( ! $(cb).prop("checked") ){
//          $(em).empty();
//      }
//  }
// }

function unsetAnalysisProfile(column){
    if($("#ar_"+column+"_Profile").val() !== ""){
        $("#ar_"+column+"_Profile").val("");
    }
}


function unsetTemplate(column){
    if($("#ar_"+column+"_Template").val() !== ""){
        $("#ar_"+column+"_Template_uid").val("");
    }
}


function setTemplate(column, template_title){
    unsetAnalyses(column);
    var request_data = {
        portal_type: "ARTemplate",
        title: template_title,
        include_fields: [
            "SampleType",
            "SampleTypeUID",
            "SamplePoint",
            "SamplePointUID",
            "ReportDryMatter",
            "AnalysisProfile",
            "Partitions",
            "Analyses"]
    };
    window.bika.lims.jsonapi_read(request_data, function(data){
        var template = data.objects[0];
        var request_data, x, i;
        // set our template fields
        $("#ar_"+column+"_SampleType").val(template.SampleType);
        $("#ar_"+column+"_SampleType_uid").val(template.SampleTypeUID);
        $("#ar_"+column+"_SamplePoint").val(template.SamplePoint);
        $("#ar_"+column+"_SamplePoint_uid").val(template.SamplePointUID);
        $("#ar_"+column+"_reportdrymatter").prop("checked", template.reportdrymatter);
        set_default_spec(column);
        // lookup AnalysisProfile
        if(template.AnalysisProfile) {
            request_data = {
                portal_type: "AnalysisProfile",
                title: template.AnalysisProfile,
                include_fields: ["UID"]
            };
            window.bika.lims.jsonapi_read(request_data, function(data){
                $("#ar_"+column+"_Profile").val(template.AnalysisProfile);
                $("#ar_"+column+"_Profile_uid").val(data.objects[0].UID);
            });
        } else {
                $("#ar_"+column+"_Profile").val("");
                $("#ar_"+column+"_Profile_uid").val("");
        }

        // scurrel the parts into hashes for easier lookup
        var parts_by_part_id = {};
        var parts_by_service_uid = {};
        for (x in template.Partitions) {
            if (!template.Partitions.hasOwnProperty(x)){ continue; }
            var P = template.Partitions[x];
            P.part_nr = parseInt(P.part_id.split("-")[1], 10);
            P.services = [];
            parts_by_part_id[P.part_id] = P;
        }
        for (x in template.Analyses) {
            if(!template.Analyses.hasOwnProperty(x)){ continue; }
            i = template.Analyses[x];
            parts_by_part_id[i.partition].services.push(i.service_uid);
            parts_by_service_uid[i.service_uid] = parts_by_part_id[i.partition];
        }
        // this one goes through with the form submit
        var parts = [];
        for(x in parts_by_part_id){
            if(!parts_by_part_id.hasOwnProperty(x)){ continue; }
            parts.push(parts_by_part_id[x]);
        }
        var formparts = $.parseJSON($("#parts").val());
        formparts[column] = parts;
        $("#parts").val($.toJSON(formparts));

        // lookup the services specified in the template
        request_data = {
            portal_type: "AnalysisService",
            UID: [],
            include_fields: ["PointOfCapture", "CategoryUID", "UID"]
        };
        for (x in template.Analyses) {
            if (!template.Analyses.hasOwnProperty(x)){ continue; }
            request_data.UID.push(template.Analyses[x].service_uid);
        }
        // save services in hash for easier lookup this
        window.bika.lims.jsonapi_read(request_data, function(data) {
            var e;
            var poc_cat_services = {};
            for(var x in data.objects) {
                if(!data.objects.hasOwnProperty(x)){ continue; }
                var service = data.objects[x];
                var poc_title = service.PointOfCapture;
                if (!(poc_title in poc_cat_services)) {
                    poc_cat_services[poc_title] = {};
                }
                if (!(service.CategoryUID in poc_cat_services[poc_title])) {
                    poc_cat_services[poc_title][service.CategoryUID] = [];
                }
                poc_cat_services[poc_title][service.CategoryUID].push(service.UID);
        // if (analyses[i]['service_uid'] == null) {
        //     // Exclude empty objects from being processed.
        //     // Sometimes, template_data['Analyses'] returns an array with an
        //     // undefined array value.
        //     continue;
        // }
            }
            // expand categories, select, and enable controls for template services
            for (var p in poc_cat_services) {
                if (!poc_cat_services.hasOwnProperty(p)){ continue; }
                var poc = poc_cat_services[p];
                for (var cat_uid in poc) {
                    if (!poc.hasOwnProperty(cat_uid)) {continue; }
                    var service_uids = poc[cat_uid];
                    var tbody = $("tbody[id='"+p+"_"+cat_uid+"']");
                    var service_uid;
                    // expand category
                    if(!($(tbody).hasClass("expanded"))) {
                        $.ajaxSetup({async:false});
                        toggleCat(p, cat_uid, 0);
                        $.ajaxSetup({async:true});
                    }
                    $(tbody).toggle(true);
                    // select checkboxes
                    for(i=0;i<service_uids.length;i++){
                        service_uid = service_uids[i];
                        e = $("input[column='"+column+"']").filter("#"+service_uid);
                        $(e).prop("checked", true);
                        toggle_spec_fields(e);
                    }
                    // set part number indicators
                    for(i=0;i<service_uids.length;i++){
                        service_uid = service_uids[i];
                        var partnr = parts_by_service_uid[service_uid].part_nr;
                        e = $(".partnr_"+service_uid).filter("[column='"+column+"']");
                        $(e).empty().append(partnr+1);
                    }
                    recalc_prices(column);
                }
            }
        });
    });

    recalc_prices(column);

}

function setAnalysisProfile(column, profile_title){
    var request_data = {
        portal_type: "AnalysisProfile",
        title: profile_title
    };
    window.bika.lims.jsonapi_read(request_data, function(data){
        var profile_objects = data.objects;
        var request_data = {
            portal_type: "AnalysisService",
            title: profile_objects[0].Service,
            include_fields: ["PointOfCapture", "Category", "UID", "title"]
        };
        window.bika.lims.jsonapi_read(request_data, function(data){
            var i;
            unsetAnalyses(column);
            $("#ar_"+column+"_ReportDryMatter").prop("checked",false);

            var service_objects = data.objects;
            if (service_objects.length === 0) return;
            var categorised_services = {};
            for (i in service_objects){
                var key = service_objects[i].PointOfCapture + "_" +
                    service_objects[i].Category;
                if(categorised_services[key] === undefined)
                    categorised_services[key] = [];
                categorised_services[key].push(service_objects[i]);
            }

            for (var poc_cat in categorised_services) {
                var services = categorised_services[poc_cat];
                var th = $("th#cat_"+poc_cat);
                if($(th).hasClass("expanded")){
                    for (i in services){
                        var service_uid = services[i].UID;
                        var e = $("input[column='"+column+"']").filter("#"+service_uid);
                        $(e).prop("checked", true);
                        toggle_spec_fields($(e));
                    }
                    recalc_prices(column);
                } else {
                    var poc = poc_cat.split("_")[0];
                    var cat_uid = services[0].Category_uid;
                    var service_uids = [];
                    for(var x = 0; x<services.length;x++){
                        service_uids.push(services[x].UID);
                    }
                    $.ajaxSetup({async:false});
                    toggleCat(poc, cat_uid, column, service_uids);
                    $.ajaxSetup({async:true});
                }
                $(th).removeClass("collapsed").addClass("expanded");
            }
            calculate_parts(column);
        });
    });
}

function service_checkbox_change(){
    /*jshint validthis:true */
    var column = $(this).attr("column");
    var element = $(this);
    unsetAnalysisProfile(column);
    unsetTemplate(column);

    // Unselecting Dry Matter Service unsets 'Report Dry Matter'
    if ($(this).val() == $("#getDryMatterService").val() && !$(this).prop("checked")) {
        $("#ar_"+column+"_ReportDryMatter").prop("checked",false);
    }

    // unselecting service: remove part number.
    if (!$(this).prop("checked")){
        $(".partnr_"+this.id).filter("[column='"+column+"']").empty();
    }

    calcdependencies([element]);
    recalc_prices();
    calculate_parts(column);
    toggle_spec_fields(element);

}

function clickAnalysisCategory(){
    /*jshint validthis:true */
    // cat is a category uid, and no column is required here.
    toggleCat($(this).attr("poc"), $(this).attr("cat"));
    if($(this).hasClass("expanded")){
        $(this).addClass("collapsed");
        $(this).removeClass("expanded");
    } else {
        $(this).removeClass("collapsed");
        $(this).addClass("expanded");
    }
}

function applyComboFilter(element, filterkey, filtervalue) {
    var base_query=$.parseJSON($(element).attr("base_query"));
    base_query[filterkey] = filtervalue;
    $(element).attr("base_query", $.toJSON(base_query));
    var options = $.parseJSON($(element).attr("combogrid_options"));
    options.url = window.location.href.split("/ar_add")[0] + "/" + options.url;
    options.url = options.url + "?_authenticator=" + $("input[name='_authenticator']").val();
    options.url = options.url + "&catalog_name=" + $(element).attr("catalog_name");
    options.url = options.url + "&base_query=" + $.toJSON(base_query);
    options.url = options.url + "&search_query=" + $(element).attr("search_query");
    options.url = options.url + "&colModel=" + $.toJSON( $.parseJSON($(element).attr("combogrid_options")).colModel);
    options.url = options.url + "&search_fields=" + $.toJSON($.parseJSON($(element).attr("combogrid_options")).search_fields);
    options.url = options.url + "&discard_empty=" + $.toJSON($.parseJSON($(element).attr("combogrid_options")).discard_empty);
    options.force_all="false";
    $(element).combogrid(options);
    $(element).addClass("has_combogrid_widget");
    $(element).attr("search_query", "{}");
}

function fill_column(data) {
    // fields which should not be completed from the source AR.
    var skip_fields = ['Sample', 'Sample_uid'];
    if (data.objects.length > 0) {
        var obj = data.objects[0];
        var col = window.bika.ar_copy_from_col;
        for (var fieldname in obj) {
            if (!obj.hasOwnProperty(fieldname)) {
                continue;
            }
            if (skip_fields.indexOf(fieldname) > -1) {
                continue;
            }
            var fieldvalue = obj[fieldname];
            var el = $("#ar_" + col + "_" + fieldname);
            if (el.length > 0) {
                $(el).val(fieldvalue);
            }
        }
        var services = {};
        var specs = {};
        var poc_name, cat_uid, service_uid, service_uids;
        var i, key;
        for (i = obj.Analyses.length - 1; i >= 0; i--) {
            var analysis = obj.Analyses[i];
            cat_uid = analysis.CategoryUID;
            service_uid = analysis.ServiceUID;
            key = analysis.PointOfCapture + "__" + analysis.CategoryUID;
            if (!(key in services)) {
                services[key] = [];
            }
            services[key].push(service_uid);
            specs[service_uid] = analysis.specification;
        }
        for (key in services) {
            if (!services.hasOwnProperty(key)) {
                continue;
            }
            poc_name = key.split("__")[0];
            cat_uid = key.split("__")[1];
            service_uids = services[key];
            window.toggleCat(poc_name, cat_uid, col, service_uids, true);
            for (i = 0; i < service_uids.length; i++) {
                service_uid = service_uids[i];
                var spec = specs[service_uid];
                if (spec) {
                    $("[name^='ar." + col + ".min." + service_uid + "']").val(spec.min);
                    $("[name^='ar." + col + ".max." + service_uid + "']").val(spec.max);
                    $("[name^='ar." + col + ".error." + service_uid + "']").val(spec.error);
                }
            }
        }
    }
}

$(document).ready(function() {

    // Only if the view is the Analysis Request Add View
    if ($(".template-ar_add #analysisrequest_edit_form").length > 0) {

    // jarn.i18n.loadCatalog('bika');
    // var _ = window.jarn.i18n.MessageFactory("bika");
    // jarn.i18n.loadCatalog('bika');
    // var PMF = window.jarn.i18n.MessageFactory("plone");

    // var curDate = new Date();
    // var y = curDate.getFullYear();
    // var limitString = "1900:" + y;
    // var dateFormat = _("date_format_short_datepicker");
    // if (dateFormat == 'date_format_short_datepicker'){
    //  dateFormat = 'yy-mm-dd';
    // }

    ar_rename_elements();
    ar_referencewidget_lookups();
    ar_set_tabindexes();

    $("input[type=text]").prop("autocomplete", "off")

    $(".copyButton").live("click",  copyButton );

    $("th[class^='analysiscategory']").click(clickAnalysisCategory);

    $("input[name^='Price']").live("change", recalc_prices );

    $("input[id*='_ReportDryMatter']").change(changeReportDryMatter);

  $(".spec_bit").live("change", function() {
        validate_spec_field_entry(this);
  });

    // AR Add/Edit ajax form submits
    var ar_edit_form = $("#analysisrequest_edit_form");
    if (ar_edit_form.ajaxForm !== undefined){
        var options = {
            url: window.location.href.split("/portal_factory")[0] + "/analysisrequest_submit",
            dataType: "json",
            data: {"_authenticator": $("input[name='_authenticator']").val()},
            beforeSubmit: function() {
                $("input[class~='context']").prop("disabled",true);
            },
            success: function(responseText) {
                var destination;
                if(responseText.success !== undefined){
                    if(responseText.labels !== undefined){
                        destination = window.location.href
                            .split("/portal_factory")[0];
                        var ars = responseText.labels;
                        var labelsize = responseText.labelsize;
                        var q = "/sticker?size="+labelsize+"&items=";
                        q = q + ars.join(",");
                        window.location.replace(destination+q);
                    } else {
                        destination = window.location.href
                            .split("/portal_factory")[0];
                        window.location.replace(destination);
                    }
                } else {
                    var msg = "";
                    for(var error in responseText.errors){
                        var x = error.split(".");
                        var e;
                        if (x.length == 2){
                            e = x[1] + ", Column " + (+x[0]) + ": ";
                        } else {
                            e = "";
                        }
                        msg = msg + e + responseText.errors[error] + "<br/>";
                    }
                    window.bika.lims.portalMessage(msg);
                    window.scroll(0,0);
                    $("input[class~='context']").prop("disabled", false);
                }
            },
            error: function(XMLHttpRequest, statusText) {
                window.bika.lims.portalMessage(statusText);
                window.scroll(0,0);
                $("input[class~='context']").prop("disabled", false);
            }
        };
        $("#analysisrequest_edit_form").ajaxForm(options);
    }


    // these go here so that popup windows can access them in our context
    window.recalc_prices = recalc_prices;
    window.calculate_parts = calculate_parts;
    window.toggleCat = toggleCat;

    // Show only the contacts and CC from the selected Client
    $("[id$='_Client']").bind("change", function() {
        var col = this.id.split("_")[1];
        var element = $("#ar_" + col + "_Contact");
        var clientuid = $(this).attr("uid");
        applyComboFilter(element, "getParentUID", clientuid);
        element = $("#ar_" + col + "_CCContact");
        applyComboFilter(element, "getParentUID", clientuid);
        // Filter sample points by client
        element = $("#ar_" + col + "_SamplePoint");
		applyComboFilter(element, "getClientUID",
						 [clientuid, $("#bika_setup").attr("bika_samplepoints_uid")]);
        // Filter template by client
        element = $("#ar_" + col + "_Template");
        applyComboFilter(element, "getClientUID",
						 [clientuid, $("#bika_setup").attr("bika_artemplates_uid")]);
        // Filter Analysis Profile by client
        element = $("#ar_" + col + "_Profile");
        applyComboFilter(element, "getClientUID",
						 [clientuid, $("#bika_setup").attr("bika_analysisprofiles_uid")]);
        // Filter Analysis Spec by client
        element = $("#ar_" + col + "_Specification");
        applyComboFilter(element, "getClientUID",
						 [clientuid, $("#bika_setup").attr("bika_analysisspecs_uid")]);
    });
    // Iterate all the columns to filtrate by client
    for (var col = 0; col < parseInt($("#col_count").val(), 10); col++) {
        var element = $("#ar_" + col + "_Contact");
        var clientuid = $("#ar_" + col + "_Client_uid").val();
        // Initial value of contact list, set by the page's hidden ClientUID.
        applyComboFilter(element, "getParentUID", clientuid);
        element = $("#ar_" + col + "_CCContact");
        applyComboFilter(element, "getParentUID", clientuid);
        // Filter sample points by client
        element = $("#ar_" + col + "_SamplePoint");
        applyComboFilter(element, "getClientUID",
						 [clientuid, $("#bika_setup").attr("bika_samplepoints_uid")]);
        // Filter template by client
        element = $("#ar_" + col + "_Template");
        applyComboFilter(element, "getClientUID",
						 [clientuid, $("#bika_setup").attr("bika_artemplates_uid")]);
        // Filter Analysis Profile by client
        element = $("#ar_" + col + "_Profile");
        applyComboFilter(element, "getClientUID",
						 [clientuid, $("#bika_setup").attr("bika_analysisprofiles_uid")]);
        // Filter Analysis Spec by client
        element = $("#ar_" + col + "_Specification");
        applyComboFilter(element, "getClientUID",
						 [clientuid, $("#bika_setup").attr("bika_analysisspecs_uid")]);
    }

    var copy_from = window.location.href.split("copy_from=");
    if(copy_from.length > 1){
        copy_from = copy_from[1].split("&")[0];
        copy_from = copy_from.split(",");
        for (var column = 0; column < copy_from.length; column++) {
            window.bika.ar_copy_from_col = column;
            $.ajaxSetup({async:false});
            window.bika.lims.jsonapi_read({
                catalog_name: "uid_catalog",
                UID: copy_from[column]
            }, fill_column);
            $.ajaxSetup({async:true});
        }
    }

}
});
}(jQuery));
