var objStepsData;
var loadStatus = 0;
var correctionIndex = 10;
var s1Validator = null;
var s5Validator = null;
var s4Validator = null;
var s1_DatePicker = null;

var mapBounds = null;
var mapCenter = null;
var mapZoom = null;
var directionsPolyline = null;
var directions;
var waypoints = [];
var map;

/// DATE FROMAT PROTOTYPE FUNCTION (  EXTERNAL )
/// usage - http://jacwright.com/projects/javascript/date_format
Date.prototype.format = function (format) { var returnStr = ''; var replace = Date.replaceChars; for (var i = 0; i < format.length; i++) { var curChar = format.charAt(i); if (replace[curChar]) { returnStr += replace[curChar].call(this); } else { returnStr += curChar; } } return returnStr; }; Date.replaceChars = { shortMonths: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], longMonths: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], shortDays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], longDays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], d: function () { return (this.getDate() < 10 ? '0' : '') + this.getDate(); }, D: function () { return Date.replaceChars.shortDays[this.getDay()]; }, j: function () { return this.getDate(); }, l: function () { return Date.replaceChars.longDays[this.getDay()]; }, N: function () { return this.getDay() + 1; }, S: function () { return (this.getDate() % 10 == 1 && this.getDate() != 11 ? 'st' : (this.getDate() % 10 == 2 && this.getDate() != 12 ? 'nd' : (this.getDate() % 10 == 3 && this.getDate() != 13 ? 'rd' : 'th'))); }, w: function () { return this.getDay(); }, z: function () { return "Not Yet Supported"; }, W: function () { return "Not Yet Supported"; }, F: function () { return Date.replaceChars.longMonths[this.getMonth()]; }, m: function () { return (this.getMonth() < 11 ? '0' : '') + (this.getMonth() + 1); }, M: function () { return Date.replaceChars.shortMonths[this.getMonth()]; }, n: function () { return this.getMonth() + 1; }, t: function () { return "Not Yet Supported"; }, L: function () { return "Not Yet Supported"; }, o: function () { return "Not Supported"; }, Y: function () { return this.getFullYear(); }, y: function () { return ('' + this.getFullYear()).substr(2); }, a: function () { return this.getHours() < 12 ? 'am' : 'pm'; }, A: function () { return this.getHours() < 12 ? 'AM' : 'PM'; }, B: function () { return "Not Yet Supported"; }, g: function () { return this.getHours() % 12 || 12; }, G: function () { return this.getHours(); }, h: function () { return ((this.getHours() % 12 || 12) < 10 ? '0' : '') + (this.getHours() % 12 || 12); }, H: function () { return (this.getHours() < 10 ? '0' : '') + this.getHours(); }, i: function () { return (this.getMinutes() < 10 ? '0' : '') + this.getMinutes(); }, s: function () { return (this.getSeconds() < 10 ? '0' : '') + this.getSeconds(); }, e: function () { return "Not Yet Supported"; }, I: function () { return "Not Supported"; }, O: function () { return (this.getTimezoneOffset() < 0 ? '-' : '+') + (this.getTimezoneOffset() / 60 < 10 ? '0' : '') + (this.getTimezoneOffset() / 60) + '00'; }, T: function () { return "Not Yet Supported"; }, Z: function () { return this.getTimezoneOffset() * 60; }, c: function () { return "Not Yet Supported"; }, r: function () { return this.toString(); }, U: function () { return this.getTime() / 1000; } };
///

//#region wayPointDataMask
var wayPointDataMask = {
    subRouteTime: 0,
    address: '',
    street: '',
    zipcode: '',
    country: '',
    city: '',
    lat: '',
    lng: '',
    delayData: {},
    departureDate: null,
    passengers: {},
    passengersDelta: {},
    passengersSumm: null
};
//#endregion

//#region waypoint
function waypoint() {
    this.subRouteTime = 0; //  miliseconds
    this.address = '';
    this.street = '';
    this.zipcode = '';
    this.country = '';
    this.city = '';
    this.lat = '';
    this.lng = '';
    this.delayTime = function () {
        return daysHoursMinutesStructToMS(this.delayData);
    };   // delay time in miliseconds
    this.delayData = {
        days: 0,
        hours: 0,
        minutes: 0
    };
    this.departureDate = null; //datetime
    this.passengersDelta = {
        old: { _in: 0,
            _out: 0
        },
        adult: { _in: 0,
            _out: 0
        },
        children: { _in: 0,
            _out: 0
        }
    };

    this.passengers = {
        old: 0,
        adult: 0,
        children: 0
    };
    this.passengersSumm = function () {
        return this.passengers.adult * 1 + this.passengers.children * 1; //according to task #129 this is removed + (this.passengers.old * ((excludeOld) ? 0 : 1));
    };
}
//#endregion

//#region inputParams
var inputParams = {
    busGUID: '8ac80fed-67a4-4423-bd3f-e38d409ed38b',
    isPresent: false,
    adult: 0,
    departure: null,
    isCruis: false,
    from: '',
    to: '',
    busNo: ''
};
//#endregion

//#region isValidEAN(barcode)  -- barcode must be STRING
function isValidEAN(barcode) {
    function checkEAN13(s) {
        var checksum = parseInt(s.charAt(12), 10);
        var sum = 0;
        for (var i = 0; i < 12; i++) {
            sum += parseInt(s.charAt(i), 10) * (i % 2 === 0 ? 1 : 3);
        }

        var ourChecksum = 10 - (sum % 10);
        if (ourChecksum === 10) {
            ourChecksum = 0;
        }
        return ourChecksum === checksum;
    }

    function checkEAN8(s) {
        var checksum = parseInt(s.charAt(7), 10);
        var sum = 0;
        for (var i = 0; i < 7; i++) {
            sum += parseInt(s.charAt(i), 10) * (i % 2 === 0 ? 3 : 1);
        }
        var ourChecksum = 10 - (sum % 10);
        if (ourChecksum === 10) {
            ourChecksum = 0;
        }
        return ourChecksum === checksum;
    }

    if (barcode.length === 13) {
        return checkEAN13(barcode);
    } else if (barcode.length === 8) {
        return checkEAN8(barcode);
    } else if (barcode.length === 0) {
        return true;
    } else {
        return false;
    }
}
//#endregion

// this variables are declared in XSLT script
//    var OB_EnterPhone = "Venligst indtast telefon numer";
//    var OB_IncorrectPhone = "Incorrect phone format";
//    var OB_IncorrectMail = "Indtast venligst email korrekt";
//    var OB_RequiredField = "Dette felt skal udfyldes";
//    var OB_Numeric = "Venligts indtast et tal";

//#region Validator(vIds)
function Validator(vIds) {
    this.valData = vIds;

    // ACCEPTABLE PHONE FORMAT 339-4248 || 339-42-48 || 339 42 48 || 339 4248 || 3394248
    //              (095) #phone# || (095)#phone# || +7 (095) #phone# || +7 (095)#phone# || +7(095) #phone# || +7(095)#phone#

    this.regExInd = {
        isPhoneEntered: { expr: /\S/, message: OB_EnterPhone }, //Please enter phone number
        isPhone: { expr: /^(\+\d)*\s*(\(\d{1,4}\)\s*)*\d{1,5}(-{0,1}|\s{0,1})\d{1,3}(-{0,1}|\s{0,1})\d{1,3}$/, message: OB_IncorrectPhone },
        isEmail: { expr: /^\s*[\w\-\+_]+(\.[\w\-\+_]+)*\@[\w\-\+_]+\.[\w\-\+_]+(\.[\w\-\+_]+)*\s*$/, message: OB_IncorrectMail }, //incorrect email format
        isEmpty: { expr: /\S/, message: OB_RequiredField }, //this field is required
        isNumber: { expr: /^\s*\d+\s*$/, message: OB_Numeric} //must be numeric
    };

    this.checkRegExp = function (elObj, regExind) {
        var value = elObj.val();
        if (String(value).search(this.regExInd[regExind].expr) == -1) {
            return false;
        }
        return true;
    };

    this.validateAll = function () {
        var allValid = true;
        for (var key in this.valData) {
            if (!this.validate(key)) {
                allValid = false;
            }
        }
        return allValid;
    };

    this.validate = function (id) {
        var valTypes = this.valData[id].split(',');
        if (valTypes.length > 0) {
            for (var i = 0; i < valTypes.length; i++) {
                var regExpKey = trim(valTypes[i], ' ');
                if (!this.checkRegExp($('#' + id), regExpKey)) {
                    this.showValidateMessage(id, this.regExInd[regExpKey].message);
                    return false;
                } else {
                    this.showValidateMessage(id, '');
                }
            }
            return true;
        }
        return false;
    };

    this.showValidateMessage = function (id, validationMessage) {
        if (trim(validationMessage, ' ') != '') {
            $('label[for=' + id + ']').show().html(validationMessage);
        } else {
            $('label[for=' + id + ']').hide().html(validationMessage);
        }
    };
}
//#endregion

//#region string trims
function trim(str, chars) {
    return ltrim(rtrim(str, chars), chars);
}

function ltrim(str, chars) {
    chars = chars || "\\s";
    return str.replace(new RegExp("^[" + chars + "]+", "g"), "");
}

function rtrim(str, chars) {
    chars = chars || "\\s";
    return str.replace(new RegExp("[" + chars + "]+$", "g"), "");
}
//#endregion

//#region StepsData()
function StepsData() {
    this.currentStep = 0;
    this.wayPointsChanged = false;
    this.data = {
        orderedServices: [],
        ClientData: {
            name: "",
            addresse: "",
            houseNum: "",
            postNr: 0,
            city: "",
            country: "",
            countryCode: "",
            phone: "",
            mobile: "",
            email: "",
            client: "",
            EAN: ""
        },
        busTypeGUID: 0,
        busType: '',
        serviceProducts: {},
        subscribedForNews: true,
        wayPoints: [],
        departureTime: null, //DateTime
        busNo: ''
    };

    this.getWayPointMaxDelta = function (ind, type) { //types = {'old', 'adult', 'children'}
        var maxDelta = this.data.wayPoints[0].passengers[type] * 1;
        for (var i = 1; i <= ind; i++) {
            maxDelta += this.data.wayPoints[i].passengersDelta[type]['_in'] * 1 - this.data.wayPoints[i].passengersDelta[type]['_out'] * 1;
        }
        return maxDelta; //current count of passengers of selected type and for the current wayPoint on boart
    };

    this.totalTime = function () {
        var res = 0;
        for (var i = 1; i < this.data.wayPoints.length; i++) {
            res += this.data.wayPoints[i].subRouteTime + this.data.wayPoints[i - 1].delayTime();
        }
        return res; //miliseconds
    };

    // returns value of arrive with seconds set to 0
    this.wayPointArriveDate = function (index) {
        var res = 0;
        for (var i = 1; i <= index; i++) {
            res += this.data.wayPoints[i].subRouteTime + this.data.wayPoints[i - 1].delayTime();
        }
        var date = new Date(this.data.departureTime.getTime() + res);
        date.setSeconds(0);
        return date; //Date obj
    };

    // returns value with seconds set to 0
    this.wayPointDepartureDate = function (index) {
        var date = new Date(this.wayPointArriveDate(index).getTime() + this.data.wayPoints[index].delayTime());
        date.setSeconds(0);
        return date; //Date obj
    };

    // returns value with seconds set to 0
    this.arriveTime = function () {
        var tmpDate = new Date(this.data.departureTime.getTime() + this.totalTime());
        tmpDate.setSeconds(0);
        return tmpDate; // DateTime
    };
}
//#endregion

//#region createDataObject()
function createDataObject() {
    var dataObject = {};
    var key;
    for (key in objStepsData.data) {
        dataObject[key] = objStepsData.data[key];
    }

    dataObject.wayPoints = [];
    for (var i = 0; i < objStepsData.data.wayPoints.length; i++) {
        dataObject.wayPoints[i] = {};
        for (key in wayPointDataMask) {
            dataObject.wayPoints[i][key] = objStepsData.data.wayPoints[i][key];
        }
        // set functions values
        dataObject.wayPoints[i]['wayPointArriveDate'] = objStepsData.wayPointArriveDate(i);
        dataObject.wayPoints[i]['wayPointDepartureDate'] = objStepsData.wayPointDepartureDate(i);
    }
    var paymentType = $("input:radio[name='paymentType']:checked");

    // set functions values
    dataObject.totalTime = objStepsData.totalTime();
    dataObject.arriveTime = objStepsData.arriveTime();
    dataObject.paymentTypeId = paymentType.val();
    //dataObject.paymentTypeText = paymentType.next().html();
    return dataObject;
}
//#endregion

$(function () {
    //init data object
    objStepsData = new StepsData();

    // init UI
    readInputData();

    initBusTypeSelectors();
    initTabs();
    refreshTabs();
    initNavigationButtons();

    $('.headerTextBlockLink').click(function () {
        $(this).next().toggle();
    });
});

//#region initBusTypeSelectors()
function initBusTypeSelectors() {
    if (inputParams.busGUID == '') {
        if ($('input[name=BUSNAME]').length > 0) {
            objStepsData.data.busTypeGUID = $($('input[name=BUSNAME]')[0]).attr('id').split('_')[1];
            objStepsData.data.busType = $($('input[name=BUSNAME]')[0]).val();
            $('#BUSTYPE_' + objStepsData.data.busTypeGUID).attr('checked', 'checked');
        }
    } else {
        $('#BUSTYPE_' + inputParams.busGUID).attr('checked', 'checked');
        objStepsData.data.busTypeGUID = inputParams.busGUID.toUpperCase();
        objStepsData.data.busType = $('#BUSNAME_' + inputParams.busGUID).val();
    }
}
//#endregion

//#region readInputData()
function readInputData() {
    var str = window.location + ' ';
    if (str.indexOf('?') > -1) {
        for (var key in inputParams) {
            if (getQueryParameter(key) != '')
                inputParams[key] = decodeURI(getQueryParameter(key));
        }
        inputParams.adult = isNaN(inputParams.adult) ? 0 : inputParams.adult * 1;
        inputParams.isPresent = true;
        inputParams.isCruis = inputParams.isCruis * 1;
        inputParams.departure = new Date(inputParams.departure);
        inputParams.busGUID = inputParams.busGUID.toLowerCase();
        objStepsData.data.busNo = inputParams.busNo;
    }
}
//#endregion

// first letter 'A' code is 0
//#region getAlfaUppercaseCharByCode(code)
function getAlfaUppercaseCharByCode(code) {
    var firstSymbol = 'A';
    var symbolOffset = firstSymbol.charCodeAt(0);
    return String.fromCharCode(symbolOffset + code);
}
//#endregion

//those variables will be generated by XSLT script
//var OB_FinishBuildOfRoute = "Sammensæt venligst den ønskede rute før du går videre.";
//var OB_NeedMoreWayPoints = "Du skal minimum have 2 destinationer, fra og til. Her hedder de henholdsvis A & B. Vent herefter på at rute bliver genereret.";
//var OB_PassengersCount = "Du skal vælge hvor mange personer der skal transporteres. Der skal være flere end 0.";
//var OB_PassengersPlaningError = {
//    msg1: "You have left unplanned bus places: \n",
//    itemStart: '\t - ',
//    of: ' of ',
//    itemEnd: ' places.\n',
//    msg2: 'Please handle this to proceed.'
//};

//#region validateAndGetStepData(stepIndex)
function validateAndGetStepData(stepIndex) {
    stepIndex = stepIndex * 1;
    var isValid = true;
    switch (stepIndex) {
        case 0:
            if (!s1Validator.validateAll()) {
                isValid = false;
            }

            if (objStepsData.wayPointChanged) {
                isValid = false;
                alert(OB_FinishBuildOfRoute); //"First finish building route."
            }

            if (objStepsData.data.wayPoints.length <= 1) {
                isValid = false;
                alert(OB_NeedMoreWayPoints); //"You have to choose at least 2 waypoints. And wait until route has been generetaed."
            } else {

                for (var key in objStepsData.data.wayPoints[0].passengers) {
                    for (var ind1 = 0; ind1 < objStepsData.data.wayPoints.length - 1; ind1++) {
                        var value = 0;
                        if (ind1 === 0) {
                            value = $('#' + key + '_s1').val() * 1;
                            objStepsData.data.wayPoints[ind1].passengers[key] = value;
                        }
                        objStepsData.data.wayPoints[ind1].passengersDelta[key]._in = value;
                        objStepsData.data.wayPoints[ind1].passengersDelta[key]._out = 0;
                    }
                }
            }
            if (isValid && (objStepsData.data.wayPoints[0].passengersSumm() == 0)) {
                isValid = false;
                alert(OB_PassengersCount); //"Count of passengers can't be 0."
            }
            if (isValid) {
                var firstStepData = $('#' + $('.stepItem.current').attr('data_id'));
                if (objStepsData.data.wayPoints[1].passengersSumm() == 0) { //if it is first time ...
                    for (var i = 1; i < objStepsData.data.wayPoints.length; i++) {
                        objStepsData.data.wayPoints[i].passengers.old = objStepsData.data.wayPoints[0].passengers.old;
                        objStepsData.data.wayPoints[i].passengers.children = objStepsData.data.wayPoints[0].passengers.children;
                        objStepsData.data.wayPoints[i].passengers.adult = objStepsData.data.wayPoints[0].passengers.adult;
                    }
                }

                var dateStr = $('#s1_dateSelect').val();
                var separatorPos = dateStr.indexOf("/");
                var day = dateStr.substr(0, separatorPos);
                dateStr = dateStr.substr(separatorPos + 1, dateStr.length - separatorPos);
                separatorPos = dateStr.indexOf("/");
                var month = dateStr.substr(0, separatorPos);
                dateStr = dateStr.substr(separatorPos + 1, dateStr.length - separatorPos);
                var year = dateStr;

                objStepsData.data.departureTime = new Date(year, month - 1, day);
                objStepsData.data.departureTime.setHours($('#hours').val() * 1);
                objStepsData.data.departureTime.setMinutes($('#minutes').val() * 1);
                var arriveTime = objStepsData.arriveTime();
            }
            break;

        case 1:
            errorString = OB_PassengersPlaningError.msg1;
            for (var key in objStepsData.data.wayPoints[0].passengers) {
                var str = $('#' + key + '_left').html();
                if (str != '') {
                    isValid = false;
                    errorString += OB_PassengersPlaningError.itemStart +
                                    str + OB_PassengersPlaningError.of +
                                    key + OB_PassengersPlaningError.itemEnd;
                }
            }
            errorString += OB_PassengersPlaningError.msg2;
            if (!isValid) {
                alert(errorString);
            }
            break;

        case 2:
            //all data auto updated in eventhandlers
            //no need validation
            break;

        case 3:
            // no validation needed to proceed
            break;

        case 4:
            break;
    }
    return isValid;
}
//#endregion

//#region setupPassengersInSelectors()
function setupPassengersInSelectors() {
    for (var i = 0; i < objStepsData.data.wayPoints.length - 1; i++) {
        for (var key in objStepsData.data.wayPoints[i].passengersDelta) {
            var optionsHtml = '';
            var maxIndex = objStepsData.data.wayPoints[0].passengers[key];

            for (var subInd = 0; subInd < objStepsData.data.wayPoints.length - 1; subInd++) {
                if (subInd != i) {
                    maxIndex -= objStepsData.data.wayPoints[subInd].passengersDelta[key]._in;
                }
            }
            var selectedIndex = objStepsData.data.wayPoints[i].passengersDelta[key]._in;

            for (var indx = 0; indx <= maxIndex; indx++) {
                optionsHtml += "<option value='" + indx + "' " + (selectedIndex == indx ? "selected = true>" : ">") + indx + "</option>";
            }
            $('#' + key + "_in_" + i).find('option').remove();
            $('#' + key + "_in_" + i).append($(optionsHtml));
        }
    }
}
//#endregion

//#region setupPassengersOutSelectors()
function setupPassengersOutSelectors() {
    var summIn = { old: 0, adult: 0, children: 0 };
    var summOut = { old: 0, adult: 0, children: 0 };
    for (var i = 0; i < objStepsData.data.wayPoints.length - 1; i++) {
        for (var key in objStepsData.data.wayPoints[i].passengersDelta) {
            if (i != 0) {
                var optionsHtml = '';
                var maxIndex = summIn[key] - summOut[key];
                var selectedIndex = objStepsData.data.wayPoints[i].passengersDelta[key]._out;
                if (selectedIndex > maxIndex) {
                    selectedIndex = maxIndex;
                    objStepsData.data.wayPoints[i].passengersDelta[key]._out = maxIndex;
                }
                for (var indx = 0; indx <= maxIndex; indx++) {
                    optionsHtml += "<option value='" + indx + "' " + (selectedIndex == indx ? "selected = true>" : ">") + indx + "</option>";
                }
                $('#' + key + "_out_" + i).find('option').remove();
                $('#' + key + "_out_" + i).append($(optionsHtml));
                summOut[key] += selectedIndex * 1;
            }
            summIn[key] += objStepsData.data.wayPoints[i].passengersDelta[key]._in * 1;
        }
    }
}
//#endregion

//#region updatePassengersValidationText()
function updatePassengersValidationText() {
    for (var key in objStepsData.data.wayPoints[0].passengersDelta) {
        var summIn = 0;
        for (var i = 0; i < objStepsData.data.wayPoints.length - 1; i++) {
            summIn += objStepsData.data.wayPoints[i].passengersDelta[key]._in * 1;
        }
        if (objStepsData.data.wayPoints[0].passengers[key] * 1 != summIn * 1) {
            $('#' + key + '_left').html(" [ + " + (objStepsData.data.wayPoints[0].passengers[key] * 1 - summIn * 1) + " ] ");
        } else {
            $('#' + key + '_left').html("");
        }
    }
}
//#endregion

//*XSLT
//var OB_Passing = "1. Via: ";
//var OB_PlaningOfPassengers = "Planlæg af og påstigning";
//var OB_TimeSetup = "Opholdstid eller afrejsetidspunkt";
//var OB_Persons = "Personer der stiger på";
//var OB_AdultTitle = "Voksne:";
//var OB_ChildrenTitle = "Børn:";
//var OB_WheelchearTitle = "Kørstole:";
//var OB_Hold = "Ophold:";
//var OB_dayTitle = "dage:";
//var OB_hoursTitle = "timer:";
//var OB_minutesTitle = "minutter:";
//var OB_Time = "klokken:";

//#region getWayPointHTMLObj(index)
function getWayPointHTMLObj(index) {
    var htmlTemplate = "<div class='wayPointItem'><div class='letter'>B</div><div class='content'>" +
     "<div class='infoBar'>" + OB_Passing + "<span></span></div>" +
    "</div><div class='content'><div class='leftPanel '><span class='labelItem'>" +
    OB_PlaningOfPassengers +
    "</span></div><div class='rightPanel '><span class='labelItem'>" + OB_TimeSetup +
    "</span></div><div class='leftPanel'><div class='passengersIn'><div class='editRow'>" + OB_Persons +
    "</div><div class='editRow bottomR'><span>" + OB_AdultTitle + "</span><select id='adult_in_'></select><span>" + OB_ChildrenTitle +
    "</span><select id='children_in_'></select><span>" + OB_WheelchearTitle +
    "</span><select id='old_in_'></select></div></div></div><div class='rightPanel'><div class='waitEditRow'><div class='centeredCell'>" +
    "<input id='hold' class='holdEdit' type='radio' name='waitType_2' /></div><div class='centeredCell'>" + OB_Hold +
    "</div><div class='cellSpacer'></div><div class='chooseCell'>" +
    "<div class='topBlock'><span>" + OB_dayTitle + "</span></div><div class='bottomBlock'><select id='days_wait'></select></div></div><div class='chooseCell'>" +
    "<div class='topBlock'><span>" + OB_hoursTitle + "</span></div><div class='bottomBlock'><select id='hours_wait'></select></div></div><div class='chooseCell'>" +
    "<div class='topBlock'><span>" + OB_minutesTitle + "</span></div><div class='bottomBlock'><select id='minutes_wait'></select></div></div></div>" +
    "</div><div class='leftPanel'>" +
    "<div class='passengersOut'><div class='editRow'>" + OB_PersonsOut + "</div><div class='editRow bottomR'><span>" + OB_AdultTitle +
    "</span><select id='adult_out_'></select><span>" + OB_ChildrenTitle +
    "</span><select id='children_out_'></select><span>" + OB_WheelchearTitle +
    "</span><select id='old_out_'></select></div></div>" +
    "</div><div class='rightPanel'><div class='moveOutEditRow'><div class='centeredCell'><input id='departure' type='radio' class='moveOutEdit'/></div>" +
    "<div class='centeredCell'>Afrejse:</div><div class='cellSpacer'></div><div class='chooseCell'><div class='topBlock'><span>dato:</span></div>" +
    "<div class='bottomBlock'><select id='day_ind'></select></div></div><div class='chooseCell'><div class='topBlock spacer'></div><div class='bottomBlock'>" +
    "<select id='month_ind'></select></div></div><div class='chooseCell'><div class='topBlock spacer'></div><div class='bottomBlock'><select id='year_ind'>" +
    "</select></div></div><div class='chooseCell'><div class='topBlock'>" + OB_Time + ":</div><div class='bottomBlock'><select id='hours_ind'>" +
    //"</select></div></div><div class='cellSpacer'></div><div class='chooseCell'><div class='topBlock'>" + OB_Time + ":</div><div class='bottomBlock'><select id='hours_ind'>" +
    "</select></div></div><div class='chooseCell'><div class='topBlock spacer'></div><div class='bottomBlock'><select id='minutes_ind'></select>" +
    "</div></div></div></div></div></div>";


    var wayPointObj = $(htmlTemplate);


    //letter insert
    wayPointObj.find('.infoBar span').html(objStepsData.data.wayPoints[index].address);
    wayPointObj.find('.letter').html(getAlfaUppercaseCharByCode(index));
    var selectors = wayPointObj.find('.passengersOut select');
    for (var i = 0; i < selectors.length; i++) {
        $(selectors[i]).attr('id', $(selectors[i]).attr('id') + index);
    }
    selectors = wayPointObj.find('.passengersIn select');
    for (var i = 0; i < selectors.length; i++) {
        $(selectors[i]).attr('id', $(selectors[i]).attr('id') + index);
    }

    wayPointObj.find('.waitEditRow').attr('id', 'waitEditRow_' + index);
    wayPointObj.find('.moveOutEditRow').attr('id', 'moveOutEditRow_' + index);

    var hold_selects = wayPointObj.find('#waitEditRow_' + index + ' select');
    var _i = 0;
    for (var key in objStepsData.data.wayPoints[index].delayData) {
        $(hold_selects[_i]).attr('id', 'hold_' + key + '_' + index).change(function () {
            var info = $(this).attr('id').split('_');
            objStepsData.data.wayPoints[info[2]].delayData[info[1]] = $(this).val() * 1;
            for (var item = info[2]; item < objStepsData.data.wayPoints.length - 1; item++) {
                var moveOutDateSelectors = $('#moveOutEditRow_' + item + ' select');
                updateMoveOutDateSelectors(false, moveOutDateSelectors, item);
            }
            updateArriveTimeInLastWayPoint();
        });
        _i++;
    }



    wayPointObj.find('.holdEdit').attr('checked', 'checked');
    wayPointObj.find('.waitEditRow select').removeAttr('disabled');
    wayPointObj.find('#hold').attr('name', 'waitType_2_' + index).attr('id', 'sel_waitEditRow_moveOutEditRow_' + index);
    wayPointObj.find('#departure').attr('name', 'waitType_2_' + index).attr('id', 'sel_moveOutEditRow_waitEditRow_' + index);
    wayPointObj.find('.moveOutEditRow select').attr('disabled', 'disabled');
    wayPointObj.find('input[type=radio]').change(function () {
        if (this.checked) {
            var info = $(this).attr('id').split('_');
            $('#' + info[1] + '_' + info[3] + ' select').removeAttr('disabled');
            $('#' + info[2] + '_' + info[3] + ' select').attr('disabled', 'disabled');
        }
    });

    var moveOutDateSelectors = wayPointObj.find('#moveOutEditRow_' + index + ' select');
    updateMoveOutDateSelectors(true, moveOutDateSelectors, index);

    return wayPointObj;
}
//#endregion

//#region msToDaysHoursMinutesStruct(ms)
function msToDaysHoursMinutesStruct(ms) {
    // 86400000 = 24*60*60*1000 - ONE DAY
    // 3600000 = 60*60*1000 - ONE HOUR
    // 60 000 = 60*1000 - ONE MINUTE
    var res = {};
    res['days'] = Math.floor(ms / (86400000));
    res['hours'] = Math.floor((ms - (res['days'] * 86400000)) / 3600000);
    res['minutes'] = Math.floor((ms - ((3600000 * res['hours']) + (res['days'] * 86400000))) / 60000);
    return res;
}
//#endregion

function daysHoursMinutesStructToMS(data) {
    return data['days'] * 86400000 + data['hours'] * 3600000 + data['minutes'] * 60000;
}

//var OB_DepartureTime = "Afrejse herfra d."; *XSLT

//#region updateArriveTimeInLastWayPoint()
function updateArriveTimeInLastWayPoint() {
    var arriveDateObj = objStepsData.arriveTime();
    var aYear = arriveDateObj.getFullYear() - 2000;
    var aMonth = arriveDateObj.getMonth() + 1;
    var aDay = arriveDateObj.getDate();
    var aMinutes = arriveDateObj.getMinutes();
    var aHours = arriveDateObj.getHours();

    $('.infoRow.last').html(OB_DepartureTime + ' ' + getLeadingZeroNum(aDay) + '/' +
                                                getLeadingZeroNum(aMonth) + '/' +
                                                getLeadingZeroNum(aYear) + ' ' + OB_Time +
                                                getLeadingZeroNum(aHours) + ':' +
                                                getLeadingZeroNum(aMinutes));
}
//#endregion

//#region updateHoldTimeSelectors(index)
function updateHoldTimeSelectors(index) {
    var optMaxVal = {
        days: 100,
        hours: 23,
        minutes: 59
    };
    for (var key in objStepsData.data.wayPoints[index].delayData) {
        var optionsHtml = "";
        for (var cv = 0; cv <= optMaxVal[key]; cv++) {
            optionsHtml += "<option value = '" +
                        cv +
                        "' " +
                        ((cv == objStepsData.data.wayPoints[index].delayData[key]) ? "selected = true" : "") +
                        " >" +
                        getLeadingZeroNum(cv) + "</option>";
        }
        $('#hold_' + key + '_' + index).find('option').remove();
        $('#hold_' + key + '_' + index).append($(optionsHtml));
    }

    updateArriveTimeInLastWayPoint();
}
//#endregion

//#region updateMoveOutDateSelectors(isFirstUpdate, selectors, index)
function updateMoveOutDateSelectors(isFirstUpdate, selectors, index) {
    var departureDateObj = objStepsData.wayPointDepartureDate(index);
    var arriveDateObj = objStepsData.wayPointArriveDate(index);

    var arriveDate = {
        Day: arriveDateObj.getDate(),
        Month: arriveDateObj.getMonth() + 1,
        Year: arriveDateObj.getFullYear() - 2000,
        Hour: arriveDateObj.getHours(),
        Minutes: arriveDateObj.getMinutes()
    };

    var departureDate = {
        Day: departureDateObj.getDate(),
        Month: departureDateObj.getMonth() + 1,
        Year: departureDateObj.getFullYear() - 2000,
        Hour: departureDateObj.getHours(),
        Minutes: departureDateObj.getMinutes()
    };

    var departureDateMinValues = {
        Day: 1,
        Month: 1,
        Year: new Date().getFullYear() - 2000,
        Hour: 0,
        Minutes: 0
    };

    var departureDateMaxValues = {
        Day: daysInMonth(departureDate.Month, departureDate.Year + 2000),
        Month: 12,
        Year: 99,
        Hour: 23,
        Minutes: 59
    };

    var i = 0;
    for (var key in departureDate) {
        var maxInd = departureDateMaxValues[key];
        var minInd = departureDateMinValues[key];
        if (isFirstUpdate) {
            minInd = arriveDate[key];
        } else {
            if (departureDate.Year == arriveDate.Year) {
                departureDateMinValues['Month'] = arriveDate.Month;
                if (departureDate.Month == arriveDate.Month) {
                    departureDateMinValues['Day'] = arriveDate.Day;
                    if (departureDate.Day == arriveDate.Day) {
                        departureDateMinValues['Hour'] = arriveDate.Hour;
                        if (departureDate.Hour == arriveDate.Hour) {
                            departureDateMinValues['Minutes'] = arriveDate.Minutes;
                        }
                    }
                }
            }
            var maxInd = departureDateMaxValues[key];
            var minInd = departureDateMinValues[key];
        }

        var optionsHtml = '';
        for (var ind = minInd; ind <= maxInd; ind++) {
            optionsHtml += "<option value = '" + ind + "' " + (ind == departureDate[key] * 1 ? "selected=true" : "") + " >" + getLeadingZeroNum(ind) + "</option>";
        }
        $(selectors[i]).find('option').remove();
        if (isFirstUpdate) $(selectors[i]).attr('id', key + '_' + index).change(function () {
            var info = $(this).attr('id').split('_');
            var index = info[1] * 1;

            var dateTmpObj = {
                day: $('#Day_' + index).val() * 1,
                month: $('#Month_' + index).val() * 1,
                year: $('#Year_' + index).val() * 1,
                hour: $('#Hour_' + index).val() * 1,
                minute: $('#Minutes_' + index).val() * 1
            };

            switch (info[0]) {
                case 'Year':
                    dateTmpObj['minute'] = 0;
                    dateTmpObj['hour'] = 0;
                    dateTmpObj['day'] = 1;
                    dateTmpObj['month'] = 1;
                    break;

                case 'Month':
                    dateTmpObj['minute'] = 0;
                    dateTmpObj['hour'] = 0;
                    dateTmpObj['day'] = 1;
                    break;

                case 'Day':
                    dateTmpObj['minute'] = 0;
                    dateTmpObj['hour'] = 0;
                    break;

                case 'Hour':
                    dateTmpObj['minute'] = 0;
                    break;
            }

            var composedDate = new Date(dateTmpObj.year + 2000, dateTmpObj.month - 1, dateTmpObj.day, dateTmpObj.hour, dateTmpObj.minute, 0);
            composedDate.setMilliseconds(0);
            var arriveT = objStepsData.wayPointArriveDate(index);
            arriveT.setMilliseconds(0);
            var delta = composedDate.getTime() - arriveT.getTime();
            var tmp = new Date(delta);

            objStepsData.data.wayPoints[index].delayData = msToDaysHoursMinutesStruct(delta);
            var selectors = $('#moveOutEditRow_' + index).find('select');
            updateMoveOutDateSelectors(false, selectors, index);

            //refresh delay data
            if (!isFirstUpdate) updateDelayData(index);

            updateHoldTimeSelectors(index);

            for (var i = (index + 1); i < objStepsData.data.wayPoints.length - 1; i++) {
                var selectors = $('#moveOutEditRow_' + i).find('select');
                updateMoveOutDateSelectors(false, selectors, i);
                updateHoldTimeSelectors(i);
            }

            updateArriveTimeInLastWayPoint();
        });
        $(selectors[i]).append($(optionsHtml));
        i++;
    }
    //refresh delay data
    //if (!isFirstUpdate) updateDelayData(index);
}
//#endregion

//#region updateDelayData(index)
function updateDelayData(index) {
    var dateTmpObj = {
        day: $('#Day_' + index).val() * 1,
        month: $('#Month_' + index).val() * 1,
        year: $('#Year_' + index).val() * 1,
        hour: $('#Hour_' + index).val() * 1,
        minute: $('#Minutes_' + index).val() * 1
    };


    var composedDate = new Date(dateTmpObj.year + 2000, dateTmpObj.month - 1, dateTmpObj.day, dateTmpObj.hour, dateTmpObj.minute, 0);
    var delta = composedDate.getTime() - objStepsData.wayPointArriveDate(index).getTime();
    var tmp = new Date(delta);

    objStepsData.data.wayPoints[index].delayData = msToDaysHoursMinutesStruct(delta);
}
//#endregion

// *XSLT
//var OB_Destination = "Destination:";
//var OB_ArriveDateInfo = 'Afrejse herfra d. _date_ klokken _hh_:_mm_';

//#region getEndWayPointHTMLObj()
function getEndWayPointHTMLObj() {
    var htmlTemplate = "<div class='wayPointItem last'><div class='letter last'>D</div><div class='content'>" +
                       "<div class='infoBar'>" + OB_Destination + " <span></span></div>" +
                       "</div><div class='content'><div class='leftPanel'><span class='labelItem'>" + OB_PlaningOfPassengers +
                       "</span></div><div class='leftPanel last'><div class='infoRow last'></div></div></div></div>";
    var wayPointObj = $(htmlTemplate);
    // init headers
    var addressSpan = wayPointObj.find('.infoBar > span');
    addressSpan.html(objStepsData.data.wayPoints[objStepsData.data.wayPoints.length - 1].address);

    var infoString = OB_ArriveDateInfo;
    var datestring = getLeadingZeroNum(objStepsData.arriveTime().getDate()) + '/' +
                        getLeadingZeroNum(objStepsData.arriveTime().getMonth() + 1) + '/' +
                        getLeadingZeroNum(objStepsData.arriveTime().getFullYear() - 2000);
    infoString = infoString.replace('_date_', datestring);
    infoString = infoString.replace('_hh_', getLeadingZeroNum(objStepsData.arriveTime().getHours()));
    infoString = infoString.replace('_mm_', getLeadingZeroNum(objStepsData.arriveTime().getMinutes()));

    var infoRowObj = wayPointObj.find('.infoRow');
    infoRowObj.html(infoString);

    wayPointObj.find('.letter').html(getAlfaUppercaseCharByCode(objStepsData.data.wayPoints.length - 1));
    return wayPointObj;
}
//#endregion

//var OB_DepartureTitle = "Afgang: ";*XSLT
//var OB_DepartureDateInfo

//#region getStartWayPointHTMLObj()
function getStartWayPointHTMLObj() {
    var htmlTemplate = "<div class='wayPointItem first'><div class='letter first'>A</div><div class='content'><div class='infoBar'>" + OB_DepartureTitle +
                       " : <span></span></div>" +
                       "</div><div class='content'><div class='leftPanel'><span class='labelItem'>" + OB_PlaningOfPassengers + "</span></div>" +
                       "<div class='rightPanel'><span class='labelItem'>" + OB_TimeSetup + "</span></div><div class='leftPanel'>" +
                       "<div class='passengersIn'><div class='editRow'>" + OB_Persons +
                       "</div><div class='editRow bottomR'><span>" + OB_AdultTitle +
                       "</span><select id='adult_in_0'></select><span>" + OB_ChildrenTitle +
                       "</span><select id='children_in_0'></select><span>" + OB_WheelchearTitle +
                       "</span><select id='old_in_0'></select>" +
                       "</div></div></div><div class='rightPanel'><div class='infoRow'></div></div></div></div>";
    var wayPointObj = $(htmlTemplate);

    // init headers

    wayPointObj.find('.passengersIn select').change(function () {
        var id_data = $(this).attr('id').split('_');
        objStepsData.data.wayPoints[0].passengersDelta[id_data[0]]._in = $(this).val();
        setupPassengersInSelectors();
    });

    var addressSpan = wayPointObj.find('.infoBar > span');
    addressSpan.html(objStepsData.data.wayPoints[0].address);
    var infoString = OB_DepartureDateInfo;
    var datestring = getLeadingZeroNum(objStepsData.data.departureTime.getDate()) + '/' +
                        getLeadingZeroNum(objStepsData.data.departureTime.getMonth() + 1) + '/' +
                        getLeadingZeroNum(objStepsData.data.departureTime.getFullYear() - 2000);
    infoString = infoString.replace('_date_', datestring);
    infoString = infoString.replace('_hh_', getLeadingZeroNum(objStepsData.data.departureTime.getHours()));
    infoString = infoString.replace('_mm_', getLeadingZeroNum(objStepsData.data.departureTime.getMinutes()));

    var infoRowObj = wayPointObj.find('.infoRow');
    infoRowObj.html(infoString);

    return wayPointObj;
}
//#endregion

//#region initPassengersInfoData_s2()
function initPassengersInfoData_s2() {
    $('#passengersSumm_s2').html(objStepsData.data.wayPoints[0].passengersSumm(true));
    $('#adult_s2').html(objStepsData.data.wayPoints[0].passengers.adult);
    $('#children_s2').html(objStepsData.data.wayPoints[0].passengers.children);
    $('#old_s2').html(objStepsData.data.wayPoints[0].passengers.old);
}
//#endregion

//#region initPanelData(stepNum)
function initPanelData(stepNum) {
    switch (stepNum) {
        case 0:
            {
                if (objStepsData.data.wayPoints.length > 0) {
                    $('#old_s1').val(objStepsData.data.wayPoints[0].passengers.old);
                    $('#children_s1').val(objStepsData.data.wayPoints[0].passengers.children);
                    $('#adult_s1').val(objStepsData.data.wayPoints[0].passengers.adult);
                    $('#passengersSumm').html(objStepsData.data.wayPoints[0].passengersSumm());
                }
                break;
            }
        case 1:
            {
                initPassengersInfoData_s2();
                $('#routeData_s2').find('div').remove();
                $('#routeData_s2').append(getStartWayPointHTMLObj());
                if (objStepsData.data.wayPoints.length > 2) {
                    //append passing waypoint pionts here
                    for (var i = 1; i < objStepsData.data.wayPoints.length - 1; i++) {
                        $('#routeData_s2').append(getWayPointHTMLObj(i));
                        updateHoldTimeSelectors(i);
                    }
                }
                $('#routeData_s2').append(getEndWayPointHTMLObj());
                setupPassengersInSelectors();
                setupPassengersOutSelectors();

                //connect onchange events
                var selects = $('.passengersOut select');
                selects.change(function () {
                    var id_data = $(this).attr('id').split('_');
                    objStepsData.data.wayPoints[id_data[2]].passengersDelta[id_data[0]]['_out'] = $(this).val();
                    setupPassengersOutSelectors();
                });

                selects = $('.passengersIn select');
                if (objStepsData.data.wayPoints.length == 2) {
                    selects.attr('disabled', 'disabled');
                } else {
                    selects.removeAttr('disabled');
                    selects.change(function () {
                        var id_data = $(this).attr('id').split('_');
                        objStepsData.data.wayPoints[id_data[2]].passengersDelta[id_data[0]]._in = $(this).val();
                        setupPassengersInSelectors();
                        setupPassengersOutSelectors();
                        updatePassengersValidationText();
                    });
                }

                break;
            }
        case 3:
            {
                //rename selects and add options
                for (var key in objStepsData.data.serviceProducts) {
                    var select = $('#dd_' + key);
                    var options = '';
                    for (var key_wp = 1; key_wp < objStepsData.data.wayPoints.length; key_wp++) {
                        options += "<option value='" + key_wp + "'" +
                                        (key_wp == 0 ? 'selected=true' : '') +
                                        '>' + objStepsData.data.wayPoints[key_wp].address + "</option>";
                    }
                    select.find('option').remove();
                    select.append($(options));
                    $('#count_' + key).val(0);
                }

//                var floatingChart = new FloatLayer('serviceSelectedItemsListContainer', parseInt($("#sliderTrack").position().left), 0, 1);
//                detach('serviceSelectedItemsListContainer');
//                $("#sliderTrack").height($("#serviceSelectedItemsListContainer").height());
//                alignFloatLayers();

                break;
            }
    }
}
//#endregion

//#region showActivePanel()
function showActivePanel() {
    var pannelId = $(".stepItem.current").attr('data_id');
    $(".stepPannel").hide();
    initPanelData(objStepsData.currentStep);
    $('.formContainer').find('#' + pannelId).show();

    if (objStepsData.currentStep == 3) {
        var floatingChart = new FloatLayer('serviceSelectedItemsListContainer', parseInt($("#sliderTrack").position().left), 0, 1);
        detach('serviceSelectedItemsListContainer');
        $("#sliderTrack").height($("#serviceSelectedItemsListContainer").height());
        alignFloatLayers();

        // fill antal
        var totalPeople = $("#passengersSumm").html() * 1;
        var items = $(".serviceItem");
        for (var key = 0; key < items.length; key++) {
            var _id = ($(items[key]).attr('id').split('_'))[1];
            $("#count_" + _id).val(totalPeople);
        }
    }
}
//#endregion

//#region initTabs()
function initTabs() {
    var stepItems = $(".stepItem");
    for (var i = 0; i < stepItems.length; i++) {
        $(stepItems[i]).attr('index', i).click(function () {
            var newIndex = $(this).attr('index') * 1;
            if ((newIndex - objStepsData.currentStep) > 1) {
                newIndex = objStepsData.currentStep + 1;
            }
            if (validateAndGetStepData(objStepsData.currentStep)) {
                objStepsData.currentStep = newIndex;
                refreshTabs();
            }
        });
        stepInit(i);
    }
}
//#endregion

//#region refreshTabs()
function refreshTabs() {
    var stepItems = $(".stepItem");
    for (var i = 0; i < stepItems.length; i++) {
        if (i < objStepsData.currentStep) {
            $(stepItems[i]).removeClass('current').addClass('passed');
        } else {
            if (i == objStepsData.currentStep) {
                $(stepItems[i]).removeClass('passed').addClass('current');
            } else {
                $(stepItems[i]).removeClass('passed').removeClass('current');
            }
        }
    }
    showActivePanel();
}
//#endregion

//#region getLeadingZeroNum(num)
function getLeadingZeroNum(num) {
    if (num < 10) num = '0' + num;
    return num;
}
//#endregion

//#region initMinutesDD(ddId)
function initMinutesDD(ddId) {
    var selectObj = $('#' + ddId);
    for (var i = 0; i <= 59; i++) {
        var optHtm = "<option  value='" + i + "'>" + getLeadingZeroNum(i) + "</option>";
        selectObj.append($(optHtm));
    }
}
//#endregion

//#region initHoursDD(ddId)
function initHoursDD(ddId) {
    var selectObj = $('#' + ddId);
    for (var i = 0; i <= 23; i++) {
        var optHtm = "<option  value='" + i + "'>" + getLeadingZeroNum(i) + "</option>";
        selectObj.append($(optHtm));
    }
}
//#endregion

//#region daysInMonth(iMonth, iYear)
function daysInMonth(iMonth, iYear) {
    var dd = new Date(iYear, iMonth, 0);
    return dd.getDate();
}
//#endregion

//#region initDaysDD(ddId, month, year)
function initDaysDD(ddId, month, year) {
    var dateObj = new Date();
    var maxDays = 31;
    var startDay = 1;
    var selectObj = $('#' + ddId);
    selectObj.find('option').remove();
    for (var i = startDay; i <= maxDays; i++) {
        var optHtm = "<option  value='" + i + "'>" + getLeadingZeroNum(i) + "</option>";
        selectObj.append($(optHtm));
    }
}
//#endregion

//#region initMothesDD(ddId, year)
function initMothesDD(ddId, year) {
    var dateObj = new Date();
    var currentMoth = 0;
    var selectObj = $('#' + ddId);
    selectObj.find('option').remove();
    for (var i = (currentMoth + 1); i <= 12; i++) {
        var optHtm = "<option  value='" + i + "'>" + getLeadingZeroNum(i) + "</option>"; //" + ((i == currentMoth) ? "selected" : "") + "
        selectObj.append($(optHtm));
    }
}
//#endregion

//#region initYearsDD(ddId, delta)
function initYearsDD(ddId, delta) {
    var currentYear = (new Date()).getFullYear();
    var selectObj = $('#' + ddId);
    selectObj.find('option').remove();
    for (var i = currentYear; i <= (currentYear + delta); i++) {
        var optHtm = "<option  value='" + i + "'>" + i + "</option>"; //"+ ((i==currentYear)? "selected": "") +"
        selectObj.append($(optHtm));
    }

}
//#endregion

//var OB_ValMessageNumeric = 'Must be a number'; *XSLT

//#region numValidation(element)
function numValidation(element) {
    var value = $(element).val();
    var message = '';
    var result = true;
    var er = $(element).attr("id");

    if (isNaN(value)) {
        result = false;
        message = OB_ValMessageNumeric;
    }

    $(element).parent().find("label[for='" + er + "']").html(message);
    return result;
}
//#endregion

//#region updatePassangersSummary()
function updatePassangersSummary() {
    var newCount = 0;
    var pInputs = $("#1 .passengers4Count");
    for (var i = 0; i < pInputs.length; i++) {
        var value = $(pInputs[i]).val();
        value = (isNaN(value) ? 0 : value);
        newCount += value * 1;
    }
    $('#passengersSumm').html(newCount);
}
//#endregion

function formatCurrency(num) {
    num = num.toString().replace(/\$|\,/g, '');
    if (isNaN(num))
        num = "0";
    sign = (num == (num = Math.abs(num)));
    num = Math.floor(num * 100 + 0.50000000001);
    cents = num % 100;
    num = Math.floor(num / 100).toString();
    if (cents < 10)
        cents = "0" + cents;
    for (var i = 0; i < Math.floor((num.length - (1 + i)) / 3); i++)
        num = num.substring(0, num.length - (4 * i + 3)) + ',' +
num.substring(num.length - (4 * i + 3));
    return (((sign) ? '' : '-') + num + '.' + cents);
}

var totalPrice = 0;
//#region stepInit(ind)
function stepInit(ind) {
    ind = ind * 1;
    switch (ind) {
        case 0:
            {
                var validationItems = {
                    old_s1: "isNumber",
                    children_s1: "isNumber",
                    adult_s1: "isNumber"
                };

                s1Validator = new Validator(validationItems);

                $("#1 .dateAndPassengers input[name='valGroup']").change(function () {
                    s1Validator.validate($(this).attr('id'));
                    updatePassangersSummary();
                });

                //////////////////////////////////////////
                /// another date time interface

                s1_DatePicker = $('#s1_dateSelect').datepicker({
                    showOn: 'button',
                    buttonImage: '/Frontend/Images/Centrumturist/BookPanel/calendar.png',
                    buttonImageOnly: true,
                    minDate: new Date(),
                    dateFormat: "dd/mm/yy"
                });

                //////////////////////////////////////////


                //initYearsDD('year', 10);
                //initMothesDD('month', (new Date()).getFullYear());
                //initDaysDD('day', (new Date()).getMonth() + 1, (new Date()).getFullYear());
                //                $('#year').change(function() {
                //                    initMothesDD('month', $('#year').val() * 1);
                //                    initDaysDD('day', $('#month').val() * 1, $('#year').val() * 1);
                //                });

                //                $('#month').change(function() {
                //                    initDaysDD('day', $('#month').val() * 1, $('#year').val() * 1);
                //                });

                initHoursDD('hours');
                initMinutesDD('minutes');
                if (inputParams.isPresent) {
                    $('#adult_s1').val(inputParams.adult);
                    s1_DatePicker.datepicker('setDate', inputParams.departure);


                    //                    $('#year option').removeAttr('selected');
                    //                    $('#year option[value='+ inputParams.departure.getFullYear() +']').attr('selected', 'true');
                    //                    $('#month option').removeAttr('selected');
                    //                    $('#month option[value=' + (inputParams.departure.getMonth() + 1) + ']').attr('selected', 'true');
                    //                    $('#day option').removeAttr('selected');
                    //                    $('#day option[value=' + getLeadingZeroNum(inputParams.departure.getDate()) + ']').attr('selected', 'true');
                } else {
                    s1_DatePicker.datepicker('setDate', new Date());
                }

                updatePassangersSummary();
                break;
            }
        case 1:
            {
                break;
            }
        case 2:
            {
                $('.busItem input[type=radio]').change(function () {
                    var id = $(this).attr('id');
                    id = id.split('_');
                    id = id[1];
                    objStepsData.data.busTypeGUID = id;
                    objStepsData.data.busType = $('#BUSNAME_' + id).val();
                });
                break;
            }
        case 3:
            {
                //objStepsData.data.serviceProducts = ///
                var validationItems = {};
                var items = $(".serviceItem");
                for (var key = 0; key < items.length; key++) {
                    var _id = ($(items[key]).attr('id').split('_'))[1];
                    objStepsData.data.serviceProducts[_id] = {
                        name: $(items[key]).find('.headerText').html(),
                        id: _id
                    };
                    validationItems['count_' + _id] = 'isNumber';
                }
                s4Validator = new Validator(validationItems);


                $(".serviceItem input[type=text]").change(function () {
                    s4Validator.validate($(this).attr('id'));
                });

                $("#serviceSelectedItemsPriceValue").html(totalPrice);

                //*XSLT
                //var OB_delete = "slet";
                //var OB_ServiceItemMask = "* %%count%% stk. %%name%% . På vej til: %%serveUntil%%. ";
                $(".serviceItem").find('input[type=image]').click(function () {
                    var info = $(this).attr('id').split('_');
                    var payAfterTrip = $("#count_" + info[1]).length == 0;
                    if (payAfterTrip || s4Validator.validate('count_' + info[1])) {
                        if (!payAfterTrip && ($('#count_' + info[1]).val() * 1 == 0))
                            return;
                        var count = payAfterTrip ? 0 : $('#count_' + info[1]).val() * 1;
                        if (!payAfterTrip)
                            $('#count_' + info[1]).val($("#passengersSumm").html() * 1);

                        var orderId = objStepsData.data.orderedServices.length;
                        objStepsData.data.orderedServices[orderId] = {
                            GUID: info[1],
                            count: count,
                            serveUntil: objStepsData.data.wayPoints[$('#dd_' + info[1]).val()].address,
                            serveUntilKey: $('#dd_' + info[1]).val(),
                            name: $.trim($('#SI_' + info[1]).find('.headerText').html()),
                            price: payAfterTrip ? "-" : $.trim($('#SI_' + info[1] + "_Price").val()),
                            info: $.trim($('#SI_' + info[1]).find('.serviceInfo').html()),
                            category: $.trim($('#SI_' + info[1] + "_Category").val()),
                            payAfterTrip: payAfterTrip
                        };
                        var itemHtml = "<div class='selectedService'>" +
                                                "<div class='selectedServiceTitle'>{TITLE}</div>" +
                                                "<div class='selectedServiceDescription'>{DESCRIPTION}</div>" +
                                                "<div class='selectedServicePrice'>{PRICE}</div>" +
                                                "<div class='selectedServiceDelete'><a class='deleteService' href='javascript:;'>" + OB_delete + "</a></div>" +
                                                "<div style='clear: both;'></div>" +
                                            "</div>";

                        var destinationContainer = "<div id='serviceItemDestination_{DESTINATIONID}' class='serviceBlock'>" +
                                                            "<div class='serviceTitle'>{TITLE}</div>" +
                                                       "</div>";

                        var currentItem = objStepsData.data.orderedServices[orderId];
                        var str = OB_ServiceItemMask;
                        if (payAfterTrip) {
                            // sum passengers
                            var sum = 0;
                            var passengers = objStepsData.data.wayPoints[objStepsData.data.orderedServices[orderId].serveUntilKey].passengers
                            for (var i in passengers) {
                                sum += passengers[i];
                            }
                            currentItem.count = sum;
                        }

                        str = str.replace("%%count%%", currentItem.count);
                        str = str.replace("%%name%%", currentItem.category);
                        str = str.replace("%%serveUntil%%", currentItem.serveUntil);

                        var desstinationDivId = "#serviceItemDestination_" + currentItem.serveUntilKey;
                        var destinationDiv = $(desstinationDivId);
                        if (destinationDiv.length == 0) {
                            destinationContainer = destinationContainer.replace("{DESTINATIONID}", currentItem.serveUntilKey);
                            destinationContainer = destinationContainer.replace("{TITLE}", $.trim($('.serviceLabel').html()) + " " + currentItem.serveUntil);
                            $("#serviceSelectedItemsList").append($(destinationContainer));
                        }

                        itemHtml = itemHtml.replace("{TITLE}", str);
                        itemHtml = itemHtml.replace("{DESCRIPTION}", currentItem.name);
                        itemHtml = itemHtml.replace("{PRICE}", payAfterTrip ? currentItem.price : $("#serviceSelectedItemsPriceValueContainer").find("span").html() + " "
                                                                                                    + formatCurrency(currentItem.price * currentItem.count));

                        if (!payAfterTrip)
                            totalPrice += currentItem.price * currentItem.count;
                        $("#serviceSelectedItemsPriceValue").html(formatCurrency(totalPrice));
                        //  På vej til: %%serveUntil%%. 

                        var itemObj = $(itemHtml);

                        itemObj.find('span').html(str);
                        itemObj.attr('id', 'SS_' + orderId);
                        itemObj.find('.deleteService').attr('id', 'del_' + orderId).click(function () {
                            var info = $(this).attr('id').split('_');
                            var item = objStepsData.data.orderedServices[info[1]]
                            if (!item.payAfterTrip) {
                                var subtract = item.price * item.count;
                                totalPrice -= subtract;
                                $("#serviceSelectedItemsPriceValue").html(formatCurrency(totalPrice));
                            }
                            objStepsData.data.orderedServices[info[1]] = null;
                            $('.serviceChooseContainer').find('#SS_' + info[1]).remove();

                            $("#sliderTrack").height($("#serviceSelectedItemsListContainer").height());
                            alignFloatLayers();

                        });

                        $(desstinationDivId).append(itemObj);

                        $("#sliderTrack").height($("#serviceSelectedItemsListContainer").height());
                        alignFloatLayers();

                    }
                });
                break;
            }
        case 4:
            {
                s5Validator = new Validator({
                    name_s5: "isEmpty",
                    addresse_s5: "isEmpty",
                    houseNum_s5: "isEmpty",
                    postNr_s5: "isEmpty, isNumber",
                    city_s5: "isEmpty",
                    phone_s5: "isPhoneEntered",
                    mobile_s5: "isPhoneEntered",
                    email_s5: "isEmpty, isEmail"
                });


                for (var key in s5Validator.valData) {
                    $('#' + key).change(function () {
                        s5Validator.validate($(this).attr('id'));
                    });
                }

                var validateAndCollectData = function () {
                    //validation here
                    isValid = s5Validator.validateAll();
                    //validate EAN
                    if (!isValidEAN($('#EAN_s5').val())) {
                        s5Validator.showValidateMessage('EAN_s5', OB_ValidEAN);
                        isValid = false;
                    }
                    else {
                        s5Validator.showValidateMessage('EAN_s5', '');
                    }
                    //if valid - collect data
                    if (isValid) {
                        for (var key in objStepsData.data.ClientData) {
                            objStepsData.data.ClientData[key] = $('#' + key + '_s5').val();
                        }
                        objStepsData.data.ClientData.country = $.trim($('#country_s5 option:selected').text());
                        objStepsData.data.ClientData.countryCode = $('#country_s5').val();
                        objStepsData.data.ClientData.houseNum = $('#houseNum_s5').val();
                        objStepsData.data.subscribedForNews = $('#subscribed_s5').attr('checked');

                        //init modal window

                        insertCustomerInformation();
                        insertRouteInformation();
                        insertOtherInformation();
                    }

                    return isValid;
                }

                //show summary step
                $('#summary').click(function () {
                    if (validateAndCollectData()) {
                        $('#modalSummary').modal({
                            overlayCss: {
                                backgroundColor: '#000'
                            },
                            containerCss: {
                                width: 865
                            }
                        });

                        /// Load real map //////////////
                        var summary_map = new google.maps.Map2($('#summary_map2')[0]);
                        var directions2 = new GDirections(summary_map);

                        summary_map.setCenter(new google.maps.LatLng(55.677584, 12.567672), 8);
                        summary_map.setUIToDefault();
                        var addr_list = Array();
                        for (var i = 0; i < objStepsData.data.wayPoints.length; i++) {
                            addr_list.push(objStepsData.data.wayPoints[i].address);
                        }
                        directions2.loadFromWaypoints(addr_list, { travelMode: G_TRAVEL_MODE_DRIVING });
                        /////////////////////////////////
                    }
                });

                $('#close_modal').click(function () {
                    $.modal.close();
                });

                var submitFuntion = function () {
                    //send form data here
                    var funcData = createDataObject();
                    var functionName = "SendOnlineBookingNotification";
                    var jsonText = JSON.stringify(funcData, function (key, value) { return value; });
                    $.ajax({
                        type: "POST",
                        url: "/Frontend/CentrumTurist/Server/ServiceFunctions.ashx",
                        data: {
                            "name": functionName,
                            "funcData": jsonText
                        },
                        success: function (data, textStatus) {
                            //var OB_BookingSuccessfull = "Din booking / pris forespørgsel er blevet sent";*XSLT
                            pageTracker._trackPageview("/booking_sent.html"); 
                            alert(OB_BookingSuccessfull); //'Your booking request has been sent.'
                            $.modal.close();
                            window.location = "/";
                        },
                        error: function (XMLHttpRequest, textStatus, errorThrown) {
                            alert(XMLHttpRequest.responseText);
                        }
                    });

                }

                $('#submit_s5').click(submitFuntion);
                $('#sendResult').click(function () { if (validateAndCollectData()) submitFuntion() });



                break;
            }
    }
}
//#endregion

//#region initNavigationButtons()
function initNavigationButtons() {
    $('.nextStep').click(function () {
        if (validateAndGetStepData(objStepsData.currentStep)) {
            objStepsData.currentStep++;
            refreshTabs();
        }
    });
}
//#endregion

//#region getQueryParameter(name)
function getQueryParameter(name) {
    name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
    var regexS = "[\\?&]" + name + "=([^&#]*)";
    var regex = new RegExp(regexS);
    var results = regex.exec(window.location.href);
    if (results == null)
        return "";
    else
        return results[1];
}
//#endregion

/* ========================================================================= */
/* ========================================================================= */
/* ========================================================================= */
/* ========================= route.js is merged here ======================= */
/* ========================================================================= */
/* ========================================================================= */
/* ========================================================================= */

var geoCoder = null;

//#region initializeMap()
function initializeMap() {
    map = new google.maps.Map2($('#map')[0]);
    directions = new GDirections(map);
    geoCoder = new GClientGeocoder();

    GEvent.addListener(directions, "load", ondirectionsectionsLoad);
    GEvent.addListener(directions, "error", handleErrors);
    GEvent.addListener(map, "tilesloaded", mapDataLoaded);
    map.setCenter(new google.maps.LatLng(55.677584, 12.567672), 8);
    map.setUIToDefault();

    if (inputParams.isPresent) {
        getDirections(false);
    }
}
//#endregion

//#region mapDataLoaded()
function mapDataLoaded() {
    mapBounds = map.getBounds();
    mapCenter = map.getCenter();
    mapZoom = map.getZoom();
}
//#endregion

//#region $(function() -- on document ready initialization
$(function () {
    google.setOnLoadCallback(initializeMap);
    $('#sortable').sortable({
        handle: '.destinationPoint',
        update: function (event, ui) {
            getDirections(true);
        }
    });
    $('#sortable').disableSelection();

    if (!inputParams.isPresent) {
        for (var i = 0; i <= 1; i++)
            addDestination("");
    } else {
        addDestination(inputParams.from);
        addDestination(inputParams.to);
        if (inputParams.isCruis) addDestination(inputParams.from);
    }
    refreshList();
    // init service accordion
    $("#serviceItemsList").accordion({
        autoHeight: false,
        navigation: true,
        collapsible: false
    });
});
//#endregion

//#region getZeroOffset()
function getZeroOffset() {
    var firstSymbol = 'A';
    var symbolOffset = firstSymbol.charCodeAt(0);
    return symbolOffset;
}
//#endregion

//var OB_thru = "Via"; *XSLT
//#region refreshList()
function refreshList() {
    var max = $('#sortable li').length - 1;
    var symbolOffset = getZeroOffset();

    $('#sortable li').each(function (i, destinationCtl) {
        destinationCtl = $(destinationCtl);
        var labelText = OB_DepartureTitle;
        var displayStyle = 'none';
        if (i != 0) {
            if (i < max) {
                labelText = i + '. ' + OB_thru;
                displayStyle = 'block';
                destinationCtl.find('.destinationPoint').removeClass('last');
                destinationCtl.find('.destinationPoint').removeClass('first');
            } else {
                labelText = OB_Destination;
                destinationCtl.find('.destinationPoint').removeClass('first');
                destinationCtl.find('.destinationPoint').addClass('last');
            }
        } else {
            destinationCtl.find('.destinationPoint').removeClass('last');
            destinationCtl.find('.destinationPoint').addClass('first');
        }
        destinationCtl.find('span').html(labelText);
        destinationCtl.find('a').css('display', displayStyle);

        var c = String.fromCharCode(symbolOffset + i);
        destinationCtl.find('div.letter').html(c);
    });
}
//#endregion

//#region addOneDestination()
function addOneDestination() {
    addDestination("");
    refreshList();
}
//#endregion

//var OB_MaxWaypointsReached = "Du kan desværre ikke tilføje flere destinationer"; *XSLT

function updateSuggestions(element) {
    if (element.attr('prevText') != element.attr('value')) {
        element.removeAttr('validated');
        objStepsData.wayPointChanged = true;
        getDirections(false);
    }
    return true;
}

//#region  addDestination(address)
function addDestination(address) {
    if (!address || address == 'undefined') {
        address = "";
    }
    var symbolOffset = getZeroOffset();
    var index = $('#sortable li').length;
    if (index > 25) {
        alert(OB_MaxWaypointsReached); //'Max number of waypoints reached'
        return false;
    }


    //var OB_DateTimeRulesMask = "Adresse, post nr., by"; *XSLT
    var destinationHtm = '<li><div class="destinationPoint last"><div class="letter">..</div><div class="data">' +
                            '<div><div class="pointTitleBlock"><span>' + OB_DepartureTitle + '</span></div><div class="pointRemoveBlock">' +
                            '<a href="javascript:;">' + OB_delete + '</a></div></div><div>' +
                            '<input unselectable="off" style="-moz-user-select:text;"  type="text" value="" class="addresseInput" />' +
                            '</div><div><label>' + OB_DateTimeRulesMask + '</label></div></div></div></li>';
    var destinationObj = $(destinationHtm);

    var $txt = destinationObj.find('input');
    $txt.attr('value', address)
        .attr('prevText', address)
        .attr('city', '')
        .attr('lat', '')
        .attr('lng', '')
        .attr('country', '')
        .attr('zipcode', '')
        .attr('street', '')
        .change(function () { updateSuggestions($(this)); })
        .keypress(function (event) {
            if (event.keyCode == '13') {
                updateSuggestions($(this));
                //event.preventDefault();
            }
        });

    var c = String.fromCharCode(symbolOffset + index);
    destinationObj.find('div.letter').html(c);
    destinationObj.find('a').click(function () {
        destinationObj.remove();
        objStepsData.wayPointsChanged = true;
        getDirections(true);
    });

    $('#sortable').attr('unselectable', 'off').removeAttr('style').append(destinationObj);
}
//#endregion

//#region getDirections(needRefreshList)
var obDestinationPointContainerClass = 'destinationPoint';
var obDestinationPointTextboxClass = 'addresseInput';
var obSuggestionsContainerClass = 'obSuggestionsContainer';
var obSuggestionsHeaderClass = 'obSuggestionsHeader';
var obSuggestionsBodyClass = 'obSuggestionsBody';
var obSuggestionClass = 'obSuggestion';
var obSuggestionHighlightedClass = 'obSuggestionHighlighted';
var obSuggestionTitleClass = 'obSuggestionTitle';
var obSuggestionDetailsClass = 'obSuggestionDetails';
var obSuggestionLinkClass = 'obSuggestionLink';

var obSuggestionHeaderText = OB_WhatDoYouMean;

function getDirections(needRefreshList) {
    var MAX_SUGGESTIONS_COUNT = 500;

    //#region validateLocations(waypoints, $textboxes, onAllValidated)
    function validateLocations(waypoints, $textboxes, onAllValidated) {

        function removeSuggestions($destPointContainer) {
            $destPointContainer.find('.' + obSuggestionsContainerClass).remove();
        }

        function createSuggestions($container) {
            var $suggContainer = $('<div/>').appendTo($container).addClass(obSuggestionsContainerClass);
            var $suggHeader = $('<div/>').appendTo($suggContainer).addClass(obSuggestionsHeaderClass).text(obSuggestionHeaderText);
            var $suggBody = $('<div/>').appendTo($suggContainer).addClass(obSuggestionsBodyClass);
            return $suggBody;
        }

        //#region addSuggestion($suggBody, placemark, waypoint)
        function addSuggestion($suggBody, placemark, waypoint) {
            var details = getPlacemarkDetails(placemark);
            var $sugg = $('<div/>').appendTo($suggBody).addClass(obSuggestionClass);
            var $suggTitle = $('<div/>').appendTo($sugg).addClass(obSuggestionTitleClass);
            var $suggDetails = $('<div/>').appendTo($sugg).addClass(obSuggestionDetailsClass);

            $suggDetails.append('<div>' + details.address + '</div>');

            var titleText = '';
            if (details.street !== '') {
                titleText += (titleText !== '' ? ', ' : '') + details.street;
            }
            if (details.city !== '') {
                titleText += (titleText !== '' ? ', ' : '') + details.city;
            }
            if (details.countryName !== '') {
                titleText += (titleText !== '' ? ', ' : '') + details.countryName;
            }
            if (titleText === '') {
                titleText = details.address;
            }
            var $titleLink = $('<div/>').appendTo($suggTitle).addClass(obSuggestionLinkClass).text(titleText);
            (function (waypoint, details) {
                $sugg.click(function (event) {
                    event.stopPropagation();
                    event.preventDefault();

                    var $this = $(this);
                    var $txt = $this.closest('.' + obDestinationPointContainerClass).find('input.' + obDestinationPointTextboxClass);
                    $txt.attr('prevText', details.address)
                        .attr('value', details.address)
                        .attr('validated', 'validated')
                        .attr('city', details.city)
                        .attr('lat', details.lat)
                        .attr('lng', details.lng)
                        .attr('zipcode', details.zipcode)
                        .attr('country', details.country)
                        .attr('street', details.street);

                    waypoint.address = details.address;
                    waypoint.city = details.city;
                    waypoint.zipcode = details.zipcode;
                    waypoint.country = details.country;
                    waypoint.street = details.street;
                    waypoint.lat = details.lat;
                    waypoint.lng = details.lng;

                    removeSuggestions($this.closest('.' + obDestinationPointContainerClass));
                    checkEverythingIsValidated();
                }).hover(function () { $(this).addClass(obSuggestionHighlightedClass); }, function () { $(this).removeClass(obSuggestionHighlightedClass); });
            })(waypoint, details);
        }
        //#endregion

        function checkEverythingIsValidated() {
            var suggCnt = $('#sortable .' + obSuggestionsContainerClass).length;
            if (suggCnt === 0) {
                onAllValidated(waypoints);
            }
        }

        if ($textboxes.length !== waypoints.length) {
            throw '$textboxes.length must be equal to waypoints.length!';
        }

        var wasChanged = false;
        for (var i = 0; i < $textboxes.length; i++) {
            var $txt = $textboxes[i];
            var wp = waypoints[i];
            if ($txt.attr('validated') !== undefined) {
                //already validated
                wp.address = $txt.attr('value');
                wp.city = $txt.attr('city');
                wp.lat = $txt.attr('lat');
                wp.lng = $txt.attr('lng');
                wp.country = $txt.attr('country');
                wp.street = $txt.attr('street');
                wp.zipcode = $txt.attr('zipcode');
            } else {
                wasChanged = true;
                (function (waypoint, $textbox) {

                    function onSuggestionsLoaded(response) {
                        var placemarks = response.Placemark;
                        if (placemarks) {
                            if (placemarks.length === 0) {
                                //$textbox.attr('validated', 'validated');
                                //checkEverythingIsValidated();
                            } else {
                                $textbox.removeClass("notFound");
                                //placemarks.sort(function(a, b) { return -(a.AddressDetails.Accuracy - b.AddressDetails.Accuracy); });
                                var cnt = Math.min(MAX_SUGGESTIONS_COUNT, placemarks.length);

                                var $destPointContainer = $textbox.closest('.' + obDestinationPointContainerClass);
                                removeSuggestions($destPointContainer);
                                var $suggBody = createSuggestions($destPointContainer);
                                for (var i = 0; i < cnt; i++) {
                                    addSuggestion($suggBody, placemarks[i], waypoint);
                                }
                            }
                        } else { 
                            var $destPointContainer = $textbox.closest('.' + obDestinationPointContainerClass);
                            removeSuggestions($destPointContainer);
                            $textbox.addClass("notFound");
                        }

                    }

                    geoCoder.getLocations(wp.address, onSuggestionsLoaded);

                    //                    geoCoder.getLocations(wp.address, function(resp) {
                    //                        if (resp.Placemark.length > 0) {
                    //                            geoCoder.getLocations(
                    //                                new GLatLng(resp.Placemark[0].Point.coordinates[1], resp.Placemark[0].Point.coordinates[0]),
                    //                                onSuggestionsLoaded);
                    //                        }
                    //                    });
                })(wp, $txt);
            }
        }
        if (!wasChanged) {
            checkEverythingIsValidated();
        }
    }
    //#endregion

    //#region onAllValidated(waypoints)
    function onAllValidated(waypoints) {
        var addresses = [];
        for (var i = 0; i < waypoints.length; i++) {
            if (waypoints[i].address.length > 0) {
                //addresses.push(waypoints[i].address);
                addresses.push(new GLatLng(waypoints[i].lat, waypoints[i].lng));
            }
        }
        if (addresses.length > 1) {
            map.clearOverlays();
            directions.loadFromWaypoints(addresses, { travelMode: G_TRAVEL_MODE_DRIVING });
        } else if (addresses.length == 1) {
            map.clearOverlays();
            geoCoder.getLatLng(addresses[0], function (latlng) {
                if (latlng) {
                    map.addOverlay(new GMarker(latlng));
                    map.setCenter(latlng);
                } else {
                    alert(OB_Gmaps_message1);
                }
            });
        }
    }
    //#endregion

    loadStatus = 0; // ?

    $('#distance').html('0');
    var $textboxes = [];
    waypoints.length = 0;

    if (needRefreshList) {
        refreshList();
    }

    $('#sortable li').each(function (i, destinationCtl) {
        var waypoint = getWaypoint(destinationCtl);
        if (waypoint.address.length > 0) {
            waypoints.push(waypoint);
            $textboxes.push($(destinationCtl).find('input.' + obDestinationPointTextboxClass));
        }
    });

    validateLocations(waypoints, $textboxes, onAllValidated);
    return null;
}
//#endregion

//#region getWaypoint(destinationCtl)
function getWaypoint(destinationCtl) {
    var w = new waypoint();
    var txtAddress = $(destinationCtl).find('input');
    w.address = $.trim(txtAddress.val());
    //    geoCoder.getLocations(w.address, function(resp) {
    //        if (resp.Status.code == G_GEO_SUCCESS && resp.Placemark.length > 0) {
    //            var pl = resp.Placemark[0];
    //            for (var i = 1; i < resp.Placemark.length; i++) {
    //                if (resp.Placemark[i].AddressDetails.Accuracy > pl.AddressDetails.Accuracy) {
    //                    pl = resp.Placemark[i];
    //                }
    //            }
    //            var latLng = new GLatLng(pl.Point.coordinates[1], pl.Point.coordinates[0]);
    //            geoCoder.getLocations(latLng, function(response) {
    //                var addr = getAdressDetails(response);
    //                txtAddress.val(addr.address);
    //                w.address = addr.address;
    //                w.city = addr.city;
    //                w.country = addr.country;
    //                w.zipcode = addr.zipcode;
    //                w.street = addr.street;
    //            });
    //        }
    //    });
    return w;
}
//#endregion

//#region ondirectionsectionsLoad()
function ondirectionsectionsLoad() {
    var distance = directions.getDistance().html;
    $('#distance').html(distance);
    for (var i = 1; i < waypoints.length; i++) {
        var subRouteTime = directions.getRoute(i - 1).getDuration().seconds * 1000;
        subRouteTime += Math.round((subRouteTime / 100) * correctionIndex);
        waypoints[i].subRouteTime = subRouteTime;
    }
    objStepsData.data.wayPoints = waypoints;
    objStepsData.wayPointChanged = false;
    directionsPolyline = directions.getPolyline();
}
//#endregion

// *XSLT
//var OB_Gmaps_message1 = 'Vi kan desværre ikke finde adressen. Du skal skrive adressen som "Adresse, post nr, by". Er adressen ny kan det være grunden til at vi ikke kan finde den. Brug evt. en adresse i nærheden eller ring til os i stedet.';
//var OB_Gmaps_message2 = 'Desværre kunne vi ikke beregne en rute med de valgte destinationer. Ring venligst til os istedet.';
//var OB_Gmaps_message3 = 'Vi kunne desværre ikke gennemfører rute beregningen. Du er meget velkommen til at ringe i stedet.';
//var OB_Gmaps_message4 = 'Vi kunne ikke finde alla adresser, venligst tjek om adresserne er skrevet rigtigt.';
//var OB_Gmaps_message5 = 'En uventet fejl opstod, prøv venligst igen.\n Error code: ';

//#region handleErrors()
function handleErrors() {
    waypoints.length = 0;
    if (directions.getStatus().code == G_GEO_UNKNOWN_ADDRESS)
        alert(OB_Gmaps_message1); //"No corresponding geographic location could be found for one of the specified addresses. This may be due to the fact that the address is relatively new, or it may be incorrect.\nError code: " + directions.getStatus().code

    else if (directions.getStatus().code == G_GEO_UNKNOWN_DIRECTIONS)
        alert(OB_Gmaps_message2); //"Could not compute directions between the points mentioned. This is usually because there is no route available between the two points, or because we do not have data for routing in that region.\nError code: " + directions.getStatus().code

    else if (directions.getStatus().code == G_GEO_SERVER_ERROR)
        alert(OB_Gmaps_message3); //"A geocoding or directions request could not be successfully processed, yet the exact reason for the failure is not known.\n Error code: " + directions.getStatus().code

    else if (directions.getStatus().code == G_GEO_MISSING_QUERY);
    //alert("The HTTP q parameter was either missing or had no value. For geocoder requests, this means that an empty address was specified as input. For directions requests, this means that no query was specified in the input.\n Error code: " + directions.getStatus().code);

    //   else if (directions.getStatus().code == G_UNAVAILABLE_ADDRESS)  <--- Doc bug... this is either not defined, or Doc is wrong
    //     alert("The geocode for the given address or the route for the given directions query cannot be returned due to legal or contractual reasons.\n Error code: " + directions.getStatus().code);

    else if (directions.getStatus().code == G_GEO_BAD_KEY);
    //alert("The given key is either invalid or does not match the domain for which it was given. \n Error code: " + directions.getStatus().code);

    else if (directions.getStatus().code == G_GEO_BAD_REQUEST)
        alert(OB_Gmaps_message4); //"A directions request could not be successfully parsed.\n Error code: " + directions.getStatus().code

    else alert(OB_Gmaps_message5 + directions.getStatus().code); //An unknown error occurred.

}
//#endregion

/* ========================================================================= */
/* ========================================================================= */
/* ========================================================================= */
/* ========================================================================= */
/* ================================  Step 6 generation ===================== */

function getWhiteSpaceBlockObj() {
    return $('<div class="wsspacer"></div>');
}

function getLineSpacerBlock() {
    return $('<div class="linespacer"></div>');
}

function getRow() {
    return $('<div class="inforow"></div>');
}

function getRowCell() {
    return $('<div class="inforow-cell"></div>');
}

function getHeaderTextBlock(text) {
    var textBlockObj = $('<div class="headerText"></div>');
    textBlockObj.html(text);
    return textBlockObj;
}

function getSimpleTextBlock(text) {
    var textBlockObj = $('<div class="infoText"></div>');
    textBlockObj.html(text);
    return textBlockObj;
}

//* XSLT
//var OB_Name = "Navn: ";
//var OB_Address = "Addresse: ";
//var OB_Phone = "Telefon:";
//var OB_Phone_stationar = ' (stationar)';
//var OB_Phone_mobile = ' (mobile)';
//var OB_Email = "Email:";
//var OB_Customers = "Kunder:";
//var OB_ForSpecialCustomers = " (for fidligere kunder)";
//var OB_EAN = "EAN:";
//var OB_ForCustomers = " (for off. virksonheder)";

//#region insertCustomerInformation()
function insertCustomerInformation() {
    var placeholder = $('#summary_c1');
    placeholder.find('div').remove();

    placeholder.append(getHeaderTextBlock(OB_Name));
    placeholder.append(getSimpleTextBlock(objStepsData.data.ClientData.name));
    placeholder.append(getWhiteSpaceBlockObj());

    placeholder.append(getHeaderTextBlock(OB_Address));
    placeholder.append(getSimpleTextBlock(objStepsData.data.ClientData.addresse));
    placeholder.append(getSimpleTextBlock(objStepsData.data.ClientData.postNr + ' ' + objStepsData.data.ClientData.city));
    placeholder.append(getSimpleTextBlock(objStepsData.data.ClientData.country));
    placeholder.append(getWhiteSpaceBlockObj());

    placeholder.append(getHeaderTextBlock(OB_Phone));
    placeholder.append(getSimpleTextBlock(objStepsData.data.ClientData.phone + OB_Phone_stationar));
    placeholder.append(getSimpleTextBlock(objStepsData.data.ClientData.mobile + OB_Phone_mobile));
    placeholder.append(getWhiteSpaceBlockObj());

    placeholder.append(getHeaderTextBlock(OB_Email));
    placeholder.append(getSimpleTextBlock(objStepsData.data.ClientData.email));
    placeholder.append(getWhiteSpaceBlockObj());

    placeholder.append(getHeaderTextBlock(OB_Customers));
    placeholder.append(getSimpleTextBlock(objStepsData.data.ClientData.client));
    placeholder.append(getSimpleTextBlock(OB_ForSpecialCustomers));
    placeholder.append(getWhiteSpaceBlockObj());

    placeholder.append(getHeaderTextBlock(OB_EAN));
    placeholder.append(getSimpleTextBlock(objStepsData.data.ClientData.EAN));
    placeholder.append(getSimpleTextBlock(OB_ForCustomers));
}
//#endregion

//var OB_ShortTime = "Kl."; *XSLT
//#region getFormatedDateTime(date)
function getFormatedDateTime(date) {
    var mm = date.getMonth() + 1;
    var yy = date.getFullYear();
    var dd = date.getDate();

    var min = date.getMinutes();
    var hour = date.getHours();

    var datestring = "";

    datestring += getLeadingZeroNum(dd) + "-";
    datestring += getLeadingZeroNum(mm) + "-";
    datestring += yy + " " + OB_ShortTime + ": ";
    datestring += getLeadingZeroNum(hour) + ":" + getLeadingZeroNum(min);

    return datestring;  //date.format('d-m-Y') + " " + OB_ShortTime + ": " + date.format('H:i');
}
//#endregion

// *XSLT
//var OB_Route = "Route";
//var OB_DepartureShort = "Afrejse";
//var OB_ArriveShort = "Ankomst";
//var OB_PassengersCountTitle = "Antal passangere";
//var OB_Adult = "";
//var OB_Children = "";
//var OB_From = "Fra";
//var OB_To = "Til";
//var OB_WaypointsLegend = "*Tidspunkterne er alene vejledende. Endelig rejseplan udarbejdes af Centrumturist.";
//var OB_Details = "Dataljer";
//var OB_PassengersManagement = "Påstigning";

//#region insertRouteInformation()
function insertRouteInformation() {
    var placeholder = $('#summary_c2');
    placeholder.find('div').remove();
    placeholder.append(getHeaderTextBlock(OB_Route + ':').attr('style', 'color:#4b8a3b;'));
    placeholder.append(getWhiteSpaceBlockObj());
    placeholder.append(getHeaderTextBlock(objStepsData.data.wayPoints[0].address + ' - ' + objStepsData.data.wayPoints[objStepsData.data.wayPoints.length - 1].address));
    placeholder.append(getWhiteSpaceBlockObj());
    placeholder.append(getLineSpacerBlock());
    placeholder.append(getHeaderTextBlock(OB_DepartureShort + ':'));
    placeholder.append(getSimpleTextBlock(getFormatedDateTime(objStepsData.data.departureTime)));
    placeholder.append(getWhiteSpaceBlockObj());

    var arrive_time = objStepsData.arriveTime();
    placeholder.append(getHeaderTextBlock(OB_ArriveShort + ':'));
    placeholder.append(getSimpleTextBlock(getFormatedDateTime(arrive_time)));
    placeholder.append(getWhiteSpaceBlockObj());
    placeholder.append(getLineSpacerBlock());
    placeholder.append(getHeaderTextBlock(OB_PassengersCountTitle + ':'));
    placeholder.append(getSimpleTextBlock(objStepsData.data.wayPoints[0].passengers.adult + " " + OB_Adult));
    placeholder.append(getSimpleTextBlock(objStepsData.data.wayPoints[0].passengers.children + " " + OB_Children));
    placeholder.append(getSimpleTextBlock(objStepsData.data.wayPoints[0].passengers.old + " " + OB_Wheelchear_Title));
    placeholder.append(getWhiteSpaceBlockObj());
    placeholder.append(getLineSpacerBlock());
    for (var i = 0; i < objStepsData.data.wayPoints.length; i++) {
        var title = OB_thru + ": ";
        if (i == 0) title = OB_From + ": ";
        if (i == objStepsData.data.wayPoints.length - 1) title = OB_To + ": ";
        var row = getRow();
        var cell = getRowCell();
        cell.append(getHeaderTextBlock(title).attr('style', 'width: 50px;'));
        row.append(cell);
        cell = getRowCell();
        cell.append(getSimpleTextBlock(objStepsData.data.wayPoints[i].address));
        cell.append(getSimpleTextBlock(getFormatedDateTime(objStepsData.wayPointDepartureDate(i))));
        row.append(cell);
        placeholder.append(row);
        placeholder.append(getWhiteSpaceBlockObj());
    }
    placeholder.append(getSimpleTextBlock(OB_WaypointsLegend));
    placeholder.append(getWhiteSpaceBlockObj());
    placeholder.append(getLineSpacerBlock());
    placeholder.append(getHeaderTextBlock(OB_Details + ':').attr('style', 'color:#4b8a3b;'));
    placeholder.append(getWhiteSpaceBlockObj());
    placeholder.append(getHeaderTextBlock(OB_PassengersManagement + ':'));
    placeholder.append(getWhiteSpaceBlockObj());
    for (var i = 0; i < objStepsData.data.wayPoints.length - 1; i++) {
        if ((objStepsData.data.wayPoints[i].passengersDelta.adult._in > 0 || objStepsData.data.wayPoints[i].passengersDelta.adult._out > 0) ||
                (objStepsData.data.wayPoints[i].passengersDelta.children._in > 0 || objStepsData.data.wayPoints[i].passengersDelta.children._out > 0)) {
            var row = getRow();
            var cell = getRowCell();
            cell.append(getHeaderTextBlock(i + '.').attr('style', 'width: 45px;'));
            row.append(cell);
            cell = getRowCell();
            cell.append(getSimpleTextBlock(objStepsData.data.wayPoints[i].address));
            var in_out;
            if (objStepsData.data.wayPoints[i].passengersDelta.adult._in > 0 || objStepsData.data.wayPoints[i].passengersDelta.adult._out > 0) {
                in_out = (objStepsData.data.wayPoints[i].passengersDelta.adult._in > 0 ? '[ +' + objStepsData.data.wayPoints[i].passengersDelta.adult._in + ' ]' : '') + (objStepsData.data.wayPoints[i].passengersDelta.adult._out > 0 ? '[ -' + objStepsData.data.wayPoints[i].passengersDelta.adult._out + ' ]' : '');
                cell.append(getSimpleTextBlock(in_out + " " + OB_Adult));
            }
            if (objStepsData.data.wayPoints[i].passengersDelta.children._in > 0 || objStepsData.data.wayPoints[i].passengersDelta.children._out > 0) {
                in_out = (objStepsData.data.wayPoints[i].passengersDelta.children._in > 0 ? '[ +' + objStepsData.data.wayPoints[i].passengersDelta.children._in + ' ]' : '') + (objStepsData.data.wayPoints[i].passengersDelta.children._out > 0 ? '[ -' + objStepsData.data.wayPoints[i].passengersDelta.children._out + ' ]' : '');
                cell.append(getSimpleTextBlock(in_out + " " + OB_Children));
            }
            if (objStepsData.data.wayPoints[i].passengersDelta.old._in > 0 || objStepsData.data.wayPoints[i].passengersDelta.old._out > 0) {
                in_out = (objStepsData.data.wayPoints[i].passengersDelta.old._in > 0 ? '[ +' + objStepsData.data.wayPoints[i].passengersDelta.old._in + ' ]' : '') + (objStepsData.data.wayPoints[i].passengersDelta.old._out > 0 ? '[ -' + objStepsData.data.wayPoints[i].passengersDelta.old._out + ' ]' : '');
                cell.append(getSimpleTextBlock(in_out + " " + OB_Wheelchear_Title));
            }

            row.append(cell);
            placeholder.append(row);
            placeholder.append(getWhiteSpaceBlockObj());
        }
    }
}
//#endregion

//*XSLT
//var OB_Bus = "Bus";
//var OB_Type = "Type";
//var OB_Ordering = "Catering";

//#region insertOtherInformation()
function insertOtherInformation() {
    var placeholder = $('#summary_c3');
    placeholder.find('div').remove();
    placeholder.append(getHeaderTextBlock(OB_Bus + ': ' + objStepsData.data.busNo).attr('style', 'color:#4b8a3b;'));
    placeholder.append(getWhiteSpaceBlockObj());
    var row = getRow();
    row.append(getRowCell().append(getHeaderTextBlock(OB_Type + ": ").attr('style', 'width: 40px;')));
    row.append(getRowCell().append(getSimpleTextBlock(objStepsData.data.busType)));
    placeholder.append(row);
    placeholder.append(getWhiteSpaceBlockObj());
    placeholder.append(getLineSpacerBlock());

    placeholder.append(getHeaderTextBlock(OB_Ordering + ':').attr('style', 'color:#4b8a3b;'));
    placeholder.append(getWhiteSpaceBlockObj());

    var inner_c = 1;
    for (var wpc = 1; wpc < objStepsData.data.wayPoints.length; wpc++) {
        var resorted = Array();
        for (var i = 0; i < objStepsData.data.orderedServices.length; i++) {
            if (objStepsData.data.orderedServices[i] != null && objStepsData.data.orderedServices[i].serveUntilKey == wpc) {
                resorted.push({
                    name: objStepsData.data.orderedServices[i].name,
                    count: objStepsData.data.orderedServices[i].count
                });
            }
        }
        if (resorted.length > 0) {
            var row = getRow();
            row.append(getRowCell().append(getHeaderTextBlock(inner_c + ".").attr('style', 'width: 15px;')));
            var cell = getRowCell();
            cell.append(getHeaderTextBlock(objStepsData.data.wayPoints[wpc].address));

            for (var i in resorted) {
                cell.append(getSimpleTextBlock(resorted[i].name + (resorted[i].count > 0 ? " : " + resorted[i].count : "")));
            }

            row.append(cell);
            placeholder.append(row);
            inner_c++;
        }
    }
}
//#endregion

//#region getAdressDetails(resp)
// usage: geocode.getLocations(latlng, getAdressDetails);
//    or  geocode.getLocations('Lviv', getAdressDetails);
function getAdressDetails(resp) {
    var res = {
        address: '',
        street: '',
        zipcode: '',
        country: '',
        city: '',
        lat: '',
        lng: ''
    };
    if (resp.Status.code == G_GEO_SUCCESS && resp.Placemark.length > 0) {
        var pl = resp.Placemark[0];
        for (var i = 1; i < resp.Placemark.length; i++) {
            if (resp.Placemark[i].AddressDetails.Accuracy > pl.AddressDetails.Accuracy) {
                pl = resp.Placemark[i];

            }
        }
        res.address = pl.address;
        res.street = FindObjectField(pl, 'ThoroughfareName') || '';
        res.zipcode = FindObjectField(pl, 'PostalCodeNumber') || '';
        res.country = FindObjectField(pl, 'CountryNameCode') || '';
        res.countryName = FindObjectField(pl, 'CountryName') || '';
        res.city = FindObjectField(pl, 'LocalityName') || '';
        res.lat = pl.Point.coordinates[1];
        res.lng = pl.Point.coordinates[0];
    }
    return res;
}
//#endregion

//#region getPlacemarkDetails(placemark)
function getPlacemarkDetails(placemark) {
    var res = {
        address: '',
        street: '',
        zipcode: '',
        country: '',
        city: '',
        lat: '',
        lng: ''
    };

    res.address = placemark.address;
    res.street = FindObjectField(placemark, 'ThoroughfareName') || '';
    res.zipcode = FindObjectField(placemark, 'PostalCodeNumber') || '';
    res.country = FindObjectField(placemark, 'CountryNameCode') || '';
    res.countryName = FindObjectField(placemark, 'CountryName') || '';
    res.city = FindObjectField(placemark, 'LocalityName') || '';
    res.lat = placemark.Point.coordinates[1];
    res.lng = placemark.Point.coordinates[0];

    return res;
}
//#endregion

//#region FindObjectField(obj, fieldName)
function FindObjectField(obj, fieldName) {
    if (obj == null || typeof (obj) != 'object')
        return null;

    for (var key in obj) {
        if (key == fieldName) {
            return obj[key];
        } else {
            var t = FindObjectField(obj[key], fieldName);
            if (t !== null) {
                return t;
            }
        }
    }
    return null;
}
//#endregion

