function AddRow(
    rowId,
    prefixId,
    tableId,
    idPrefixId = "",
    anNo = 0,
    selectClearNotAllowed = false
) {
    let row = $(rowId);

    if (!ValidateRow(row)) {
        return null;
    }

    let newRow = $(row).clone();
    let dateTimePickersToInitialize = [];
    let datePickersToInitialize = [];
    let select2ToInitialize = [];
    let namePrefix = $(prefixId).val();
    let lastRowIdNo = Number($(tableId).find('tr:last').attr('id'));
    let newOrdinalNo = 0;
    let tabletWidth = window.innerWidth >= 576 && window.innerWidth <= 768;
    let mobileWidth = window.innerWidth < 576;

    if (!isNaN(lastRowIdNo)) {
        newOrdinalNo = ++lastRowIdNo;
    }

    newRow.attr('id', newOrdinalNo);
    namePrefix = namePrefix.replace('OrdinalNumberNo', newOrdinalNo);

    //handle id's of inputs
    $(newRow).each(function () {
        $(this)
            .find(':input')
            .each(function () {

                let elementName = $(this).attr('name');
                let elementId = $(this).attr('id');
                let dataUrl = $(this).attr('data-url');
                let elementClass = $(this).attr('class');
                let newId = elementId + newOrdinalNo;

                if (idPrefixId) {
                    let idPrefix = $(idPrefixId).val();
                    idPrefix = idPrefix.replace('OrdinalNumberNo', newOrdinalNo);
                    idPrefix = idPrefix.replace('Property', elementName);
                    idPrefix = idPrefix.replace('AnNo', anNo);
                    idPrefix = idPrefix.replace('AnCostNo', anNo);
                    newId = idPrefix;
                }

                $(this).attr('id', newId);

             
                let newName = namePrefix.replace('Property', elementName);
                $(this).attr('name', newName);

                //since select2 is not initializing after row insert we must build 
                //new select list, pass selected value, and replace td content
                if (elementClass && ~elementClass.indexOf('select2')) {
                    let cell = $(this).closest('td');
                    let selectData = $("#" + elementId).select2('data');
                    let select2Id = newId;
                    let filterBy = $("#" + elementId).attr("filter-by");

                    $(cell).html(
                        BuildSelectList(select2Id,
                            newName,
                            dataUrl,
                            selectData,
                            filterBy
                        ));

                    select2ToInitialize.push(select2Id);
                }
                else if (elementClass && ~elementClass.indexOf('custom-datepicker')) {
                    datePickersToInitialize.push(newId);
                }
                else if (elementClass && ~elementClass.indexOf('custom-datetimepicker')) {
                    dateTimePickersToInitialize.push(newId);
                }
            });
    });

    if (tabletWidth === true) {
        $(newRow).find('td:nth-child(6)').html(BuildDeleteButton(tableId, newOrdinalNo));
        $(tableId + ' tbody').append(newRow);
    } else if (mobileWidth === true) {
        $(newRow).find('td:nth-child(3)').html(BuildDeleteButton(tableId, newOrdinalNo));
        $(tableId + ' tbody').append(newRow);
    } else {
        $(newRow).find('td:last').html(BuildDeleteButton(tableId, newOrdinalNo));
        $(tableId + ' tbody').append(newRow);
    }    

    //clear original row fields
    $(row).each(function () {
        $(this).find(':input').each(function () {
            let elementClass = $(this).attr('class');
            let resetValue = $(this).attr('resetValue');

            if (!resetValue || resetValue !== 'false') {
                $(this).val('');
            }

            if (elementClass && (~elementClass.indexOf('select2') || ~elementClass.indexOf('custom-datetimepicker'))) {
                $(this).val(null).trigger('change');
            }
        });

        $(this).find(':checkbox').each(function () {
            $(this).attr("checked", false);
            $(this).prop('checked', false);
            $(this).val("false");
        });
    });

    //initialize date pickers and select2
    $(dateTimePickersToInitialize).each(function (index, element) {
        dateTimePicker(element);
    });

    $(datePickersToInitialize).each(function (index, element) {
        datePicker(element);
    });

    $(select2ToInitialize).each(function (index, element) {
        let elem = $("#" + element);
        if (selectClearNotAllowed) {
            $(elem).attr('data-allow-clear', 'false');
        }
        initializeSelect2WithAPI(elem);
    });

    return newRow;
}

function ValidateRow(row) {
    let validRow = true;

    $(row).each(function () {
        $(this)
            .find(':input')
            .each(function () {

                let required = $(this).attr('required');

                if (required && !getFieldValue(this.id)) {
                    validRow = false;
                    $(this).parents('td').last().css('border-bottom', '1px solid red');
                }
                else {
                    $(this).parents('td').last().css('border-bottom', '1px solid #ddd');
                }

            });
    });

    return validRow;
}


function DeleteRow(tableId, id) {
    let row = $('#' + tableId + ' #' + id);

    let delField = $(row).find("input[name$='Deleted']");
    delField.val('True');
    row.slideToggle("slow");
}

function DeleteDistance(tableId, id) {
    let row = $('#' + tableId + ' #' + id);

    let delField = $(row).find("input[name$='Deleted']");
    delField.val('True');
    $('#distance-accordion-' + id).hide();
}