// general variables
var eventid;  // string with id field from JSON
var bookingtoken;
var serverInfo, serverNewBooking, serverResourceAvailability, serverValidateBooking, serverPackBooking, serverPayBooking;
var pages;
// pack variables
var pack;
var packToken;
var packBookings = new Array();
var packTotalAmount, packDepositAmount;
// calculator variables
var calculator;
var amounts = new Array();
var biggestAmount, smallestAmount, price, discount, deposit, totalAmount, depositAmount;
var prices = new Array();
var discounts = new Array();
var deposits = new Array();

var inputFields;
var availableFields; // output from server
var unavailableFields; // fields sold out
var inputsForAvailabilityCheck; // inputs for availability check
var lowavailabilitythreshold; // threshold for low availability alert

const params = new Proxy(new URLSearchParams(window.location.search), {
    get: (searchParams, prop) => searchParams.get(prop),
});

function getFileName() {
    let url = new URL(window.location.href);
    let path = url.pathname;
    let fileName = path.substring(path.lastIndexOf('/') + 1);
    return fileName;
}

$(document).ready( function () {
    // set current year
    $("#yearCurrent").html(new Date().getFullYear());
    // read meta and update form
    $('[name="title"]').html(document.querySelector('meta[name="title"]').content.trim());
    $('[name="author"]').html(document.querySelector('meta[name="author"]').content.trim());
    if( params.token!==undefined )
        packToken = params.token;
    // load respective json
    $.ajax({
        cache: false,
        url: (getFileName().substring(0, getFileName().lastIndexOf('.')) + ".json"),
        dataType: "json",
        success: function(data) {
            // Disabled for development only
            // In production it should be executed
            /*
            if ( data.fields['terms'] !== undefined )
                $('#modalInfo').modal('show');
            */
            // set PHP servers that will receive/validate the booking
            url_dream = window.location.protocol + "//" + window.location.hostname + window.location.pathname.substring(0, window.location.pathname.lastIndexOf(data.id));
            serverInfo                  = url_dream + data.controller.server;
            serverNewBooking            = url_dream + data.controller.new;
            serverResourceAvailability  = url_dream + data.controller.available;
            serverValidateBooking       = url_dream + data.controller.validator;
            serverPackBooking           = url_dream + data.controller.pack;
            serverPayBooking            = url_dream + data.controller.payment;
            // get activity id
            eventid = data.id.substring(data.id.indexOf('/') + 1);
            // set globals
            inputsForAvailabilityCheck = data.inputsForAvailabilityCheck;
            lowavailabilitythreshold = data.lowavailabilitythreshold;
            // get calculator
            $.ajax({
                type: "POST",
                url: serverInfo,
                dataType: 'json',
                data: '{"activity":"' + eventid + '"}',
                success: function(data2) {
                    // check if activity is open
                    if ( data2.error!==undefined ) {
                        // bookings closed
                        $('#modal' + data2.error).modal('show');
                        return;
                    }
                    // get calculator
                    if( data2.calculator!==undefined )
                        calculator = data2.calculator;
                    else
                        return;
                    // get pack
                    if( data2.pack!==undefined )
                        pack = data2.pack;
                    // setup form
                    if( data.setup!==undefined )
                        setupForm( data.setup );
                    // set click handlers
                    $.each( data.events.input, function( key, val ) {
                        $( "input[name='" + key + "']" ).on( 'click', val, inputClickHandler );
                    });
                    // check if form is paginated
                    if( data2.booking[0].pages===undefined || data2.booking[0].pages===false )
                        pages = false;
                    else
                        pages = data2.booking[0].pages;
                    if( pages!==false ) {
                        $("button[name='bNext']").click(function(event) {
                            var tabindex = $('.nav-tabs .active').closest('li').index();
                            var allvalid = true;
                            var type;
                            $.each( pages[tabindex], function( key, val) {
                                type = $("input[name='" + val + "']").attr("type");
                                if( type=="radio" && !$("input[name='" + val + "']:checked").val() ) {
                                    allvalid = false;
                                    $("input[name='" + val + "']").addClass("is-invalid");
                                } else if( type=="text" && !$("input[name='" + val + "']").val() ) {
                                    allvalid = false;
                                    $("input[name='" + val + "']").addClass("is-invalid");
                                }
                            });
                            if( allvalid===false ) {
                                return;
                            }
                            const nextTabLinkEl = $('.nav-tabs .active').closest('li').next('li').find('button')[0];
                            if( nextTabLinkEl!==undefined ) {
                                const nextTab = new bootstrap.Tab(nextTabLinkEl);
                                nextTab.show();
                                $( "button[name='bPrevious']" ).removeClass("d-none");
                                const nextnextTabLinkEl = $('.nav-tabs .active').closest('li').next('li').find('button')[0];
                                if( nextnextTabLinkEl===undefined ) {
                                    $( "button[name='bNext']" ).addClass("d-none");
                                    $( "button[name='bSubmit']" ).removeClass("d-none");
                                }
                            }
                        });
                        $("button[name='bPrevious']").click(function(event) {
                            const prevTabLinkEl = $('.nav-tabs .active').closest('li').prev('li').find('button')[0];
                            if( prevTabLinkEl!==undefined ) {
                                const prevTab = new bootstrap.Tab(prevTabLinkEl);
                                prevTab.show();
                                $( "button[name='bNext']" ).removeClass("d-none");
                                $( "button[name='bSubmit']" ).addClass("d-none");
                                const prevprevTabLinkEl = $('.nav-tabs .active').closest('li').prev('li').find('button')[0];
                                if( prevprevTabLinkEl===undefined ) {
                                    $( "button[name='bPrevious']" ).addClass("d-none");
                                }
                            }
                        });
                    } else
                        $( "button[name='bSubmit']" ).removeClass("d-none");
                    // set recalculate amounts event handler
                    $.each( calculator, function( key, val ) {
                        $.each( val, function( key2, val2 ) {
                            $( "input[name='" + key2 + "']" ).on( 'click', val2, calculateAmounts );
                        });  
                    });
                    // get pack token from URL (null if not present)
                    if( packToken!=null ) {
                        let inputfields = {};
                        // add activity ID to form data
                        inputfields.activity = eventid;
                        inputfields.packtoken = packToken;
                        $.ajax({
                            type: "POST",
                            url: serverPackBooking,
                            dataType: 'json',
                            data: JSON.stringify( inputfields ),
                            success: function(result){
                                packBookings = result.bookings;
                                // add pack bookings to table
                                packTotalAmount = parseFloat(result.totalamount).toFixed(2);
                                packDepositAmount = parseFloat(result.depositamount).toFixed(2);
                                $.each( result.bookings, function( key, val ) {
                                    $('#infoBooking tbody').append('<tr><td>' + val.number + '</td><td>' + val.name + '</td><td>' + val.price + '</td><td>' + val.deposit + '</td><td>0</td></tr>');
                                });
                                // update amounts
                                $("#packTotalAmount").text(packTotalAmount);
                                $("#packDepositAmount").text(packDepositAmount);
                                $('#t_PaymentAmount').prop('placeholder', "Entre " + packDepositAmount + " e " + packTotalAmount);
                            },
                            error: function (jqXHR, exception) {
                                var msg = '';
                                if (jqXHR.status === 0) {
                                    msg = 'Not connect.\n Verify Network.';
                                } else if (jqXHR.status === 400) {
                                    msg = 'Valor do ano é inválido!';
                                } else if (jqXHR.status === 403) {
                                    msg = 'Não foi possível criar o diretório!';
                                } else if (jqXHR.status == 404) {
                                    msg = 'Requested page not found. [404]';
                                } else if (jqXHR.status === 409) {
                                    msg = 'O diretório já existe!';
                                } else if (jqXHR.status == 500) {
                                    msg = 'Internal Server Error [500].';
                                } else {
                                    msg = 'Uncaught Error.\n' + jqXHR.responseText;
                                }
                            }
                        });
                        //$('#formBooking').addClass("d-none");
                        $('#formPack').removeClass("d-none");
                        $('#formPayment').removeClass("d-none");
                    }
                    // Disabled for development only
                    // In production it should be executed
                    /*
                    if ( data.fields['terms'] !== undefined )
                        // Mandatory info modal
                        $('#formInfo').submit(function(e){
                            var proceed=true;
                            $( "input[name='" + data.fields['terms'] + "']" ).each( function() {
                                if( $(this).prop("checked") === false )
                                    proceed=false;
                            });
                            if( proceed )
                                $('#modalInfo').modal('hide');
                            e.preventDefault();
                        });
                    */

                    /*
                    // SE test
                    if(typeof(EventSource) !== "undefined") {
                        var source = new EventSource("server/sse.php");
                        source.onmessage = function(event) {
                            document.getElementById("info").innerHTML += event.data + "<br>";
                        };
                        } else {
                        document.getElementById("info").innerHTML = "Sorry, your browser does not support server-sent events...";
                        }
                    */

                },
                error: function (jqXHR, exception) {
                    var msg = '';
                    if (jqXHR.status === 0) {
                        msg = 'Not connect.\n Verify Network.';
                    } else if (jqXHR.status === 400) {
                        msg = 'Valor do ano é inválido!';
                    } else if (jqXHR.status === 403) {
                        msg = 'Não foi possível criar o diretório!';
                    } else if (jqXHR.status == 404) {
                        msg = 'Requested page not found. [404]';
                    } else if (jqXHR.status === 409) {
                        msg = 'O diretório já existe!';
                    } else if (jqXHR.status == 500) {
                        msg = 'Internal Server Error [500].';
                    } else {
                        msg = 'Uncaught Error.\n' + jqXHR.responseText;
                    }
                }
            });
        }
    });
    // disable form submissions if there are invalid fields
    (function () {
        'use strict'

        var form = document.getElementById('formBooking');
        
        form.addEventListener('submit', function (event) {
            if (!form.checkValidity()) {
              event.preventDefault()
              event.stopPropagation()
            } else {
              event.preventDefault();
              event.stopPropagation()
              // prepare modal Confirmation
              function convertFormToJSON(form) {
                  return $(form)
                      .serializeArray()
                      .reduce(function (json, { name, value }) {
                          json[name] = value;
                          return json;
                      }, {});
              }  
              inputFields = convertFormToJSON(form);
              $.each( inputFields, function(key, val) {
                  var value=val;
                  var optionkey = key + "\\." + val;
                  try{
                      if ( $( 'label[for=' + optionkey + ']' ).length ) {
                          value = $( 'label[for=' + optionkey + ']' ).text();
                      }
                  } catch(err) {
                  }
                  if( value.length ) {
                      $('#tConfirmation tr[name=' + key + '] td').html(value);
                      $('#tConfirmation tr[name=' + key + ']').prop("hidden", false);
                      //$('#tConfirmation tr[name=' + key + ']').show();
                  } else {
                      $('#tConfirmation tr[name=' + key + ']').prop("hidden", true);
                      //$('#tConfirmation tr[name=' + key + ']').hide();
                  }
              });
              $('#modalConfirmation').modal('show');
            }
            form.classList.add('was-validated')
        }, false)

        var form2 = document.getElementById('formPayment');

        form2.addEventListener('submit', function (event) {
            if (!form2.checkValidity()) {
              event.preventDefault()
              event.stopPropagation()
            } else {
              event.preventDefault();
              event.stopPropagation()
              /*
              // prepare modal Confirmation
              function convertFormToJSON(form) {
                  return $(form)
                      .serializeArray()
                      .reduce(function (json, { name, value }) {
                          json[name] = value;
                          return json;
                      }, {});
              }  
              inputFields = convertFormToJSON(form);
              $.each( inputFields, function(key, val) {
                  var value=val;
                  var optionkey = key + "\\." + val;
                  try{
                      if ( $( 'label[for=' + optionkey + ']' ).length ) {
                          value = $( 'label[for=' + optionkey + ']' ).text();
                      }
                  } catch(err) {
                  }
                  if( value.length ) {
                      $('#tConfirmation tr[name=' + key + '] td').html(value);
                      $('#tConfirmation tr[name=' + key + ']').show();
                  } else
                      $('#tConfirmation tr[name=' + key + ']').hide();
              });
              $('#modalConfirmation').modal('show');
              */
            }
            form2.classList.add('was-validated')
        }, false)

    })()

    $('#formConfirmation').submit(function(e){
        e.preventDefault();
        e.stopPropagation();
        // add activity ID to form data
        inputFields.activity = eventid;
        // add token if it exists
        if( bookingtoken!==undefined ) inputFields.token = bookingtoken;
        // add date/time/zone to form data
        inputFields.datetimeUTC    = new Date().toISOString();
        inputFields.timezone       = Intl.DateTimeFormat().resolvedOptions().timeZone;
        inputFields.timezoneOffset = new Date().getTimezoneOffset();
        // add HTML language
        inputFields.language       = document.documentElement.lang;
        inputFields.contentLanguage= document.querySelector('meta[http-equiv="content-language"]').content.trim();
        // add OS to form data
        inputFields.os = getOS();
        // add screen/browser window size
        inputFields.screenWidth  = screen.width;
        inputFields.screenHeight = screen.height;
        inputFields.windowWidth  = window.innerWidth;
        inputFields.windowHeight = window.innerHeight;
        // Detect Landscape or Portrait mode
        if (window.matchMedia('(orientation: portrait)').matches == true)
            inputFields.orientation = "portrait";
        else
            inputFields.orientation = "landscape";
        // Submit new booking data
        $.ajax({
            type: "POST",
            url: serverNewBooking,
            dataType: 'json',
            data: JSON.stringify( inputFields ),
            success: function(result){
                $('#modalConfirmation').modal('hide');
                if (result.error) {
                    // Server internal error
                    $('#modalValidationSavedBookingError').removeClass("d-none");
                    return;
                }
                // Received a temporary token
                var validationRequest = {};
                validationRequest.activity = inputFields.activity;
                validationRequest.token    = result.token;
                //validationRequest.pack     = JSON.stringify( packBookings );
                validationRequest.packtoken= packToken;
                // Validate booking data
                $.ajax({
                    type: "POST",
                    url: serverValidateBooking,
                    dataType: 'json',
                    data: JSON.stringify( validationRequest ),
                    success: function(result){
                        $('#modalValidationSavedBooking').addClass("d-none");
                        if (result.number===undefined || typeof result.number!=='number') {
                            // Not all selected options are available
                            bookingtoken = result.token;
                            $('#modalValidationSavedBookingReview').removeClass("d-none");
                            getResourceAvailability();
                            return;
                        }

                        // Received the booking number
                        // store it in the pack
                        //packBookings.push(result.number);
                        // store the pack token
                        packToken = result.packtoken;
                        // prepare pack
                        inputfields = {};
                        inputfields.activity = eventid;
                        /*
                        // request booking data for packBookings
                        $json = '{"pack":[{"number":8},{"number":9}]}';
                        packBookings = JSON.parse($json);
                        inputfields.pack = packBookings.pack;
                        */
                        if( packToken!==undefined && packToken!='' ) {
                            inputfields.packtoken = packToken;
                            $.ajax({
                                type: "POST",
                                url: serverPackBooking,
                                dataType: 'json',
                                data: JSON.stringify( inputfields ),
                                success: function(result){
                                    // add pack bookings to table
                                    $('#infoBooking tbody').html('');
                                    $.each( result.bookings, function( key, val ) {
                                        $('#infoBooking tbody').append('<tr><td>' + val.number + '</td><td>' + val.name + '</td><td>' + val.price + '</td><td>' + val.deposit + '</td><td>0</td></tr>');
                                    });
                                },
                                error: function (jqXHR, exception) {
                                    var msg = '';
                                    if (jqXHR.status === 0) {
                                        msg = 'Not connect.\n Verify Network.';
                                    } else if (jqXHR.status === 400) {
                                        msg = 'Valor do ano é inválido!';
                                    } else if (jqXHR.status === 403) {
                                        msg = 'Não foi possível criar o diretório!';
                                    } else if (jqXHR.status == 404) {
                                        msg = 'Requested page not found. [404]';
                                    } else if (jqXHR.status === 409) {
                                        msg = 'O diretório já existe!';
                                    } else if (jqXHR.status == 500) {
                                        msg = 'Internal Server Error [500].';
                                    } else {
                                        msg = 'Uncaught Error.\n' + jqXHR.responseText;
                                    }
                                }
                            });
                        } else {

                        }
            

                        // update interface
                        $('#bookingNumber').html(result.number);
                        //$('#formBooking').addClass("d-none");
                        $('#formPack').removeClass("d-none");
                        $('#formPayment').removeClass("d-none");
                        // Fill bookings table
                        $('#infoBooking tbody').append('<tr><td>' + result.number + '</td><td>' + inputFields.datetimeUTC + '</td></tr>');
                        // Select payment method
                        var paymentAmount = $( "input[name='t_Payment']:checked" ).val();
                        if( paymentAmount == "full") {
                            $( "input[name='paymentAmount']" ).val(totalAmount);
                        } else if ( paymentAmount == "minimum") {
                            $( "input[name='paymentAmount']" ).val(depositAmount);
                        } else if ( paymentAmount == "other") {
                            $( "input[name='paymentAmount']" ).val($( "input[name='t_PaymentAmount']" ).val());
                        } else {
                            // error
                            // use full amount
                            $( "input[name='paymentAmount']" ).val(totalAmount);
                        }
                    },
                    error: function (jqXHR, exception) {
                        var msg = '';
                        if (jqXHR.status === 0) {
                            msg = 'Not connect.\n Verify Network.';
                        } else if (jqXHR.status === 400) {
                            msg = 'Valor do ano é inválido!';
                        } else if (jqXHR.status === 403) {
                            msg = 'Não foi possível criar o diretório!';
                        } else if (jqXHR.status == 404) {
                            msg = 'Requested page not found. [404]';
                        } else if (jqXHR.status === 409) {
                            msg = 'O diretório já existe!';
                        } else if (jqXHR.status == 500) {
                            msg = 'Internal Server Error [500].';
                        } else {
                            msg = 'Uncaught Error.\n' + jqXHR.responseText;
                        }
                    }
                });     
            },
            error: function (jqXHR, exception) {
                var msg = '';
                if (jqXHR.status === 0) {
                    msg = 'Not connect.\n Verify Network.';
                } else if (jqXHR.status === 400) {
                    msg = 'Valor do ano é inválido!';
                } else if (jqXHR.status === 403) {
                    msg = 'Não foi possível criar o diretório!';
                } else if (jqXHR.status == 404) {
                    msg = 'Requested page not found. [404]';
                } else if (jqXHR.status === 409) {
                    msg = 'O diretório já existe!';
                } else if (jqXHR.status == 500) {
                    msg = 'Internal Server Error [500].';
                } else {
                    msg = 'Uncaught Error.\n' + jqXHR.responseText;
                }
            }
        });     
    });

    $('#formPack').submit(function(e){
        e.preventDefault();
        e.stopPropagation();

        // clear formBooking and start a new booking
        //$('#formBooking').trigger("reset");
        function resetForm($form) {
            $form.find('input:text, input:password, input:file, select, textarea').val('');
            $form.find('input:radio, input:checkbox')
                 .removeAttr('checked').removeAttr('selected');
        }
        
        // to call, use:
        resetForm($('#formBooking')); // by id, recommended
        //resetForm($('form[name=myName]')); // by name
        
        //$('#formBooking').addClass('was-validated')
        $('#formPack').addClass("d-none");
        $('#formPayment').addClass("d-none");
        $('#formBooking').removeClass("d-none");   
    });


    $('#formPayment').submit(function(e){
        e.preventDefault();
        e.stopPropagation();
        // add activity ID to form data
        inputFields.activity = eventid;
        if( packToken!==undefined && packToken!='' ) {
            inputFields.packtoken = packToken;
        } else {    
            // add booking number to form data
            inputFields.bookingnumber = $('#bookingNumber').html();
        }
        // add payment amount
        inputFields.payment = $( "#formPayment input[name='t_Payment']:checked" ).val();
        inputFields.paymentamount = $( "#formPayment input[name='t_PaymentAmount']" ).val();
        // add payment method
        inputFields.paymentmethod = $( "#formPayment input[name='s_Payment']:checked" ).val();
        // add date/time/zone to form data
        inputFields.datetimeUTC    = new Date().toISOString();
        inputFields.timezone       = Intl.DateTimeFormat().resolvedOptions().timeZone;
        inputFields.timezoneOffset = new Date().getTimezoneOffset();
        // add HTML language
        inputFields.language       = document.documentElement.lang;
        inputFields.contentLanguage= document.querySelector('meta[http-equiv="content-language"]').content.trim();
        // add OS to form data
        inputFields.os = getOS();
        // add screen/browser window size
        inputFields.screenWidth  = screen.width;
        inputFields.screenHeight = screen.height;
        inputFields.windowWidth  = window.innerWidth;
        inputFields.windowHeight = window.innerHeight;
        // Detect Landscape or Portrait mode
        if (window.matchMedia('(orientation: portrait)').matches == true)
            inputFields.orientation = "portrait";
        else
            inputFields.orientation = "landscape";
        // Submit new booking data
        $.ajax({
            type: "POST",
            url: serverPayBooking,
            dataType: 'json',
            data: JSON.stringify( inputFields ),
            success: function(result){

            },
            error: function (jqXHR, exception) {
                var msg = '';
                if (jqXHR.status === 0) {
                    msg = 'Not connect.\n Verify Network.';
                } else if (jqXHR.status === 400) {
                    msg = 'Valor do ano é inválido!';
                } else if (jqXHR.status === 403) {
                    msg = 'Não foi possível criar o diretório!';
                } else if (jqXHR.status == 404) {
                    msg = 'Requested page not found. [404]';
                } else if (jqXHR.status === 409) {
                    msg = 'O diretório já existe!';
                } else if (jqXHR.status == 500) {
                    msg = 'Internal Server Error [500].';
                } else {
                    msg = 'Uncaught Error.\n' + jqXHR.responseText;
                }
            }
        });     
    });


})
function getOS() {
    var userAgent = window.navigator.userAgent,
        platform = window.navigator.platform,
        macosPlatforms = ['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'],
        windowsPlatforms = ['Win32', 'Win64', 'Windows', 'WinCE'],
        iosPlatforms = ['iPhone', 'iPad', 'iPod'],
        os = null;
  
    if (macosPlatforms.indexOf(platform) !== -1) {
      os = 'Mac OS';
    } else if (iosPlatforms.indexOf(platform) !== -1) {
      os = 'iOS';
    } else if (windowsPlatforms.indexOf(platform) !== -1) {
      os = 'Windows';
    } else if (/Android/.test(userAgent)) {
      os = 'Android';
    } else if (!os && /Linux/.test(platform)) {
      os = 'Linux';
    }
  
    return os;
}
/*
function checkBookingOpen( form ) {
    var date = new Date();
    // Evaluate date array and open switch
    $.each( form, function (key, val) {
        if( val.date!==undefined && val.date.begin!==undefined ) {
            var begin = new Date(val.date.begin);
            if( date < begin ) {
                $('#modalBookingNotStarted').modal('show');
                return; // continue
            }
        }
        if( val.date!==undefined && val.date.end!==undefined ) {
            var end = new Date(val.date.end);
            if( date > end ) {
                $('#modalBookingEnded').modal('show');
                return; // continue
            }
        }
        if( val.open!==undefined && val.open===false ) {
            $('#modalTemporarilyClosed').modal('show');
            return false; // break
        }
    });
}
    */
function getResourceAvailability(actions=false) {
    const form = document.querySelector('form')
    function convertFormToJSON(form) {
        return $(form)
            .serializeArray()
            .reduce(function (json, { name, value }) {
                json[name] = value;
                return json;
            }, {});
    }  
    inputFields = convertFormToJSON(form);
    // remove all fields that are not in the list
    for (const key in inputFields)
        if( inputsForAvailabilityCheck.includes(key)===false )
            delete inputFields[key];
    // add activity ID to form data
    inputFields.activity = eventid;
    $.ajax({
        type: "POST",
        url: serverResourceAvailability,
        dataType: 'json',
        data: JSON.stringify( inputFields ),
        success: function(result){
            availableFields = result.available;
            unavailableFields = new Array();
            // check if any time field is sold out
            $.each( availableFields, function (key, val) {
                let t_available = false;
                $.each( val, function (key2, val2) {
                    let s_available = false;
                    let s_capacity = 0;
                    $.each( val2, function (key3, val3) {
                        let r_available = true;
                        let r_capacity;
                        $.each( val3, function (key4, val4) {
                            if( r_capacity===undefined || r_capacity>val4 ) 
                                r_capacity = val4;
                            if( val4==0 ) {
                                r_available = false;
                                return false;
                            }
                        });
                        if( r_available===true )
                            s_available = true;
                            //return false;
                        if( r_capacity!==undefined )
                            s_capacity += r_capacity;
                    });
                    if( s_available===false ) {
                        unavailableFields.push(key2);
                        $( '[id="' + key2 + '"]' ).prop("checked", false);
                        $( '[id="' + key2 + '"]' ).prop("disabled", true);
                    } else {
                        t_available = true;
                        $( '[id="' + key2 + '"]' ).prop("disabled", false);
                        let field = key2.substring(0, key2.indexOf('.'));
                        let value = key2.substring(key2.indexOf('.')+1);
                        // check if low availability alert is set
                        if( lowavailabilitythreshold!=undefined && lowavailabilitythreshold[field]!=undefined) {
                            if( !Array.isArray(lowavailabilitythreshold[field]) && s_capacity<lowavailabilitythreshold[field] )
                                $( '[id="' + key2 + '.alert"]' ).removeClass("d-none");
                            else if( Array.isArray(lowavailabilitythreshold[field]) && s_capacity<lowavailabilitythreshold[field][value] )
                                $( '[id="' + key2 + '.alert"]' ).removeClass("d-none");
                        } else {
                            $( '[id="' + key2 + '.alert"]' ).addClass("d-none");
                        }
                    }
                });
                if( t_available===false ) {
                    unavailableFields.push(key);
                    $( '[id="' + key + '"]' ).prop("checked", false);
                    $( '[id="' + key + '"]' ).prop("disabled", true);
                }
            });
            if( actions!==false )
                // do actions
                doActions( actions );
        },
        error: function (jqXHR, exception) {
            var msg = '';
            if (jqXHR.status === 0) {
                msg = 'Not connect.\n Verify Network.';
            } else if (jqXHR.status === 400) {
                msg = 'Valor do ano é inválido!';
            } else if (jqXHR.status === 403) {
                msg = 'Não foi possível criar o diretório!';
            } else if (jqXHR.status == 404) {
                msg = 'Requested page not found. [404]';
            } else if (jqXHR.status === 409) {
                msg = 'O diretório já existe!';
            } else if (jqXHR.status == 500) {
                msg = 'Internal Server Error [500].';
            } else {
                msg = 'Uncaught Error.\n' + jqXHR.responseText;
            }
        }
    });     
}

function conditionNOT( constraint ) {
    var condition;
    if( constraint.NOT!==undefined ) {
        condition = conditionNOT( constraint.NOT );
    } else if( constraint.AND!==undefined ) {
        condition = conditionAND( constraint.AND );
    } else if( constraint.OR!==undefined ) {
        condition = conditionOR( constraint.OR );
    } else if( constraint.XOR!==undefined ) {
        condition = conditionXOR( constraint.XOR );
    } else {
        const keys = Object.keys(constraint);
        if( $( "input[name='" + keys[0] + "']:checked" ).val() != constraint[keys[0]] )
            condition = true;
        else
            condition = false;
    }
    return condition;
}
function conditionAND( constraint ) {
    var condition;
    for( let n = 0; n < constraint.length; n++ ) {
        if( constraint[n].NOT!==undefined ) {
            condition = conditionNOT( constraint[n].NOT );
        } else if( constraint[n].AND!==undefined ) {
            condition = conditionAND( constraint[n].AND );
        } else if( constraint[n].OR!==undefined ) {
            condition = conditionOR( constraint[n].OR );
        } else if( constraint[n].XOR!==undefined ) {
            condition = conditionXOR( constraint[n].XOR );
        } else {
            const keys = Object.keys(constraint[n]);
            if( $( "input[name='" + keys[0] + "']:checked" ).val() == constraint[n][keys[0]] )
                condition = true;
            else
                condition = false;
        }
        if( condition===false )
            break;
    }
    return condition;
}
function conditionOR( constraint ) {
    var condition;
    for( let n = 0; n < constraint.length; n++ ) {
        if( constraint[n].NOT!==undefined ) {
            condition = conditionNOT( constraint[n].NOT );
        } else if( constraint[n].AND!==undefined ) {
            condition = conditionAND( constraint[n].AND );
        } else if( constraint[n].OR!==undefined ) {
            condition = conditionOR( constraint[n].OR );
        } else if( constraint[n].XOR!==undefined ) {
            condition = conditionXOR( constraint[n].XOR );
        } else {
            const keys = Object.keys(constraint[n]);
            if( $( "input[name='" + keys[0] + "']:checked" ).val() == constraint[n][keys[0]] )
                condition = true;
            else
                condition = false;
        }
        if( condition===true )
            break;
    }
    return condition;
}
function conditionXOR( constraint ) {
    var condition, count=0;
    for( let n = 0; n < constraint.length; n++ ) {
        if( constraint[n].NOT!==undefined ) {
            condition = conditionNOT( constraint[n].NOT );
        } else if( constraint[n].AND!==undefined ) {
            condition = conditionAND( constraint[n].AND );
        } else if( constraint[n].OR!==undefined ) {
            condition = conditionOR( constraint[n].OR );
        } else if( constraint[n].XOR!==undefined ) {
            condition = conditionXOR( constraint[n].XOR );
        } else {
            const keys = Object.keys(constraint[n]);
            if( $( "input[name='" + keys[0] + "']:checked" ).val() == constraint[n][keys[0]] )
                condition = true;
            else
                condition = false;
        }
        if( condition===true )
            count++;
    }
    if( count==0 || count>1 )
        condition = false;
    else
        condition = true;
    return condition;
}

function evaluateConstraint( constraint ) {
    //
    // requires upgrade to recursive evaluation
    //
    var condition = true;
    if( constraint.IF!==undefined ) {
        // single field
        const keys = Object.keys(constraint.IF);
        if( $( "input[name='" + keys[0] + "']:checked" ).val() == constraint.IF[keys[0]] )
            condition = true;
        else
            condition = false;
        // if there are more fields they are ignored
    } else if( constraint.NOT!==undefined ) {
        // NOT field
        condition = conditionNOT( constraint.NOT );
    } else if( constraint.AND!==undefined ) {
        // AND fields
        condition = conditionAND( constraint.AND );
    } else if( constraint.OR!==undefined ) {
        // OR fields
        condition = conditionOR( constraint.OR );
    } else if( constraint.XOR!==undefined ) {
        // XOR fields
        condition = conditionXOR( constraint.XOR );
    }
    return condition;
}

function checkConditions( val ) {
    if( val.date!==undefined && val.date.begin!==undefined ) {
        var begin = new Date(val.date.begin);
        if( date < begin ) return false;
    }
    if( val.date!==undefined && val.date.end!==undefined ) {
        var end = new Date(val.date.end);
        if( date > end ) return false;
    }
    if( val.open==undefined || val.open===true )
        return evaluateConstraint( val );
    return false;
}
function setupForm( setup ) {
    // Evaluate date/fields array
    $.each( setup, function (key, val) {
        if( val.date!==undefined && val.date.begin!==undefined ) {
            var date = new Date();
            var begin = new Date(val.date.begin);
            if( date < begin ) return true;
        }
        if( val.date!==undefined && val.date.end!==undefined ) {
            var date = new Date();
            var end = new Date(val.date.end);
            if( date > end ) return true;
        }
        // check conditions
        var condition = evaluateConstraint( val );
        if( condition===true )
            if( val.checkAvailability!==undefined && val.checkAvailability===true ) {
                // check availability
                getResourceAvailability(val.actions);
            } else {
                // execute actions defined
                doActions(val.actions);
            }
    });
}
//
//  Event handlers
//
function inputClickHandler( event ) {
    var value;
    value = $( "input[name='" + $(this).attr("name") + "']:checked" ).val();
    // Check if there's a click block for this radio/checkbox
    if( event.data[value]!==undefined && event.data[value].click!==undefined)
       clickHandler($(this),event.data[value].click);
}
function buttonClickHandler( event ) {
    clickHandler($(this),event.data.click);
      /*
      // Working code
      $('.btnNext').click(function() {
        const nextTabLinkEl = $('.nav-tabs .active').closest('li').next('li').find('button')[0];
        const nextTab = new bootstrap.Tab(nextTabLinkEl);
        nextTab.show();
      });
      $('.btnPrevious').click(function() {
        const prevTabLinkEl = $('.nav-tabs .active').closest('li').prev('li').find('button')[0];
        const prevTab = new bootstrap.Tab(prevTabLinkEl);
        prevTab.show();
      });
      */
}
function clickHandler( element, click ) {
//console.log(element.attr("id"));
    // Evaluate date/fields array
    $.each( click, function (key, val) {
        if( val.date!==undefined && val.date.begin!==undefined ) {
            var date = new Date();
            var begin = new Date(val.date.begin);
            if( date < begin ) return true;
        }
        if( val.date!==undefined && val.date.end!==undefined ) {
            var date = new Date();
            var end = new Date(val.date.end);
            if( date > end ) return true;
        }
        // check conditions
        var condition = evaluateConstraint( val );
        if( condition===true )
            if( val.checkAvailability!==undefined && val.checkAvailability===true ) {
                // check availability
                getResourceAvailability(val.actions);
            } else {
                // execute actions defined
                doActions(val.actions);
            }
    });
}

function doActions(val) {
    // enable
    $.each( val.enable, function (key2, val2) {
        $.each( val2, function (key3, val3) {
            var id;
            if( val3===true ) id = key3;
            else id = key3 + "." + val3;
            if( unavailableFields.includes(id)===false )
                $( '[id="' + id + '"]' ).prop("disabled", false);
        });
    });
    // check
    $.each( val.check, function (key2, val2) {
        $.each( val2, function (key3, val3) {
            var id;
            if( val3===true ) id = key3;
            else id = key3 + "." + val3;
            if( unavailableFields.includes(id)===false )
                $( '[id="' + id + '"]' ).prop("checked", true);
        });
    });
    // uncheck
    $.each( val.uncheck, function (key2, val2) {
        $.each( val2, function (key3, val3) {
            var id;
            if( val3===true ) id = key3;
            else id = key3 + "." + val3;
            $( '[id="' + id + '"]' ).prop("checked", false);
        });
    });
    // clear
    $.each( val.clear, function (key2, val2) {
        $.each( val2, function (key3, val3) {
            var id;
            if( val3===true ) id = key3;
            else id = key3 + "." + val3;
            $( '[id="' + id + '"]' ).val("");
        });
    });
    // disable
    $.each( val.disable, function (key2, val2) {
        $.each( val2, function (key3, val3) {
            var id;
            if( val3===true ) id = key3;
            else id = key3 + "." + val3;
            $( '[id="' + id + '"]' ).prop("disabled", true);
        });
    });                
    // expand
    $.each( val.expand, function (key2, val2) {
        $.each( val2, function (key3, val3) {
            var id;
            if( val3===true ) id = key3;
            else id = key3 + "." + val3;
            $( '[id="' + id + '"]' ).collapse("show");
        });
    });
    // collapse
    $.each( val.collapse, function (key2, val2) {
        $.each( val2, function (key3, val3) {
            var id;
            if( val3===true ) id = key3;
            else id = key3 + "." + val3;
            $( '[id="' + id + '"]' ).collapse("hide");
        });
    });
    // show
    $.each( val.show, function (key2, val2) {
        $.each( val2, function (key3, val3) {
            var id;
            if( val3===true ) id = key3;
            else id = key3 + "." + val3;
            $( '[id="' + id + '"]' ).removeClass("d-none");
        });
    });
    // hide
    $.each( val.hide, function (key2, val2) {
        $.each( val2, function (key3, val3) {
            var id;
            if( val3===true ) id = key3;
            else id = key3 + "." + val3;
            $( '[id="' + id + '"]' ).addClass("d-none");
        });
    });
}
//
//  Calculator functions
//
function calculateAmounts() {
    var discountAmount = 0;
    depositAmount = 0;
    totalAmount = 0;
    // process each block of the calculator
    $.each( calculator, function( key, val ) {
        price = 0;
        amounts[key] = 0;
        $.each( val, calculateBlock );
        if( prices.length > 0 ) {
            // add all elements of prices array using a reduce
            const reducer = (accumulator, curr) => accumulator + curr;
            amounts[key] = prices.reduce(reducer);
            prices = [];
        }
        if( discounts.length > 0 ) {
            // add all elements of prices array using a reduce
            const reducer = (accumulator, curr) => accumulator + curr;
            discountAmount += discounts.reduce(reducer);
            discounts = [];
        }
        if( deposits.length > 0 ) {
            // add all elements of prices array using a reduce
            const reducer = (accumulator, curr) => accumulator + curr;
            depositAmount += deposits.reduce(reducer);
            deposits = [];
        }
    });

    // prepare amounts to display
    partialAmount = 0;
    for( const key in amounts ) {
        const value = amounts[key];
        partialAmount += value;
        if( value>0 ) {
            $('#tAmounts tr[name=' + key + 'Amount] td').html(parseFloat(value).toFixed(2));
            $('#tAmounts tr[name=' + key + 'Amount]').removeClass("d-none");
        } else
            $('#tAmounts tr[name=' + key + 'Amount]').addClass("d-none");
    }
    totalAmount = partialAmount - discountAmount;
    
    if( discountAmount>0 ) {
        $('#tAmounts tr[name=partialAmount] td').html(parseFloat(partialAmount).toFixed(2));
        $('#tAmounts tr[name=discountAmount] td').html(parseFloat(discountAmount).toFixed(2));
        $('#tAmounts tr[name=partialAmount]').removeClass("d-none");
        $('#tAmounts tr[name=discountAmount]').removeClass("d-none");
    } else {
        $('#tAmounts tr[name=partialAmount]').addClass("d-none");
        $('#tAmounts tr[name=discountAmount]').addClass("d-none");
    }
    $('#tAmounts tr[name=totalAmount] td').html(parseFloat(totalAmount).toFixed(2));
    $('span[name=totalAmount]').html(parseFloat(totalAmount).toFixed(2));
    $('#tAmounts tr[name=depositAmount] td').html(parseFloat(depositAmount).toFixed(2));
    $("#packTotalAmount").text(packTotalAmount);
    $("#packDepositAmount").text(packDepositAmount);
    // update min and max of other amount field
    $('#t_PaymentAmount').prop('min', parseFloat(depositAmount).toFixed(2));
    $('#t_PaymentAmount').prop('max', parseFloat(totalAmount).toFixed(2));
    $('#t_PaymentAmount').prop('placeholder', "Entre " + parseFloat(depositAmount).toFixed(2) + " e " + parseFloat(totalAmount).toFixed(2));
}

function calculateBlock(key, val) {
    $.each( val, function (key2, val2) {
        // initialize discount
        discount=0;
        var id = key + "." + key2;
        if( $( '[id="' + id + '"]' ).prop("checked") ) {
            if( val2.price!==undefined ) {
                // there's a price block so iterate each element of price array to get the best amount
                smallestAmount= Number.MAX_SAFE_INTEGER;
                biggestAmount = 0;
                $.each( val2.price, getBlockAmount );
                if( smallestAmount < Number.MAX_SAFE_INTEGER ) {
                    price = smallestAmount
                    prices.push( price );
                }
            }
            if( val2.discount!==undefined && price>0 ) {
                // there's a discount block so iterate each element of discount array to get the best amount
                smallestAmount= Number.MAX_SAFE_INTEGER;
                biggestAmount = 0;
                $.each( val2.discount, getBlockAmount );
                if( biggestAmount > 0 ) {
                    discount = biggestAmount;
                    discounts.push( discount );
                }
            }
            if( val2.deposit!==undefined && price>0 ) {
                // there's a deposits block so iterate each element of deposits array to get the best amount
                smallestAmount= Number.MAX_SAFE_INTEGER;
                biggestAmount = 0;
                $.each( val2.deposit, getBlockAmount );
                if( biggestAmount > 0 ) {
                    deposit = biggestAmount;
                    deposits.push( biggestAmount );
                }
            }
        }
    });
}

function getBlockAmount(key, val) {
    // Evaluate date/fields array
    if( val.date!==undefined && val.date.begin!==undefined ) {
        var date = new Date();
        var begin = new Date(val.date.begin);
        if( date < begin ) return;
    }
    if( val.date!==undefined && val.date.end!==undefined ) {
        var date = new Date();
        var end = new Date(val.date.end);
        if( date > end ) return;
    }
    if( val.open!==undefined && val.open===false ) {
        return;
    }
    // check conditions
    var condition = evaluateConstraint( val );
    if( condition===true) {
        // get amount from current block if it's lower than the best amount from the previous blocks
        if( val.amount!==undefined && smallestAmount>val.amount)
            smallestAmount = val.amount;
        else if( val.percentage!==undefined && smallestAmount>(val.percentage * (price-discount) / 100) )
            smallestAmount = val.percentage * (price-discount) / 100;
        // get amount from current block if it's lower than the best amount from the previous blocks
        if( val.amount!==undefined && biggestAmount<val.amount)
            biggestAmount = val.amount;
        else if( val.percentage!==undefined && biggestAmount<(val.percentage * (price-discount) / 100) )
            biggestAmount = val.percentage * (price-discount) / 100;
    }
}
