/* Minification failed. Returning unminified contents.
(2885,40-41): run-time error JS1195: Expected expression: .
(2885,41-42): run-time error JS1010: Expected identifier: .
(2885,42-43): run-time error JS1010: Expected identifier: .
(2885,81-82): run-time error JS1004: Expected ';': ]
(2893,14-15): run-time error JS1195: Expected expression: )
(2894,9-10): run-time error JS1002: Syntax error: }
(2900,59-60): run-time error JS1195: Expected expression: )
(2900,61-62): run-time error JS1004: Expected ';': {
(2902,10-11): run-time error JS1195: Expected expression: )
(2904,52-53): run-time error JS1195: Expected expression: )
(2904,54-55): run-time error JS1004: Expected ';': {
(2906,10-11): run-time error JS1195: Expected expression: )
(2908,56-57): run-time error JS1195: Expected expression: )
(2908,58-59): run-time error JS1004: Expected ';': {
(2910,10-11): run-time error JS1195: Expected expression: )
(2913,81-82): run-time error JS1004: Expected ';': {
(2968,1-2): run-time error JS1002: Syntax error: }
(2969,2-10): run-time error JS1197: Too many errors. The file might not be a JavaScript file: function
(2909,13-132): run-time error JS1018: 'return' statement outside of function: return me.requestPaymentStatus() !== $paramount.EVENT_PAYMENT_STATUS.NOT_AVAILABLE && me.eventOrganiserOwedAmount() > 0
(2905,13-97): run-time error JS1018: 'return' statement outside of function: return me.requestPaymentStatus() === $paramount.EVENT_PAYMENT_STATUS.REQUEST_PENDING
(2901,13-97): run-time error JS1018: 'return' statement outside of function: return me.requestPaymentStatus() !== $paramount.EVENT_PAYMENT_STATUS.REQUEST_PENDING
 */
(function ($, $p) {

    function CategoryService(baseUrl) {
        this.baseUrl = baseUrl || $p.baseUrl;
    }

    CategoryService.prototype.getParentCategories = function () {
        return $.ajax({ url: this.baseUrl + 'Categories/GetCategories' });
    }

    CategoryService.prototype.getChildCategories = function (parentId) {
        return $.ajax({ url: this.baseUrl + 'Categories/GetCategories?parentId=' + parentId });
    }

    CategoryService.prototype.isOnlineOnly = function (id) {
        return $p.httpPost(this.baseUrl + 'Categories/IsOnlineOnlyCategory', { id: id });
    }

    $p.CategoryService = CategoryService;

})(jQuery, $paramount);;
(function ($, google) {

    if (!google) {
        return;
    }

    if (!google.maps) {
        return;
    }

    $(function () {

        /*
         * Renders the google map on the required div marked with .google-map class
         * Required attributes: 
         * data-langitude
         * data-longitude
         * data-address (for displaying tooltip marker)
         */
        var $map = $('.google-map');
        if ($map.length === 0) {
            return;
        }
        var data = $map.data();
        var mapCanvas = $map.get(0);
        function initialize() {
            var latLng = new google.maps.LatLng(data.latitude, data.longitude);
            var mapOptions = {
                center: latLng,
                zoom: 15,
                mapTypeId: google.maps.MapTypeId.ROADMAP,
                scrollwheel: false
            };
            var map = new google.maps.Map(mapCanvas, mapOptions);

            var marker = new google.maps.Marker({
                position: latLng,
                title: data.address,
                visible: true
            });
            marker.setMap(map);
        }
        initialize();
    });

})(jQuery, google);;

var $paramount = (function (me, $) {

    function ImageService(baseUrl) {
        this.baseUrl = baseUrl || me.baseUrl;
    }

    ImageService.prototype.getImageUrl = function (id, dimensions) {
        // Default to the thumb size
        if (_.isUndefined(id) || _.isEmpty(id)) {
            return null;
        }
        dimensions = dimensions || {};
        _.defaults(dimensions, { h: 100, w: 200 });
        return me.baseUrl + 'img/' + id + '/' + dimensions.w + '/' + dimensions.h;
    }

    ImageService.prototype.cancelCropImage = function (filename) {
        return me.httpPost(this.baseUrl + 'Image/CancelCrop', { filename: filename });
    }

    ImageService.prototype.cropImage = function (fileName, x, y, width, height, resizeForPrint) {
        return me.httpPost(this.baseUrl + 'Image/CropImage', { fileName: fileName, x: x, y: y, width: width, height: height, resizeForPrint: resizeForPrint });
    }

    ImageService.prototype.uploadCropImageUrl = function () {
        return this.baseUrl + 'Image/UploadCropImage';
    }

    ImageService.prototype.renderCropImageUrl = function (filename) {
        return this.baseUrl + 'Image/RenderCropImage?fileName=' + filename;
    }

    ImageService.prototype.getUploadOnlineImageUrl = function () {
        return this.baseUrl + 'Image/UploadOnlineImage';
    }

    ImageService.prototype.getUploadEventFloorplanUrl = function () {
        return this.baseUrl + 'Image/UploadEventFloorplanUrl';
    }

    me.ImageService = ImageService;

    // Return the module/namespace
    return me;

})($paramount, jQuery);

;
/*
 * Extends knockout by adding extra bindings for elements
 */

(function (knockout, $) {


    /*
     * Usage : <input type='text' data-bind='date: modelProperty' />
     */
    ko.bindingHandlers.date = {
        init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
            var value = valueAccessor();
            var date = ko.unwrap(value);

            $(element)
                .attr('data-provide', "datepicker")
                .attr('readonly', "") // Prevents the user from inputting their own value
                .attr('placeholder', 'Click here to show calendar ...')
                .addClass('bs-date-picker') // Prevents the user from inputting their own value
                .val(date)
                .datepicker({
                    autoclose: true,
                    format: 'dd/mm/yyyy',
                    todateBtn: true,
                    todayHighlight: true,
                    startDate: new Date(),
                    orientation: 'bottom'
                })
                .on('changeDate', function () {
                    var changedDate = $(element).val();
                    value(changedDate);
                });
        },
        update: function (element, valueAccessor) {
            var newValue = ko.unwrap(valueAccessor());
            if (newValue === null) {
                $(element).val(''); // Force to clear the textbox
            }
        }
    };
    ko.validation.makeBindingHandlerValidatable('date');

    /*
     * Google Map
     * Usage : <input type='text' data-bind="googleMap: modelProperty, mapElement : '#LocationMap'" />
     */
    ko.bindingHandlers.googleMap = {
        init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
            var existingValue = valueAccessor();
            var address = ko.unwrap(existingValue);

            var $map = $(allBindings.get('mapElement'));

            if ($map.length === 0) {
                throw "googleMap binding requires a map binding";
            }

            function assignMapValueToObservable(componentType, observable, propertyName, value) {
                if (_.isUndefined(observable)) {
                    return false;
                }
                if (componentType === propertyName) {
                    observable(value);
                }
                return true;
            }

            var googleMap = $(element).val(address)
                .geocomplete({
                    country: "AU",
                    type: ['(regions)'],
                    map: $map,
                    markerOptions: {
                        draggable: false
                    }
                })
                .bind('geocode:result', function (event, geoData) {
                    viewModel.location(geoData["formatted_address"]);
                    viewModel.locationLatitude(geoData.geometry.location.lat());
                    viewModel.locationLongitude(geoData.geometry.location.lng());

                    // Capture every map component
                    _.each(geoData.address_components, function (comp) {
                        _.each(comp.types, function (t) {
                            assignMapValueToObservable(t, viewModel.streetNumber, 'street_number', comp.long_name);
                            assignMapValueToObservable(t, viewModel.streetName, 'route', comp.long_name);
                            assignMapValueToObservable(t, viewModel.suburb, 'locality', comp.long_name);
                            assignMapValueToObservable(t, viewModel.state, 'administrative_area_level_1', comp.long_name);
                            assignMapValueToObservable(t, viewModel.postCode, 'postal_code', comp.long_name);
                            assignMapValueToObservable(t, viewModel.country, 'country', comp.long_name);
                        });
                    });

                });

            // Bind the current address if any
            if (address) {
                googleMap.geocomplete('find', address);
            }
        }
    }
    ko.validation.makeBindingHandlerValidatable('googleMap');

    /*
     * Toggle button
     */
    ko.bindingHandlers.toggle = {
        init: function (element, valueAccessor) {
            var $element = $(element),
                observable = valueAccessor();

            // Set the current value
            if (observable() === true) {
                $element.attr('checked', 'checked');
            }

            $element.bootstrapToggle().on('change', function (e) {
                observable($element.prop('checked'));
            });
        }
    }

    /*
    *   Bounce in animation
    */
    ko.bindingHandlers.bounceInDown = {
        init: function (element, valueAccessor) {
            var value = valueAccessor();
            $(element).toggle(ko.unwrap(value));
            $(element).addClass('animated');
        },
        update: function (element, valueAccessor) {
            var value = valueAccessor();
            var isVisible = ko.unwrap(value);
            $(element).toggleClass('bounceInDown', isVisible);
            $(element).toggle(isVisible);
        }
    }


    /*
     * New date selector (with time)
     */
    ko.bindingHandlers.datetime = {
        init: function (element, valueAccessor, allBindingsAccessor) {
            //initialize datepicker with some optional options

            var options = allBindingsAccessor().dateTimePickerOptions || {};
            options.format = $paramount.jsToDisplayDateFormat;
            $(element).datetimepicker(options);

            //when a user changes the date, update the view model
            ko.utils.registerEventHandler(element, "dp.change", function (event) {
                var value = valueAccessor();
                if (ko.isObservable(value)) {
                    if (event.date !== null && !(event.date instanceof Date)) {
                        value(event.date.toDate());
                    } else {
                        value(event.date);
                    }
                }
            });

            ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
                var picker = $(element).data("DateTimePicker");
                if (picker) {
                    picker.destroy();
                }
            });
        },
        update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {

            var picker = $(element).data("DateTimePicker");

            if (picker) {
                var koDate = ko.utils.unwrapObservable(valueAccessor());

                //in case return from server datetime i am get in this form for example /Date(93989393)/ then fomat this
                //koDate = (typeof (koDate) !== 'object') ? new Date(parseFloat(koDate.replace(/[^0-9]/g, ''))) : koDate;

                koDate = $paramount.dateFromServer(koDate);

                picker.date(koDate);
            }
        }
    };

    /*
    *   Type Ahead - https://github.com/bassjobsen/Bootstrap-3-Typeahead
    */
    ko.bindingHandlers.typeahead = {
        init: function (element, valueAccessor, allBindingsAccessor) {
            var $element = $(element);
            var allBindings = allBindingsAccessor();
            var source = ko.utils.unwrapObservable(valueAccessor());
            var items = ko.utils.unwrapObservable(allBindings.items) || 8;

            var valueChange = function (item) {
                if (allBindings.onItemSelected) {
                    allBindings.onItemSelected(item);
                }
                return item;
            };

            var options = {
                source: source,
                items: items,
                updater: valueChange
            };

            $element
                .attr('autocomplete', 'off')
                .typeahead(options);
        }
    };


    /*
    *   This is very important and it is what wires up all our validation 
    */
    ko.validation.makeBindingHandlerValidatable('datetime');


    /*
    *   Charts
    */

    ko.bindingHandlers.chart = {
        update: function (element, valueAccessor, allBindings) {

            var ctx = element.getContext("2d");
            var chartTypeValue = valueAccessor();
            var chartType = ko.unwrap(chartTypeValue);
            var chartData = ko.unwrap(allBindings.get('data'));

            var chart = new Chart(ctx, {
                type: chartType,
                data: chartData
            });
        }
    }


    /*
    *
    */
    var imageService = new $paramount.ImageService();

    ko.bindingHandlers.upload = {
        init: function (element, valueAccessor) {
            var $rootElement = $(element);
            var $uploadElement = $rootElement.find('input[type=file]');
            var $progressElement = $rootElement.find('.upload-progress');
            
            $paramount.upload({
                url: imageService.getUploadOnlineImageUrl(),
                element: $uploadElement,
                progressBar: $progressElement,
                complete: function (documentId) {
                    var value = valueAccessor();
                    value(documentId);
                },
                error: function (errorMsg) {
                    console.error('error', errorMsg);
                }
            });
        }
    }

})(ko, jQuery);;
/*
 * Contains any knockout extensions we may need
 */

(function (ko) {
    
    /*
     * subscribeChanged method exposes the old and new value in the callback
     * e.g. this.observableValue.subscribeChanged(function(oldValue, newValue){ })
     */
    ko.subscribable.fn.subscribeChanged = function (callback) {
        var oldValue;
        this.subscribe(function (_oldValue) {
            oldValue = _oldValue;
        }, this, 'beforeChange');

        var subscription = this.subscribe(function (newValue) {
            callback(oldValue, newValue);
        });

        return subscription;
    };


})(ko);;
/*
 * This allows ko components to look like the following where we can specify the full path to the template html:
 * ko.components.register('ticket-selection', {
        viewModel: ...,
        template: { path: $paramount.baseUrl + '/Scripts/app/events/ticketSelection/ticket-selection.html' }
    });
 */
ko.components.loaders.unshift({
    loadTemplate: function (name, templateConfig, callback) {
        if (templateConfig.path) {
            $.get(templateConfig.path).then(function (markup) {
                ko.components.defaultLoader.loadTemplate(name, markup, callback);
            });
        } else {
            callback(null); // continue process knockout stuff...
        }
    }
});
;
/*
 * Sets up the global settings for the bootstrap validation styling
 */


(function (ko, dateService) {

    ko.validation.init({
        errorElementClass: 'has-error',
        errorMessageClass: 'help-block',
        decorateInputElement: true,
        grouping: {
            deep: true,
            live: true,
            observable: true
        }
    });


    /*
     * Min date validation
     * example : 
     * me.validator = ko.validatedObservable({
            closingDate: me.closingDate.extend({
                pmtMinDate: new Date(data.adStartDate)
            })
        });
     */

    ko.validation.rules['pmtMinDate'] = {
        validator: function (val, otherVal) {
            if (typeof val === 'undefined' || val === null) {
                return true;
            }

            var minDate = dateService(otherVal);
            var selectedDate = dateService(val, "DD/MM/YYYY");

            return minDate.isBefore(selectedDate);
        },
        message: 'Must be a later date'
    }

    ko.validation.rules['mustBeAfter'] = {
        validator: function (val, comparisonVal) {
            if (!val) {
                return false;
            }

            if (!comparisonVal) {
                return false;
            }

            return moment(comparisonVal).isBefore(moment(val));
        },
        message: 'Must be a later date'
    };

    ko.validation.rules['mustNotEqual'] = {
        validator: function (val, comparisonVal) {
            if (!val) {
                return false;
            }

            if (!comparisonVal) {
                return false;
            }

            return val.trim() !== comparisonVal.trim();
        },
        message : 'Must not equal this value.'
    };

    ko.validation.registerExtenders();
    
})(ko, moment);;
/*
** $paramount utility class
*/
(function ($paramount, $window, $, $mobileDetect, htmlEditor) {

    var me = this;
    me.isMobileDevice = null;

    $paramount.jsToServerDateFormat = "YYYY-MM-DD HH:mm";   // How we talk to the server
    $paramount.jsToDisplayDateFormat = "DD/MM/YYYY HH:mm";  // How we display in browser

    $paramount.dateToServerString = function (date) {
        ///<summary>Returns a string ready to be converted to the .Net parsable on the server</summary>
        if (!date) {
            return null;
        }
        return moment(date).format($paramount.jsToServerDateFormat);
    }

    $paramount.dateFromServer = function (date) {
        ///<summary>Returns a moment date object after being parsed from the server</summary>
        if (!date) {
            return null;
        }

        return moment(date, $paramount.jsToServerDateFormat);
    }

    $paramount.dateToDisplay = function (date) {
        if (!date) {
            return '';
        }

        return moment(date).format($paramount.jsToDisplayDateFormat);
    }

    $paramount.isUtcDateBeforeNow = function (utcDate) {
        return moment.utc(utcDate).local().isBefore(moment());
    }

    $paramount.getRandomColor = function () {
        var letters = '0123456789ABCDEF';
        var color = '#';
        for (var i = 0; i < 6; i++) {
            color += letters[Math.floor(Math.random() * 16)];
        }
        return color;
    }


    /*
     * Constants
     */
    $paramount.PAYMENT = {
        PAYPAL: 'PayPal',
        DIRECT_DEBIT: 'DirectDebit'
    }

    $paramount.EVENT_PAYMENT_STATUS = {
        CLOSE_EVENT_FIRST: 'Close Event First',
        REQUEST_PENDING: 'Request Pending',
        NOT_AVAILABLE: 'Not Available'
    }

    $paramount.CATEGORY_AD_TYPE = {
        EVENT: 'Event'
    }

    // Lazy loading for mobile checking
    me.evaluateMobile = function () {
        if (isMobileDevice !== null) {
            return isMobileDevice;
        }
        var detector = new $mobileDetect($window.navigator.userAgent);
        me.isMobileDevice = detector.mobile() !== null;
        return me.isMobileDevice;
    };

    /*
     * Utility function to guard against undefined parameters
     */
    $paramount.guard = function (val, name) {
        if (_.isUndefined(val)) {
            throw new Error(name + ' must be defined');
        }
    };

    $paramount.formatCurrency = function (value) {
        if (value === undefined || value === null)
            return '';

        if (typeof value === "string") {
            value = Number.parseFloat(value);
        }

        return "$" + value.toFixed(2);
    };

    $paramount.isMobile = function () {
        return evaluateMobile();
    };

    $paramount.setOnlineEditor = function (element) {
        if (me.evaluateMobile()) {
            return null;
        }

        $paramount.onlineEditor = htmlEditor.replace(element);

        return $paramount.onlineEditor;
    };

    $paramount.delay = (function () {
        var timer = 0;
        return function (callback, ms) {
            clearTimeout(timer);
            timer = setTimeout(callback, ms);
        };
    })();

    /*
     * File upload control
     */
    $paramount.upload = function (options) {

        $paramount.guard(options, 'options');
        $paramount.guard(options.url, 'url');
        $paramount.guard(options.element, '');

        options.progressBar = options.progressBar || $('<div><span class=".progress-bar"></span></div>'); // Todo - popup a real progress bar somewhere
        options.progressBar.hide();
        options.complete = options.complete || function () { };
        options.completeWithDetails = options.completeWithDetails || function () { };
        options.start = options.start || function () { };
        options.error = options.error || function () { };

        var upload = options.element.fileupload({
            dataType: 'json',
            url: options.url,
            autoUpload: true,
            singleFileUploads: false
        });

        upload.on('fileuploaddone', function (e, data) {
            if (data.result.documentId) {
                options.complete(data.result.documentId);
                options.completeWithDetails(data.result);
            } else {
                options.error(data.result.errorMsg);
            }
        });

        upload.on('fileuploadstart', function (data) {
            // Start showing the progress bar
            options.progressBar.show();
            options.start(data);
        });

        upload.on('fileuploadalways', function () {
            // Reset the width of the progress bar
            options.progressBar.hide();
            options.progressBar.find('.progress-bar').width('0');
        });

        upload.on('fileuploadprogressall', function (e, data) {
            var progress = parseInt(data.loaded / data.total * 100, 10);
            options.progressBar.find('.progress-bar').css('width', progress + '%');
        });

        upload.on('fileuploadadd', function (e, data) {
            if (data.files.length > 1) {
                options.error("Please select one image at a time.");
                return false;
            }
            return true;
        });
    };

    /*
     * Puts focus on the first element with an error
     */
    $paramount.goToFirstError = function () {
        $('.has-error input').first().focus();
    }

    /*
     * Checks the knockout object validator property
     */
    $paramount.checkValidity = function () {
        var result = true;
        for (var i = 0; i < arguments.length; i++) {
            var obj = arguments[i];

            if (obj.constructor === Array) {
                for (var j = 0; j < obj.length; j++) {
                    // Recursive call
                    result = $paramount.checkValidity(obj[j]);
                }

            } else {

                // Loop through each property of the object
                for (var p in obj) {
                    if (p === 'validator') {
                        // Execute it
                        if (obj[p].isValid() === false) {
                            result = false;
                            obj[p].errors.showAllMessages();
                        }
                    } else if (isObservableArray(obj[p])) {
                        ko.utils.arrayForEach(obj[p](), function (i) {
                            result = $paramount.checkValidity(i);
                        });
                    }
                }
            }
        };

        if (result === false) {
            // Show all messages (from knockout validation library) would trigger the error msgs to fire
            // So make the call to focus on the first error
            $paramount.goToFirstError();
        }

        return result;
    }

    function isObservableArray(obj) {
        return ko.isObservable(obj) && !(obj.destroyAll === undefined);
    }

    $paramount.notNullOrUndefined = function (arg) {
        if (typeof arg === 'undefined') {
            return false;
        }
        if (arg === null) {
            return false;
        }
        return true;
    }

    $paramount.isNullOrUndefined = function (arg) {
        return $paramount.notNullOrUndefined(arg) === false;
    }

    $paramount.ko = {
        bindArray: function (collection, creator) {
            /// <summary>Creates a new knockout observableArray where each item is created by the creator callback</summary>
            var observableArray = ko.observableArray();
            _.forEach(collection, function (item) {
                observableArray.push(creator(item));
            });
            return observableArray;
        }
    }

    $paramount.encodeQuery = function (obj) {
        var str = [];
        for (var p in obj)
            if (obj.hasOwnProperty(p)) {
                str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
            }
        return str.join("&");
    }

    $paramount.processPromises = function (funcsWithPromises, cb) {
        /// <summary>Will process each promise one by one which is very useufl in http calls to not flood the server.</summary>  
        /// <param name="funcsWithPromises" type="Array">The collection of methods when executed will return a Promise.</param>  
        /// <param name="cb" type="function">Callback function that is executed whenever each promise is returned and will contain the result as the first parameter.</param>  
        /// <returns type="Number">Promise</returns>  

        $paramount.guard(funcsWithPromises);
        $paramount.guard(cb);

        if (!_.isArray(funcsWithPromises)) {
            throw new Error('funcs must be an array');
        }

        return new Promise(function (resolve) {

            var processCount = 0;
            next(); // start the recurse

            function next() {
                if (processCount >= funcsWithPromises.length) {
                    return resolve('done'); // Finished
                }

                return funcsWithPromises[processCount]().then(function (result) {
                    cb(result);
                    processCount++;
                    next();
                });
            }

        });
    }

    $paramount.isFunction = function (functionToCheck) {
        var getType = {};
        return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
    }

    return me;

})($paramount, window, jQuery, MobileDetect, CKEDITOR);


;
$paramount.social = (function($) {
    
    /*
     * Facebook sharing event handler
     */
    return {
        setupFacebook : function(facebookBtn, data) {
            var facebookShareData = _.extend({
                method: 'share'
            }, data);

            facebookBtn.on('click', function () {
                FB.ui(facebookShareData, function(response) {});
            });
        }
    }
})(jQuery);;

/*
** General element hooks for the entire website (jQuery)
*/

(function ($) {

    $(function () {

        // Global ajax error handler
        $.ajaxSetup({
            error: function (err) {
                if (err.status === 404 || err.status === 500) {
                    toastr.error('Oh no. Something is not wired properly. Our team will be notified and apply fix shortly.');
                }
                else {
                    toastr.error('Oh no. We were unable to connect to our server. Check your internet connection and try again.');
                }
            }
        });

        // Every submit form button will have a Please Wait... while submitting the form to server ( non-ajax )
        var loadingText = 'Please wait...';
        $('form').find('button[type=submit]').attr('data-loading-text', loadingText);
        $('form').submit(function () {
            if ($(this).valid()) {
                $(this).find('button[type=submit]').button('loading');
            }
        });
        $('button.ko-load').attr('data-loading-text', loadingText);
        $('button.js-load, a.js-load').attr('data-loading-text', loadingText).on('click', function () { $(this).button('loading'); });

        // Any captcha input should add the form-control css class
        $('#CaptchaInputText').addClass("form-control");

        // Online Ad location should load areas
        $('#OnlineAdLocationId').on('change', function () {
            $('#OnlineAdLocationAreaId').loadLocationAreas($(this).val(), false);
        });

        // Wire up the bootstrap tooltips
        $("[rel='tooltip']").tooltip();

        // Wire up js-select dropdowns
        $('.js-select').each(function () {
            var me = $(this);
            me.attr('disabled', 'disabled');
            me.append('<option>Loading...</option>');
            var url = me.data().url;
            var selected = me.data().selected;
            $.getJSON(url).done(function (data) {
                me.empty();
                $.each(data, function (index, option) {
                    if (selected == option.value) {
                        me.append('<option selected value="' + option.value + '">' + option.text + '</option>');
                    } else {
                        me.append('<option value="' + option.value + '">' + option.text + '</option>');
                    }
                });
                me.removeAttr('disabled');
            });
        });

        // Buttons that navigate    
        $('button[data-nav]').on('click', function () {
            window.location = $(this).data().nav;
            return false;
        });

        // Wire up the datepickers (using bootstrap-datepicker.js library)
        $('.datepicker').datepicker({
            autoclose: true,
            format: 'dd/mm/yyyy',
            todateBtn: true,
            todayHighlight: true,
            startDate: new Date()
        });

        $('input[data-numbers-only]').on('keypress', function (e) {
            if ((e.which < 48 || e.which > 57)) {
                if (e.which == 8 || e.which == 46 || e.which == 0) {
                    return true;
                }
                else {
                    return false;
                }
            }
        });

        // JQuery validation extensions
        $.validator.methods.date = function (value, element) {
            return this.optional(element) || moment(value, 'dd/MM/yyyy').isValid();
        };

        /*
         * jQuery extensions
         */
        $.fn.extend({
            loadSubCategories: function (parentCategoryId) {
                var me = this;
                me.empty();
                if (parentCategoryId === "") {
                    me.addClass('hidden');
                    return me;
                }
                me.attr('disabled', 'disabled').append('<option>Loading...</option>');

                var service = new $paramount.CategoryService();
                service.getChildCategories(parentCategoryId).done(function (data) {
                    me.empty().append('<option>-- Sub Category --</option>');
                    $.each(data, function (index, option) {
                        me.append('<option value=' + option.categoryId + '>' + option.title + '</option>');
                    });
                    me.removeAttr('disabled').removeClass('hidden');
                });
                return me;
            },
            loadLocationAreas: function (locationId) {
                var me = this;
                me.empty();
                if (locationId === "") {
                    me.addClass('hidden');
                    return me;
                }
                me.attr('disabled', 'disabled').append('<option>Loading...</option>');

                var locationService = new $paramount.LocationService();

                locationService.getLocationAreas(locationId).done(function (data) {
                    me.empty();
                    $.each(data, function (index, option) {
                        me.append('<option value=' + option.value + '>' + option.text + '</option>');
                    });
                    me.removeAttr('disabled').removeClass('hidden');
                });
                return me;
            },
            loadBtn: function () {
                this.button('loading');
                return this;
            },
            resetBtn: function () {
                this.button('reset');
                return this;
            }
        });
    });

})(jQuery);;
/*
** Support for styling the bootstrap elements using jquery unobtrusive validation library
** See http://stackoverflow.com/questions/11468130/twitter-bootstrap-integration-to-asp-net-mvc-validation/14651140#14651140
*/


(function ($) {
    $.validator.setDefaults({
        highlight: function (element, errorClass, validClass) {
            if (element.type === 'radio') {
                this.findByName(element.name).addClass(errorClass).removeClass(validClass);
            } else {
                $(element).addClass(errorClass).removeClass(validClass);
                $(element).closest('.form-group, .form-group-lg').removeClass('has-success').addClass('has-error');
            }
        },
        unhighlight: function (element, errorClass, validClass) {
            if (element.type === 'radio') {
                this.findByName(element.name).removeClass(errorClass).addClass(validClass);
            } else {
                $(element).removeClass(errorClass).addClass(validClass);
                $(element).closest('.form-group, .form-group-lg').removeClass('has-error').addClass('has-success');
            }
        }
    });

    // Wire up the on ready
    $(function () {
        $("span.field-validation-valid, span.field-validation-error").addClass('help-block');
        $("div.form-group").has("span.field-validation-error").addClass('has-error');
        $("div.validation-summary-errors").has("li:visible").addClass("alert alert-block alert-danger");
    });

}(jQuery));;
(function ($, ko, $paramount) {
    
    function DynamicFieldDefinition(parent, data) {
        var me = this;
        me.fieldName = ko.observable().extend({
            validation: {
                validator: function (name, params) {
                    var allFields = params.parent.eventTicketFields.peek();

                    var otherFields = _.filter(allFields, function (row) {
                        return row !== params.currentRow;
                    });

                    var otherFieldNames = _.map(otherFields, function (f) {
                        return f.fieldName.peek();
                    });

                    return !_.includes(otherFieldNames, name);

                },
                message: 'Field Name must be unique',
                params: {
                    currentRow: me,
                    parent: parent
                }
            }
        });
        me.isRequired = ko.observable();
        me.showFieldNameWarning = ko.computed(function () {
            if (me.fieldName()) {
                var val = me.fieldName().toLowerCase();
                return (val.indexOf('name') !== -1) || (val.indexOf('email') !== -1);
            }
            return false;
        });

        if (data) {
            this.bindDynamicFieldDefinition(data);
        }

        // Validation
        me.validator = ko.validatedObservable({
            fieldName: me.fieldName.extend({ required: true })
        });
    }

    DynamicFieldDefinition.prototype.bindDynamicFieldDefinition = function (data) {
        var me = this;
        me.fieldName(data.fieldName);
        me.isRequired(data.isRequired);
    }

    $paramount.models = $paramount.models || {};
    $paramount.models.DynamicFieldDefinition = DynamicFieldDefinition;

})(jQuery, ko, $paramount);;
(function ($, ko, $paramount) {
    
    function DynamicFieldValue(data) {
        var me = this;
        me.fieldName = ko.observable();
        me.fieldValue = ko.observable();
        me.isRequired = ko.observable();

        if ($paramount.notNullOrUndefined(data)) {
            this.bindDynamicFieldValue(data);

            // Validation
            me.validator = ko.validatedObservable({
                fieldValue: me.fieldValue.extend({ required: data.isRequired })
            });
        }
    }

    DynamicFieldValue.prototype.bindDynamicFieldValue = function (data) {
        var me = this;
        me.fieldName(data.fieldName);
        me.fieldValue(data.fieldValue);
        me.isRequired(data.isRequired);
    }

    $paramount.models = $paramount.models || {};
    $paramount.models.DynamicFieldValue = DynamicFieldValue;

})(jQuery, ko, $paramount);;
(function ($, ko, $paramount) {

    $paramount.ui = $paramount.ui || {};
    $paramount.ui.home = {
        init: function () {

            var baseUrl = $paramount.baseUrl;

            var $linksRootEl = $('.categories-links');
            if ($linksRootEl.length > 0) {
                var categoryService = new $paramount.CategoryService(baseUrl);

                categoryService.getParentCategories().then(function (data) {
                    var vm = new $paramount.models.CategoryLinks(data);
                    ko.applyBindings(vm, $linksRootEl.get(0));
                });
            }

            var $eventList = $('#eventList');
            if ($eventList.length > 0) {
                ko.applyBindings({}, $eventList.get(0));
            }

            var $adList = $('#adList');
            if ($adList.length > 0) {
                ko.applyBindings({}, $adList.get(0));
            }
        }
    }


})(jQuery, ko, $paramount);;
(function ($, $p) {

    var $adEditor = $('#editAdForm');

    $p.editAd = {
        init: function (designAdModel, adService) {

            var imageService = new $p.ImageService();

            $(function () {
                // Set online editor
                $p.setOnlineEditor('OnlineAdDescription');

                // Upload online images
                $p.upload({
                    url: imageService.getUploadOnlineImageUrl(),
                    element: $adEditor.find('#fileupload'),
                    progressBar: $adEditor.find('#onlineImages .progress'),
                    start: function () {
                        // Start
                        designAdModel.errorMsg('');
                        designAdModel.uploadImageInProgress(true);
                    },
                    complete: function (fileId) {
                        adService.assignOnlineImage(fileId)
                            .done(function () {
                                designAdModel.adImages.push(fileId);
                                designAdModel.uploadImageInProgress(false);
                            });
                    },
                    error: function (err) {
                        // Error
                        designAdModel.errorMsg(err);
                        designAdModel.uploadImageInProgress(false);
                    }
                });

                // Upload control for print
                var $printImg = $('#imgCropContainer > img');
                var printImgFileName;

                $p.upload({
                    url: imageService.uploadCropImageUrl(),
                    element: $adEditor.find('#fileuploadPrint'),
                    progressBar: $adEditor.find('#fileUploadPrintProgress'),
                    start: function () {
                    },
                    complete: function (fileName) {
                        printImgFileName = fileName;
                        $('#printCropImg').attr('src', imageService.renderCropImageUrl(fileName));
                        $('#printImageCropDialog').modal('show');
                    }
                });

                $('#printImageCropDialog').on('shown.bs.modal', function () {
                    $printImg.cropper({
                        aspectRatio: 1,
                        data: { x: 500, y: 500, height: 700, width: 700 },
                        modal: true,
                        dashed: false
                    });
                });

                $('#printImageCropDialog').on('hide.bs.modal', function (e) {
                    $printImg.cropper('destroy');
                });

                $('#btnDoneCropping').on('click', function () {
                    var $btn = $(this);
                    $btn.button('loading');
                    var data = $printImg.cropper("getData");
                    data.documentId = printImgFileName;
                    imageService
                        .cropImage(printImgFileName, data.x, data.y, data.width, data.height)
                        .done(function (documentId) {
                            $btn.button('reset');
                            $('#printImageCropDialog').modal('hide');
                            designAdModel.lineAdImageId(documentId);
                        });
                });

                $('#btnCancelCropping').on('click', function () {
                    if (printImgFileName) {
                        imageService.cancelCropImage(printImgFileName);
                    }
                });

                ko.applyBindings(designAdModel);
            });
        }
    }


})(jQuery, $paramount, $paramount.models);;

/*
** Supports the login view functionality
*/

(function ($) {

    // JQuery on-ready
    $(function () {

        // Forgot password functionality
        var $firstStep = $('#passwordResetModal #passwordReset');
        var $btn = $('#passwordResetModal #btnSubmit');
        var $emailInput = $('#passwordResetModal #EmailForRecovery');
        var $successMessage = $('#passwordResetModal #forgotPassword_Success');
        var $failMessage = $('#passwordResetModal #forgotPassword_Fail');

        $successMessage.hide();
        $failMessage.hide();

        $btn.on('click', function () {
            $btn.button('loading');
            $.post($firstStep.attr('data-url'), { email: $emailInput.val() })
                .done(function (data) {
                    if (data.errors) {
                        _.each(data.errors, function (e) {
                            var msg = e.value[0];
                            $successMessage.hide();
                            $failMessage.text(msg);
                            $failMessage.show();
                        });
                        return;
                    }
                    
                    $successMessage.show();
                    $failMessage.hide();
                    $btn.hide();
                })
                .always(function () {
                    $btn.button('reset');
                });
        });
    });

})(jQuery);;
(function ($, $paramount) {

    function UserAdService(baseUrl) {
        this.baseUrl = baseUrl || $paramount.baseUrl;
    }
    
    UserAdService.prototype.cancelAd = function (adId) {
        return $paramount.httpPost(this.baseUrl + 'UserAds/Cancel', { adId: adId });
    }

    UserAdService.prototype.startNewBookingFromTemplate = function (adId) {
        return $paramount.httpPost(this.baseUrl + 'Booking/StartFromTemplate', { id: adId });
    }
    
    UserAdService.prototype.getInvoiceUrl = function (adId) {
        return this.baseUrl + 'Invoice/Booking/' + adId;
    }
    
    $paramount.UserAdService = UserAdService;
    return $paramount;

})(jQuery, $paramount);;
(function ($p, $, ko) {

    $p.ui = $p.ui || {};

    $p.ui.userAdsUI = {

        init: function () {

            var $eventList = $('#eventList');
            if ($eventList.length > 0) {
                ko.applyBindings({}, $eventList.get(0));
            }

            var $adList = $('#adList');
            if ($adList.length > 0) {
                ko.applyBindings({}, $adList.get(0));
            }

        }
    }

})($paramount, jQuery, ko);;
(function ($p, ko, $) {


    function UserEnquiry(item) {
        this.id = ko.observable(item.id);
        this.fullName = ko.observable(item.fullName);
        this.email = ko.observable(item.email);
        this.enquiryText = ko.observable(item.question);
        this.createdDate = ko.observable(item.createdDate);

        this.mailtoLink = ko.observable('mailto:' + item.email);
    };


    // Assign the models/classes to the paramount models namespace
    $p.models = $p.models || {};
    $p.models.UserEnquiry = UserEnquiry;


})($paramount, ko, jQuery);;
(function () {

    ko.components.register('availability-options', {
        viewModel: function (params) {
            var me = this;

            this.availability = ko.observable("alwaysAvailable");

            if (isObservableDefinedAndNotNull(params.startDate) || isObservableDefinedAndNotNull(params.endDate)) {
                this.availability("specificDates");
            }

            this.startDate = params.startDate;
            this.endDate = params.endDate;

            // Optional parameters
            this.startDateLabel = params.startDateLabel || 'Start Date';
            this.endDateLabel = params.endDateLabel || 'End Date';
            this.showEndDate = _.isUndefined(params.showEndDate) ? true : params.showEndDate;
            this.dateOptionLabel = params.dateOptionLabel || 'Only for the following dates';

            this.availability.subscribe(function(newValue) {

                if (newValue === "alwaysAvailable") {
                    me.startDate(null);
                    if(me.endDate){
                        me.endDate(null);
                    }

                    if (params.alwaysAvailableSelected) {
                        params.alwaysAvailableSelected();
                    }
                }

            });
        },
        template: {
            path: $paramount.baseUrl + 'Scripts/app/availabilityOptions/availability-options.html'
        }
    });

    function isObservableDefinedAndNotNull(observable) {
        if (!_.isUndefined(observable) && !_.isNull(observable())) {
            return true;
        }
        return false;
    }

})(ko);;

// Ad Booking service
(function ($, $paramount) {

    var me = this;

    // Constructor
    function AdDesignService(adId) {
        $.extend(me, {
            // When editing an ad, we may always have to provide the ad id.
            // See AuthorizeBookingIdentity filter
            model: {
                id: adId
            },
            // If there adId is defined then we are pointing at the EditAdController
            baseUrl: _.isUndefined(adId)
                ? $paramount.baseUrl + 'Booking/'
                : $paramount.baseUrl + 'EditAd/'
        });
    };

    AdDesignService.prototype.updateBookingRates = function (model) {
        return $paramount.httpPost(me.baseUrl + 'GetRate', model);
    }

    AdDesignService.prototype.previewBookingEditions = function (firstEdition, insertions) {
        return $paramount.httpPost(me.baseUrl + 'PreviewEditions', {
            firstEdition: firstEdition,
            printInsertions: insertions
        });
    }

    AdDesignService.prototype.removePrintImg = function (documentId) {
        $.extend(me.model, {
            documentId: documentId
        });
        return $paramount.httpPost(me.baseUrl + 'RemoveLineAdImage', me.model);
    }

    AdDesignService.prototype.removeOnlineAdImage = function (documentId) {
        $.extend(me.model, {
            documentId: documentId
        });
        return $paramount.httpPost(me.baseUrl + 'RemoveOnlineImage', me.model);
    }

    AdDesignService.prototype.assignPrintImg = function (documentId) {
        $.extend(me.model, {
            documentId: documentId
        });
        return $paramount.httpPost(me.baseUrl + 'SetLineAdImage', me.model);
    }

    AdDesignService.prototype.assignOnlineImage = function (documentId, removeExisting) {
        $.extend(me.model, {
            documentId: documentId,
            removeExisting: removeExisting || false
        });
        return $paramount.httpPost(me.baseUrl + 'AssignOnlineImage', me.model);
    }

    AdDesignService.prototype.updateEventTicketDetails = function (eventBookingTicketSetup) {
        $.extend(me.model, eventBookingTicketSetup);
        return $paramount.httpPost(me.baseUrl + 'EventTickets', me.model);
    }

    AdDesignService.prototype.addEventTicket = function (eventTicket) {
        eventTicket.id = me.model.id;
        return $paramount.httpPost(me.baseUrl + 'AddTicket', eventTicket);
    }

    AdDesignService.prototype.requestEventPayment = function (paymentDetails) {
        $.extend(me.model, paymentDetails);
        return $paramount.httpPost(me.baseUrl + 'EventPaymentRequest', me.model);
    }

    AdDesignService.prototype.closeEvent = function (eventId) {
        $.extend(me.model, { eventId: eventId });
        return $paramount.httpPost(me.baseUrl + 'CloseEvent', me.model);
    }

    AdDesignService.prototype.setCategoryAndPublications = function (categoryPublicationModel) {
        return $paramount.httpPost(me.baseUrl + 'Step1', categoryPublicationModel);
    }

    AdDesignService.prototype.updateEventDetails = function (event) {
        $.extend(me.model, event);
        return $paramount.httpPost(me.baseUrl + 'UpdateEventDetails', me.model);
    }

    AdDesignService.prototype.addGuest = function (guest) {
        $.extend(me.model, guest);
        return $paramount.httpPost(me.baseUrl + 'add-guest', me.model);
    }

    AdDesignService.prototype.editGuestUrl = function (ticketNumber) {
        if ($paramount.notNullOrUndefined(me.model.id) === false) {
            throw 'Ad Id must be available to generate the edit-guest url';
        }

        return $paramount.baseUrl + 'event-dashboard/' + me.model.id + '/guest/' + ticketNumber;
    }

    AdDesignService.prototype.editGuest = function (guest) {
        $.extend(me.model, guest);
        var url = this.editGuestUrl(guest.eventBookingTicketId);
        return $paramount.httpPost(url, me.model);
    }

    AdDesignService.prototype.removeGuest = function (data) {
        $.extend(me.model, data);
        return $paramount.httpPost(me.baseUrl + 'remove-guest', me.model);
    }

    AdDesignService.prototype.getCurrentEventDetails = function () {
        var url = me.baseUrl + 'GetEventDetails';

        if ($paramount.notNullOrUndefined(me.model.id)) {
            url += '?id=' + me.model.id;
        }

        return $.getJSON(url);
    }

    AdDesignService.prototype.addEventGroup = function (eventGroup) {
        var url = me.baseUrl + 'AddEventGroup';
        $.extend(me.model, eventGroup);
        return $paramount.httpPost(url, me.model);
    }

    AdDesignService.prototype.toggleEventGroup = function (val) {
        var url = me.baseUrl + 'ToggleEventGroupStatus';
        $.extend(me.model, val);
        return $paramount.httpPost(url, me.model);
    }

    AdDesignService.prototype.editTicketSettings = function (eventId, settings) {
        settings.openingDate = $paramount.dateToServerString(settings.openingDate);
        settings.closingDate = $paramount.dateToServerString(settings.closingDate);
        var url = $paramount.baseUrl + 'event-dashboard/' + me.model.id + '/event/' + eventId + '/edit-ticket-settings';
        return $paramount.httpPost(url, settings);
    }

    AdDesignService.prototype.updateEventGroupSettings = function (settings) {
        return $paramount.httpPost(me.baseUrl + 'updateEventGroupSettings', $.extend(me.model, settings));
    }

    AdDesignService.prototype.editTicket = function (data) {
        $paramount.guard(data, 'data');
        $paramount.guard(data.eventTicket, 'data.eventTicket');

        var url = $paramount.baseUrl + "event-dashboard/" + me.model.id + '/event-ticket/' + data.eventTicket.eventTicketId;
        return $paramount.httpPost(url, $.extend(me.model, data));
    }

    AdDesignService.prototype.updateEventGuestSettings = function (model) {
        var url = $paramount.baseUrl + 'event-dashboard/' + me.model.id + '/event/' + model.eventId + '/guest-settings';
        return $paramount.httpPost(url, model);
    }

    AdDesignService.prototype.addSurveyOption = function (model) {
        var url = $paramount.baseUrl + 'event-dashboard/' + me.model.id + '/event/' + model.eventId + '/survey-option';
        return $paramount.httpPost(url, model);
    }

    AdDesignService.prototype.remove = function (adId) {
        var url = $paramount.baseUrl + 'userAds/cancel?adId=' + adId;
        return $paramount.httpPost(url, model);
    }


    // Exports
    $paramount.AdDesignService = AdDesignService;

    return $paramount;

})(jQuery, $paramount);;
(function ($, ko, $p) {
    
    $p.models = $p.models || {};

    $p.models.BookingCategorySelection = function (stepData) {
        var self = this;
        self.categoryId = ko.observable(stepData.categoryId);
        self.subCategoryId = ko.observable(stepData.subCategoryId);
        self.publications = ko.observableArray(stepData.publications);
        self.shouldShowSubCategory = ko.computed(function () {
            return self.categoryId() !== "";
        });
        
        self.togglePublication = function (pub) {
            if (!pub) {
                return;
            }

            if (pub.isSelected === 'undefined') {
                return;
            }

            pub.isSelected = !pub.isSelected;
        };
        self.errorMsg = ko.observable("");
    }

    $p.booking = $p.booking || {};
    $p.booking.stepOne = function (contract) {
        var adDesignService = new $p.AdDesignService();
        var categorySelection = new $p.models.BookingCategorySelection(contract);
        ko.applyBindings(categorySelection);

        $('#parentCategoryId').on('change', function () {
            var me = $(this);
            categorySelection.subCategoryId = ko.observable(null); // clear
            if (me.val() === '') {
                return;
            }
            $('#subCategoryId').loadSubCategories(me.val(), false);
        });


        $('#btnSubmit').on('click', function () {
            var $btn = $(this);
            $btn.loadBtn();
            var modelToPost = ko.toJS(categorySelection);
            
            // Validate
            if (isNaN(categorySelection.subCategoryId()) || categorySelection.subCategoryId() === null) {
                categorySelection.errorMsg('You must select a sub category for your ad');
                $(this).button('reset');
                $btn.resetBtn();
                return;
            }

            adDesignService.setCategoryAndPublications(modelToPost);
        });
    };

})(jQuery, ko, $paramount);;
(function ($, $paramount, ko) {

    $paramount.models = $paramount.models || {};

    $paramount.models.DesignAd = function (options) {

        var adService = options.adService,
            onlineImages = options.onlineImages,
            maxImages = options.maxImages,
            lineAd = options.lineAd,
            updateRates = options.updateRates,
            imageService = new $paramount.ImageService();

        var self = this;

        self.adId = options.adId;
        self.deleteAd = function () {
            adService.remove(self.adId);
        }

        // Online Images
        self.adImages = ko.observableArray(onlineImages);
        self.getImageUrl = function (id) {
            return imageService.getImageUrl(id);
        }
        self.errorMsg = ko.observable("");
        self.removeImage = function (img) {
            adService.removeOnlineAdImage(img)
                .done(function (result) {
                    if (result) {
                        self.adImages.remove(img);
                    }
                });
        };

        self.maxImages = ko.observable(maxImages);
        self.maxLimitNotReached = function () {
            return self.adImages().length < self.maxImages();
        };
        self.uploadImageInProgress = ko.observable(false);


        // Line Ad
        if (lineAd !== undefined && lineAd !== null) {

            self.printInsertions = ko.observable(lineAd.printInsertions);

            self.lineAdHeader = ko.observable(lineAd.lineAdHeader);

            self.lineAdText = ko.observable(lineAd.lineAdText);

            self.wordCount = ko.computed(function () {
                if (self.lineAdText() == null || self.lineAdText().length === 0) {
                    return 0;
                }
                return self.lineAdText().split(' ').length;
            });

            self.lineAdImageId = ko.observable(lineAd.lineAdImageId == null ? '' : lineAd.lineAdImageId);

            self.lineAdImageId.subscribeChanged(function (oldValue, newValue) {
                if (newValue !== '') {
                    adService.assignPrintImg(newValue); // Calls the service to set the value
                } else {
                    adService.removePrintImg(oldValue);
                }
            }, this);

            self.removePrintImage = function () {
                self.lineAdImageId("");
            }
            self.lineAdImgUrl = ko.computed(function () {
                if (self.lineAdImageId() === 'undefined' || self.lineAdImageId() === '') {
                    return null;
                }
                return imageService.getImageUrl(self.lineAdImageId());
            });
        }


        // Editions
        self.publicationEditions = ko.observableArray([]);

        // Prices
        if (updateRates === true) {
            self.pricetotal = ko.observable();
            self.publicationPrices = ko.observableArray([]);
            self.onlineItemPrices = ko.observableArray([]);
            self.calculate = ko.computed(function () {
                var factors = {}

                if (lineAd != null) {
                    factors.lineAdText = self.lineAdText();
                    factors.lineAdHeader = self.lineAdHeader();
                    factors.usePhoto = self.lineAdImageId();
                    factors.editions = self.printInsertions();
                }

                adService.updateBookingRates(factors).done(function (resp) {
                    // Map Total
                    self.pricetotal('Total: ' + $paramount.formatCurrency(resp.bookingTotal));

                    // Map online line items
                    self.onlineItemPrices.removeAll();
                    $.each(resp.onlinePrice.items, function (index, serverItem) {
                        self.onlineItemPrices.push(new OnlineLineItem(serverItem));
                    });

                    // Map publications 
                    self.publicationPrices.removeAll();
                    if (resp.publicationPrices !== undefined && resp.publicationPrices !== null) {

                        $.each(resp.publicationPrices, function (index, serverItem) {
                            var publicationPrice = new PublicationPrice(serverItem);
                            if (publicationPrice.total > 0) {
                                self.publicationPrices.push(publicationPrice);
                            }
                        });

                    }
                });

            }).extend({ throttle: 1000 });
        }


    };

    var OnlineLineItem = function (serverItem) {
        this.name = serverItem.name;
        this.price = $paramount.formatCurrency(serverItem.price);
        this.quantity = serverItem.quantity;
        this.itemTotal = $paramount.formatCurrency(serverItem.itemTotal);
    };

    var PublicationPrice = function (serverItem) {
        var me = this;
        me.publicationName = serverItem.publication;
        me.total = serverItem.publicationTotal;
        me.publicationTotal = $paramount.formatCurrency(serverItem.publicationTotal);
        me.lineItems = ko.observableArray([]);
        $.each(serverItem.items, function (index, lineItem) {
            me.lineItems.push(new PrintLineItem(lineItem));
        });
    };

    var PrintLineItem = function (serverItem) {
        this.name = serverItem.name;
        this.price = $paramount.formatCurrency(serverItem.price);
        this.quantity = serverItem.quantity;
        this.editions = serverItem.editions;
        this.itemTotal = $paramount.formatCurrency(serverItem.itemTotal);
    };

})(jQuery, $paramount, ko);;
(function ($, ko, $paramount) {

    function EventTicketDefinition(parent, data) {
        var eventService = new $paramount.EventService();

        var me = this;
        me.ticketName = ko.observable();
        me.availableQuantity = ko.observable();
        me.eventTicketFields = ko.observableArray();
        me.price = ko.observable();

        me.addField = function () {
            me.eventTicketFields.push(new $paramount.models.DynamicFieldDefinition(me));
        }

        me.removeTicketField = function (f) {
            me.eventTicketFields.remove(f);
        }

        me.totalTicketCost = ko.computed(function () {
            if (!me.price()) {
                return "";
            }

            if (parent.includeTransactionFee() === true && me.price() > 0) {
                return eventService.calculateBuyerPriceWithTxnFee(me.price(), parent.eventTicketFee(), parent.eventTicketFeeCents());
            }
            return $paramount.formatCurrency(me.price());
        });

        /*
         * Validation
         */
        me.validator = ko.validatedObservable({
            ticketName: me.ticketName.extend({ required: true }),
            availableQuantity: me.availableQuantity.extend({ min: 0, required: true }),
            price: me.price.extend({ min: 0, required: true })
        });

        /*
         * Sync existing data
         */
        if (data) {
            this.bindEventTicketDefinition(data);
        }
    }

    EventTicketDefinition.prototype.bindEventTicketDefinition = function (data) {
        $.extend(data, {});

        var me = this;
        me.ticketName(data.ticketName);
        me.availableQuantity(data.availableQuantity);
        me.price(data.price);

        if (data.eventTicketFields) {
            $.each(data.eventTicketFields, function (idx, f) {
                me.eventTicketFields.push(new $paramount.models.DynamicFieldDefinition(me, f));
            });
        }
    }

    $paramount.models = $paramount.models || {};
    $paramount.models.EventTicketDefinition = EventTicketDefinition;


})(jQuery, ko, $paramount);;
(function ($, ko, $paramount) {

    function EventTicketingSetup(data) {
        var me = this,
            adDesignService = new $paramount.AdDesignService();

        me.tickets = ko.observableArray();
        me.closingDate = ko.observable();
        me.includeTransactionFee = ko.observable();
        me.eventTicketFee = ko.observable();
        me.eventTicketFeeCents = ko.observable();

        /*
         * Functions
         */
        me.addTicketType = function () {
            me.tickets.push(new $paramount.models.EventTicketDefinition(me));
        }

        me.removeTicketType = function (t) {
            me.tickets.remove(t);
        }

        me.submitTickets = function (e) {
            if ($paramount.checkValidity(me) === false) {
                return;
            }

            var $button = $('#btnSubmit');
            $button.loadBtn();
            var eventTicketingSetup = ko.toJS(me);
            adDesignService.updateEventTicketDetails(eventTicketingSetup).error(function () {
                $button.resetBtn();
            });
        }

        me.clearClosingDate = function () {
            me.closingDate(null);
        }

        /*
         * Validation
         */
        me.validator = ko.validatedObservable({
            closingDate: me.closingDate.extend({
                pmtMinDate: new Date(data.adStartDate)
            })
        });

        /*
         * Sync existing data
         */
        me.bindEventTicketingSetup(data);
    }

    EventTicketingSetup.prototype.bindEventTicketingSetup = function (data) {
        $.extend(data, {});

        var me = this;
        $.each(data.tickets, function (idx, t) {
            me.tickets.push(new $paramount.models.EventTicketDefinition(me, t));
        });
        me.closingDate(data.closingDate);
        me.eventTicketFee(data.eventTicketFee);
        me.eventTicketFeeCents(data.eventTicketFeeCents);
        me.includeTransactionFee(data.includeTransactionFee);
    }

    $paramount.models = $paramount.models || {};
    $paramount.models.EventTicketingSetup = EventTicketingSetup;


})(jQuery, ko, $paramount);;
(function ($, ko, $paramount) {

    $paramount.models = $paramount.models || {};
    $paramount.models.CategoryLinks = function (parentCategories) {
        var me = this;
        me.parentCategories = ko.observableArray();
        _.each(parentCategories, function (c) {
            c.fontIcon = 'fa fa-' + c.fontIcon;
            me.parentCategories.push(c);
        });

        me.searchLink = function(category) {
            return $paramount.baseUrl + 'Listings/Find?categoryId=' + category.categoryId;
        }
    }
 
})(jQuery, ko, $paramount);;
(function ($, $p) {

    function ContactAdvertiser(params) {

        var me = this;
        me.adId = params.adId;
        me.isLoggedIn = params.isLoggedIn || false;
        me.fullName = ko.observable();
        me.email = ko.observable();
        me.question = ko.observable();
        me.submitted = ko.observable(false);

        /*
        *   Validation
        */
        me.validator = ko.validatedObservable({
            fullName: me.fullName.extend({ required: !me.isLoggedIn }),
            email: me.email.extend({ required: !me.isLoggedIn, email: true }),
            question: me.question.extend({ required: true })
        });


        /*
        *   Submit
        */ 
        me.submit = function (model, event) {
            if (!$p.checkValidity(model)) {
                return;
            }

            var $btn = $(event.target);
            $btn.loadBtn();


            $p.httpPost($p.baseUrl + 'listings/adenquiry', {
                adId: me.adId,
                fullName: me.fullName(),
                email: me.email(),
                question: me.question(),
                googleCaptchaResult: $('.g-recaptcha-response').val()
            }).then(function (r) {
                $btn.resetBtn();
                if (r.errors) {
                    return;
                }
                me.submitted(true);
            });
        }
    }

    ko.components.register('contact-advertiser', {
        viewModel: ContactAdvertiser,
        template: {
            path: $p.baseUrl + 'Scripts/app/contactAdvertiser/contactAdvertiser.html'
        }
    });


})(jQuery, $paramount);;
(function ($, $p, ko) {

    function AddGuest() {
        this.id = ko.observable();
        this.eventId = ko.observable();
        this.isSeatedEvent = ko.observable();
        this.guestFullName = ko.observable();
        this.guestEmail = ko.observable();
        this.selectedTicket = ko.observable();
        this.seatNumber = ko.observable();
        this.sendEmailToGuest = ko.observable(true);
        this.tickets = ko.observableArray();
        this.ticketFields = ko.observableArray();
        this.promoCode = ko.observable();
        this.saved = ko.observable();
        this.selectedGroup = ko.observable();
        this.displayGuests = ko.observable();
        this.isPublic = ko.observable();
        this.hasGroups = ko.observable(false);
        this.eventGroups = ko.observableArray();
        this.seats = ko.observableArray();
        this.guestAddWarning = ko.observable('');
        this.showSeatWarning = ko.observable(false);
        this.disableAddGuest = ko.observable();
        this.validator = ko.validatedObservable({
            guestFullName: this.guestFullName.extend({ required: true }),
            guestEmail: this.guestEmail.extend({ required: true, email: true })
        });
        this.isLoading = ko.observable(true);
        this.cachedEventSeating = [];

        var me = this;
        me.seatSelected = function (seatNumber) {
            me.showSeatWarning(false);
            var seat = _.find(me.cachedEventSeating, function (s) {
                return s.seatNumber === seatNumber;
            });
            if (seat.available === false) {
                me.showSeatWarning(true);
                me.seatNumber(null);
                me.selectedTicket(null);
                me.disableAddGuest(true);
            } else {
                var eventTicketId = seat.eventTicketId;
                var eventTicket = _.find(me.tickets(), function (t) {
                    return t.eventTicketId() === eventTicketId;
                });
                me.selectedTicket(eventTicket);
                me.ticketChanged();
                me.disableAddGuest(false);
            }
        }

        me.getSelectedTicketName = ko.computed(function () {
            return me.selectedTicket() && me.selectedTicket().ticketName();
        });

        me.getSelectedTicketRemainingCount = ko.computed(function () {
            return me.selectedTicket() && me.selectedTicket().remainingQuantity();
        });
    }

    AddGuest.prototype.bindData = function (data) {
        var service = new $p.EventService();

        var me = this;
        me.id(data.id);
        me.eventId(data.eventId);
        me.guestFullName(data.guestFullName);
        me.guestEmail(data.guestEmail);
        me.displayGuests(data.displayGuests);
        me.isPublic(data.isPublic);
        me.hasGroups(data.eventGroups && data.eventGroups.length > 0);
        me.isSeatedEvent(data.isSeatedEvent);
        me.disableAddGuest(data.isSeatedEvent === true);

        _.each(data.ticketFields, function (tf) {
            me.ticketFields.push(new $p.models.DynamicFieldValue(tf));
        });

        _.each(data.eventTickets, function (et) {
            me.tickets.push(new $p.models.EventTicket(et, 5));
        });

        _.each(data.eventGroups, function (gr) {
            me.eventGroups.push(new $p.models.EventGroup(gr));
        });

        if (data.isSeatedEvent === true) {
            service.getEventSeating(data.eventId).then(function (response) {
                if (!response.rows) {
                    toastr.error('Unable to find any seats. Please ensure the seating has been setup first.');
                }
                _.each(response.rows, function (r) {
                    _.each(r.seats, function (s) {
                        me.seats.push(s.seatNumber);
                        me.cachedEventSeating.push(s);
                    });
                });
            });
        } else {
            me.isLoading(false);
        }
    }

    AddGuest.prototype.toModel = function (vm) {
        // maps to AddEventGuestViewModel
        return {
            id: vm.id(),
            eventId: vm.eventId(),
            guestFullName: vm.guestFullName(),
            guestEmail: vm.guestEmail(),
            isPublic: vm.isPublic(),
            seatNumber: vm.seatNumber(),
            sendEmailToGuest: vm.sendEmailToGuest(),
            selectedTicket: ko.toJS(vm.selectedTicket()),
            selectedGroup: ko.toJS(vm.selectedGroup),
            promoCode : vm.promoCode()
        }
    }

    AddGuest.prototype.ticketChanged = function () {
        var me = this;
        var service = new $p.EventService();
        me.ticketFields.removeAll();
        service.getFieldsForTicket(me.selectedTicket().eventTicketId()).then(function (resp) {
            _.each(resp, function (tf) {
                me.ticketFields.push(new $p.models.DynamicFieldValue(tf));
            });
        });

        me.eventGroups.removeAll();
        service.getGroupsForTicket(me.eventId(), me.selectedTicket().eventTicketId()).then(function (resp) {
            _.each(resp, function (gr) {
                me.eventGroups.push(new $p.models.EventGroup(gr));
            });
        });
    }

    AddGuest.prototype.addAnother = function (mode, event) {
        $(event.target).loadBtn();
        location.reload();
    }

    /*
    *   Submit 
    */
    AddGuest.prototype.submitGuest = function (element, event) {
        var me = this;
        if (!$p.checkValidity(me) || !$p.checkValidity(me.ticketFields())) {
            return;
        }

        if (me.isSeatedEvent() === true && $p.isNullOrUndefined(me.seatNumber())) {
            me.guestAddWarning('Please ensure seat is selected');
            return;
        }

        var $btn = $(event.target);
        $btn.button('loading');

        var objToSend = this.toModel(me);

        var service = new $p.AdDesignService(me.id());
        service.addGuest(objToSend).then(function (r) {
            if (r.errors) {
                return;
            }

            $btn.button('reset');
            me.saved(true);
        });
    }

    $p.models = $p.models || {};
    $p.models.AddGuest = AddGuest;

})(jQuery, $paramount, ko);;
(function ($, $p) {
    
    var $view = $('.add-guest-view');
    $p.ui = $p.ui || {};
    $p.ui.addGuest = {
        init: function (vm) {
            var addGuestModel = new $p.models.AddGuest();
            addGuestModel.bindData(vm);
            
            ko.applyBindings(addGuestModel, $view[0]);
        }
    }
})(jQuery, $paramount);;
(function ($, $paramount, ko) {

    function BookTickets(data, eventService) {
        var me = this;

        $.extend(data, {});

        me.eventId = ko.observable(data.eventId);
        me.includeTransactionFee = ko.observable(data.includeTransactionFee);
        me.minsRemaining = ko.observable(data.reservationExpiryMinutes);
        me.secondsRemaining = ko.observable(data.reservationExpirySeconds);
        me.secondsRemainingDisplay = ko.computed(function () {
            return ("0" + me.secondsRemaining()).slice(-2);
        });
        me.canContinue = ko.observable(data.successfulReservationCount > 0);
        me.notAllRequestsAreFulfilled = ko.observable(data.reservations.length !== data.successfulReservationCount);
        me.displayGuests = ko.observable(data.displayGuests);

        // User details
        me.firstName = ko.observable(data.firstName);
        me.lastName = ko.observable(data.lastName);
        me.phone = ko.observable(data.phone);
        me.postCode = ko.observable(data.postCode);
        me.email = ko.observable(data.email);
        me.showHowYouHeardAboutEventOptions = ko.observable(data.howYouHeardAboutEventOptions && data.howYouHeardAboutEventOptions.length > 0);
        me.howYouHeardAboutEvent = ko.observable();
        me.howYouHeardAboutEventOptions = ko.observableArray(data.howYouHeardAboutEventOptions);

        // Promo code
        me.promoCode = ko.observable();
        me.promoCodeApplied = ko.observable(0);
        me.promoDiscountPercent = ko.observable();
        me.promoDiscountAmount = ko.observable();
        me.promoNotAvailable = ko.observable();

        me.applyPromoCode = function (model, event) {
            if (!me.promoCode()) {
                return;
            }
            var $btn = $(event.target);
            $btn.loadBtn();

            eventService.applyPromoCode(me.eventId(), me.promoCode())
                .then(function (r) {
                    if (r.errors) {
                        return;
                    }

                    if (r.notAvailable === true) {
                        me.promoNotAvailable(true);
                        return;
                    }

                    me.promoCodeApplied(true);
                    me.promoDiscountPercent(r.discountPercent);
                    me.promoDiscountAmount(r.discountAmount);
                    me.priceAfterDiscount(r.priceAfterDiscount);
                    me.fee(r.fee);
                    me.totalPrice(r.totalPrice);

                })
                .always(function () {
                    $btn.resetBtn();
                });
        }

        // Pricing
        me.price = ko.observable(data.totalCostWithoutFees);
        me.priceAfterDiscount = ko.observable();
        me.fee = ko.observable(data.totalFees);
        me.totalPrice = ko.observable(data.totalCost);
        me.requiresPayment = ko.computed(function () {
            return me.totalPrice() > 0;
        });

        // Tickets
        me.reservations = ko.observableArray();
        var groupsPromise = eventService.getGroups(data.eventId);
        $.each(data.reservations, function (idx, reservationData) {
            if (idx === 0) {
                if (data.email) {
                    reservationData.guestEmail = data.email;
                }
                reservationData.guestFullName = getFullName(data);
            }

            reservationData.getGroupsPromise = groupsPromise;
            reservationData.displayGuests = me.displayGuests();
            me.reservations.push(new $paramount.models.EventTicketReserved(reservationData));
        });

        me.useLoginDetailsForAllTickets = function () {
            _.each(me.reservations(), function (r) {
                r.guestEmail(data.email);
                r.guestFullName(getFullName(data));
            });
            toastr.info('All tickets details have been prefilled.');
        }

        function getFullName(data) {
            var name = '';
            if (data.firstName) {
                name = data.firstName;
            }

            if (data.lastName) {
                name = name + ' ' + data.lastName;
            }
            return name;
        }

        // Timer
        if (data.outOfTime !== true && data.successfulReservationCount > 0) {
            var interval = setInterval(function () {
                if (me.minsRemaining() === 0 && me.secondsRemaining() === 1) {
                    window.clearInterval(interval);
                }

                if (me.secondsRemaining() > 0) {
                    var updatedSecs = me.secondsRemaining() - 1;
                    me.secondsRemaining(updatedSecs);
                } else {
                    var updatedMins = me.minsRemaining() - 1;
                    me.minsRemaining(updatedMins);
                    me.secondsRemaining(59);
                }
            }, 1000);
        }

        // Time checking
        me.outOfTime = ko.computed(function () {
            if (data.outOfTime) {
                return true;
            }

            return me.minsRemaining() === 0 && me.secondsRemaining() === 0;
        });

        /*
         * Submit ticket booking
         */
        me.submitTicketBooking = function () {

            if (me.outOfTime()) {
                // Scroll to the top 
                $('html, body').animate({ scrollTop: $('.alert-count-down').offset().top }, 1000);
                return;
            }

            var fields = getAllDynamicFields();

            if (!$paramount.checkValidity(me.reservations()) || !$paramount.checkValidity(fields)) {
                return;
            };

            var $form = $('#bookTicketsForm');
            var $btn = $('#proceedToPaymentBtn');

            if ($form.valid() === true) {
                $btn.loadBtn();

                var request = ko.toJSON(me);
                eventService.bookTickets(request)
                    .then(function (resp) {
                        if (resp.nextUrl) {
                            return;
                        }
                        $btn.resetBtn();
                    });
            }
        }


        function getAllDynamicFields() {

            var result = [];
            var fieldObservables = _.map(me.reservations(), 'ticketFields');
            _.each(fieldObservables, function (f) {
                _.each(f(), function (dynamicField) {
                    result.push(dynamicField);
                });
            });
            return result;
        }
    }


    $paramount.models = $paramount.models || {};
    $paramount.models.BookTickets = BookTickets;

})(jQuery, $paramount, ko);;
(function ($, ko, $paramount) {
    
    var $bookTicketsView = $('#bookTicketsView');

    $paramount.ui = $paramount.ui || {};
    $paramount.ui.bookTickets = {
        init: function (options) {
            $(function () {
                var eventService = new $paramount.EventService();
                var bookTickets = new $paramount.models.BookTickets(options.data, eventService);
                ko.applyBindings(bookTickets, $bookTicketsView[0]);
            });
        }
    }
}(jQuery, ko, $paramount));;
(function ($, ko, notifier, $p) {
    
    // Maps to ViewModel: EditGuestViewModel
    function EditGuest(data) {

        var me = this,
            adDesignService = new $p.AdDesignService(data.adId),
            eventService = new $p.EventService();

        me.adId = ko.observable();
        me.eventId = ko.observable();
        me.eventBookingTicketId = ko.observable();
        me.eventBookingId = ko.observable();
        me.eventTicketId = ko.observable();
        me.guestFullName = ko.observable();
        me.originalGuestEmail = ko.observable();
        me.guestEmail = ko.observable();
        me.fields = ko.observableArray();
        me.groups = ko.observableArray();
        me.selectedGroup = ko.observable();
        me.currentGroupId = ko.observable();
        me.displayGuests = ko.observable(); // High level setting
        me.isPublic = ko.observable();
        me.seatNumber = ko.observable();
        me.sendTransferEmail = ko.observable(true);
        me.sendEmailToGuestAboutRemoval = ko.observable(false);
        me.isEmailDifferent = ko.computed(function () {
            if (me.guestEmail() && me.originalGuestEmail()) {
                return me.guestEmail().toLowerCase() !== me.originalGuestEmail().toLowerCase();
            }
            return false;
        });

        /*
         * Validation
         */
        me.validator = ko.validatedObservable({
            guestFullName: me.guestFullName.extend({ required: true }),
            guestEmail: me.guestEmail.extend({ required: true, email: true })
        });

        me.save = function (vm, event) {

            if (!$p.checkValidity(me) || !$paramount.checkValidity(me.fields())) {
                return;
            }

            var $btn = $(event.target);
            $btn.button('loading');


            var dataToPost = ko.toJS(me);
            if (me.selectedGroup()) {
                dataToPost.groupId = me.selectedGroup().eventGroupId();
            } else {
                dataToPost.groupId = null;
            }
            dataToPost.sendTransferEmail = me.isEmailDifferent() && me.sendTransferEmail();

            adDesignService.editGuest(dataToPost).then(function (resp) {
                if (!resp.errors) {
                    notifier.success("Guest information updated.");
                    //  Update the local details
                    me.originalGuestEmail(me.guestEmail());
                    me.eventBookingTicketId(resp.eventBookingTicketId);
                }
            });
        }

        me.removeGuest = function (vm, event) {
            var $btn = $(event.target);
            $btn.button('loading');

            var data = {
                eventId : me.eventId(),
                eventBookingTicketId: me.eventBookingTicketId(),
                sendEmailToGuestAboutRemoval: me.sendEmailToGuestAboutRemoval()
            }

            adDesignService.removeGuest(data);
        }

        me.resendGuestEmail = function(vm, event) {
            var $btn = $(event.target);
            $btn.button('loading');

            eventService.resendGuestEmail(me.adId(), me.eventBookingTicketId())
                .success(function() {
                    notifier.success('Email has been sent successfully.');
                });
        }

        if (data) {
            me.bind(data);
        }

    }

    EditGuest.prototype.bind = function (data) {
        var me = this;
        me.adId(data.adId);
        me.eventId(data.eventId);
        me.eventBookingTicketId(data.eventBookingTicketId);
        me.eventBookingId(data.eventBookingId);
        me.eventTicketId(data.eventTicketId);
        me.guestFullName(data.guestFullName);
        me.originalGuestEmail(data.guestEmail);
        me.guestEmail(data.guestEmail);
        me.currentGroupId(data.currentGroupId);
        me.displayGuests(data.displayGuests);
        me.isPublic(data.isPublic);
        me.seatNumber(data.seatNumber);

        _.each(data.fields, function (f) {
            me.fields.push(new $p.models.DynamicFieldValue(f));
        });

        _.each(data.groups, function (g) {
            var eventGroup = new $p.models.EventGroup(g);
            me.groups.push(eventGroup);

            if (g.eventGroupId === data.groupId) {
                me.selectedGroup(eventGroup);
            }
        });
    }

    $p.models.EditGuest = EditGuest;

})(jQuery, ko, toastr, $paramount);;

(function ($, $paramount) {

    function EventService(baseUrl) {
        this.baseUrl = baseUrl || $paramount.baseUrl;
    }

    EventService.prototype.getEvent = function (eventId) {
        return $paramount.httpGet(this.baseUrl + 'api/events/' + eventId);
    }

    EventService.prototype.searchEvents = function (query) {

        var url = this.baseUrl + 'api/events/search';

        if (!query) {
            return $paramount.httpGet(url);
        }

        var queryEncoded = $paramount.encodeQuery(query);
        url += '?' + queryEncoded;

        return $paramount.httpGet(url);
    }

    EventService.prototype.startTicketOrder = function (order) {
        return $paramount.httpPost(this.baseUrl + 'event/reserveTickets', order);
    }

    EventService.prototype.bookTickets = function (ticketBookingDetails) {
        return $paramount.httpPost(this.baseUrl + 'event/bookTickets', ticketBookingDetails);
    }

    EventService.prototype.applyPromoCode = function (eventId, promoCode) {
        return $paramount.httpPost(this.baseUrl + 'event/' + eventId + '/promo/', { promoCode: promoCode });
    }
    
    EventService.prototype.updateTicket = function (ticketDetails) {
        return $paramount.httpPost(this.baseUrl + 'editAd/eventTicketUpdate', {
            id: ticketDetails.adId, eventTicketViewModel: ticketDetails
        });
    }

    EventService.prototype.payWithPayPal = function () {
        return $paramount.httpPost(this.baseUrl + 'event/payWithPayPal');
    }

    EventService.prototype.getFieldsForTicket = function (eventTicketId) {
        return $paramount.httpGet(this.baseUrl + 'event/ticket-fields?id=' + eventTicketId);
    }

    EventService.prototype.getGroups = function (eventId) {
        var url = this.baseUrl + 'api/events/' + eventId + '/groups';
        return $paramount.httpGet(url);
    }

    EventService.prototype.getGroupsForTicket = function (eventId, eventTicketId) {
        var url = this.baseUrl + 'api/events/' + eventId + '/tickets/' + eventTicketId + '/groups';
        return $paramount.httpGet(url);
    }

    EventService.prototype.getTicketsForEvent = function (eventId) {
        var url = this.baseUrl + 'api/events/' + eventId + '/tickets';
        return $paramount.httpGet(url);
    }

    EventService.prototype.getTicketsForGroup = function (eventId, eventGroupId) {
        var url = this.baseUrl + 'api/events/' + eventId + '/groups/' + eventGroupId + '/tickets';
        return $paramount.httpGet(url);
    }

    EventService.prototype.getGuests = function (eventId) {
        var url = this.baseUrl + 'api/events/' + eventId + '/guests';
        return $paramount.httpGet(url);
    }

    EventService.prototype.getGuestNames = function (eventId) {
        var url = this.baseUrl + 'api/events/' + eventId + '/guest-names';
        return $paramount.httpGet(url);
    }

    EventService.prototype.getGuestsForTicket = function (eventId, eventTicketId) {
        var url = this.baseUrl + 'api/events/' + eventId + '/ticket/' + eventTicketId + '/guests';
        return $paramount.httpGet(url);
    }

    EventService.prototype.assignGroup = function (eventBookingTicketId, eventGroupId) {
        var data = {
            eventBookingTicketId: eventBookingTicketId,
            eventGroupId: eventGroupId
        }
        return $paramount.httpPost(this.baseUrl + 'event/assign-group', data);
    }

    EventService.prototype.calculateBuyerPriceWithTxnFee = function (price, eventTicketFee, eventTicketFeeCents) {
        var percentage = ((eventTicketFee / 100) + 1);
        var amount = (percentage * price) + (eventTicketFeeCents / 100);
        return $paramount.formatCurrency(amount);
    }

    EventService.prototype.resendGuestEmail = function (adId, eventBookingTicketId) {
        return $paramount.httpPost(this.baseUrl + 'event-dashboard/' + adId + '/resend-email/' + eventBookingTicketId);
    }

    EventService.prototype.createGuestEmailSendPromises = function (id, guests) {
        var me = this;
        var emailFuncs = _.map(guests, function (g) {
            return function () {
                return new Promise(function (resendResolve) {

                    me.resendGuestEmail(id, g.ticketNumber)
                        .then(function (res) {
                            resendResolve(res);
                        });

                });
            }
        });

        return emailFuncs;
    }

    EventService.prototype.getEventSeating = function (id, orderRequestId) {
        var uri = this.baseUrl + 'api/events/' + id + '/seating';

        if (orderRequestId && orderRequestId.length > 0) {
            uri += "/" + orderRequestId;
        }

        return $paramount.httpGet(uri);
    }

    EventService.prototype.getEventDashboardUrl = function(adId) {
        return this.baseUrl + 'event-dashboard/' + adId;
    }

    $paramount.EventService = EventService;
    return $paramount;

})(jQuery, $paramount);;
(function ($, $paramount, ko) {

    $paramount.models = $paramount.models || {};

    // Event ad details editing object used for knockout
    $paramount.models.EventAd = function (data, options) {

        var me = this,
            adService = options.adDesignService,
            imageService = options.imageService,
            eventService = new $paramount.EventService(),
            MAX_TITLE_CHARS = 100;

        me.adId = ko.observable(data.adId);
        me.eventId = ko.observable(data.eventId);
        me.hasBookings = ko.observable(data.hasBookings);
        me.title = ko.observable(data.title);
        me.titleRemaining = ko.computed(function () {
            if (me.title() === null) {
                return 100;
            }
            return MAX_TITLE_CHARS - me.title().length;
        });
        me.description = ko.observable(data.description);
        me.eventPhoto = ko.observable(data.eventPhoto);
        me.eventPhotoUploadError = ko.observable(null);
        me.eventPhotoUrl = ko.computed(function () {
            return imageService.getImageUrl(me.eventPhoto(), { w: 1278, h: 502 });
        });
        me.removeEventPhoto = function () {
            if (me.eventPhoto() !== null) {
                adService.removeOnlineAdImage(me.eventPhoto()).done(function () {
                    me.eventPhoto(null);
                });
            }
            return;
        }
        me.configDurationDays = ko.observable(options.configDurationDays);
        me.adStartDate = ko.observable(data.adStartDate);
        me.venueName = ko.observable(data.venueName);
        me.location = ko.observable(data.location);
        me.locationLatitude = ko.observable(data.locationLatitude);
        me.locationLongitude = ko.observable(data.locationLongitude);
        me.locationFloorPlanDocumentId = ko.observable(data.locationFloorPlanDocumentId);
        me.locationFloorPlanFilename = ko.observable(data.locationFloorPlanFilename);
        me.eventStartDate = ko.observable(data.eventStartDate);
        me.eventEndDate = ko.observable(data.eventEndDate);
        me.organiserName = ko.observable(data.organiserName);
        me.organiserPhone = ko.observable(data.organiserPhone);
        me.ticketingEnabled = ko.observable(data.ticketingEnabled);
        me.displayGuests = ko.observable(data.displayGuests);

        /*
         * Address properties
         */
        me.streetNumber = ko.observable(data.streetNumber);
        me.streetName = ko.observable(data.streetName);
        me.suburb = ko.observable(data.suburb);
        me.state = ko.observable(data.state);
        me.postCode = ko.observable(data.postCode);
        me.country = ko.observable(data.country);

        /*
         * Validation
         */
        me.validator = ko.validatedObservable({
            title: me.title.extend({ required: true, maxLength: MAX_TITLE_CHARS }),
            description: me.description.extend({ required: true }),
            location: me.location.extend({ required: true, maxLength: 200 }),
            eventStartDate: me.eventStartDate.extend({ required: true }),
            eventEndDate: me.eventEndDate
                .extend({ required: true })
                .extend({ mustBeAfter: me.eventStartDate(), message: 'End date must be after start date.' }),
            organiserName: me.organiserName.extend({ required: true }),
            adStartDate: me.adStartDate.extend({ required: options.adStartDateRequired })
        });

        /*
         * Submit changes
         */

        me.saveEventDetails = function (element, event, sendNotifications) {
            if (!$paramount.checkValidity(me)) {
                return Promise.resolve();
            }

            var $btn = $(event.target);
            if (!sendNotifications) {
                $btn.loadBtn();
            }

            return adService.updateEventDetails(ko.toJS(me))
                .then(function (res) {
                    if (res.errors || res.nextUrl) {
                        return null;
                    };

                    if (!sendNotifications) {
                        toastr.success('Details updated successfully');
                        $btn.resetBtn();
                    }
                    return res;

                });
        }

        me.startEmailSending = ko.observable(false);
        me.guestsAffected = ko.observable();
        me.guestsNotified = ko.observable();

        me.saveEventDetailsAndNotify = function (element, event) {
            me.saveEventDetails(element, event, true)
                .then(function () {
                    return eventService.getGuests(me.eventId());
                })
                .then(function (res) {
                    if (res.errors) {
                        throw new Error(res.errors[0]);
                    }

                    return res;
                })
                .then(function (guests) {
                    me.startEmailSending(true);
                    me.guestsAffected(guests.length);
                    me.guestsNotified(1);

                    var emailFuncs = eventService.createGuestEmailSendPromises(me.adId(), guests);

                    return $paramount.processPromises(emailFuncs, function () {
                        me.guestsNotified(me.guestsNotified() + 1);
                    }).then(function () {
                        me.startEmailSending(false);
                        toastr.success('Done! The guests should receive an email with updated ticket information.');
                    });

                });
        }

    };

})(jQuery, $paramount, ko);;
(function ($, ko, $paramount) {
    
    function EventDashboardModel(editEventViewModel, adDesignService) {
        var me = this;
        me.adId = ko.observable();
        me.eventId = ko.observable();
        me.tickets = ko.observableArray();
        me.totalSoldQty = ko.observable();
        me.isClosed = ko.observable();
        me.totalRemainingQty = ko.computed(function () {
            return _.sumBy(me.tickets(), function (t) {
                return t.remainingQuantity();
            });
        });
        me.requiresEventOrganiserConfirmation = ko.observable();
        me.organiserAbsorbsTransactionFee = ko.observable();
        me.eventOrganiserOwedAmount = ko.observable();
        me.totalSoldAmount = ko.observable();
        me.requestPaymentStatus = ko.observable();
        me.showPaymentStatusLabel = ko.observable();
        me.showPayMeButton = ko.observable();
        me.showWithdrawPayment = ko.observable();
        me.pageViews = ko.observable();
        me.newSurveyOption = ko.observable();
        me.surveyStatChartData = ko.observable(buildSurveyChartData(editEventViewModel));
        me.bindEditEvent(editEventViewModel);

        /*
         * Methods - Close event
         */
        me.closeEvent = function (element, event) {
            var $btn = $(event.target); // Grab the jQuery element from knockout
            $btn.loadBtn();

            adDesignService.closeEvent(me.eventId())
                .then(function (res) {
                    if (res.errors) {
                        return;
                    }

                    $('#closeEventDialog').modal('hide');
                    me.isClosed(true);
                    me.requestPaymentStatus($paramount.EVENT_PAYMENT_STATUS.REQUEST_PENDING);
                });
        }

        me.deleteEvent = function (element, event) {
            var $btn = $(event.target);
            $btn.loadBtn();

            // This should return a nextUrl property that will automatically navigate away from this page
            adDesignService.remove(me.adId());
        }

        me.addSurveyOption = function () {

            var newOption = me.newSurveyOption();
            if (!newOption) {
                return;
            }

            if (_.includes(editEventViewModel.surveyStatistics, newOption)) {
                toastr.error('The option ' + newOption + ' already exists');
                return;
            }

            var model = {
                eventId: me.eventId(),
                optionName: newOption,
                count: 0
            };

            var currentStats = editEventViewModel.surveyStatistics;

            adDesignService.addSurveyOption(model).then(function (resp) {

                if (resp.errors) {
                    return;
                }
                
                var updated = {
                    surveyStatistics: [...currentStats, Object.assign({}, model)]
                };

                var updatedChartData = buildSurveyChartData(updated);
                me.surveyStatChartData(updatedChartData);

                me.newSurveyOption(null);
                toastr.success('Option added successfully');
            });
        }


        /*
         * Computed Methods
         */
        me.showPaymentStatusLabel = ko.computed(function () {
            return me.requestPaymentStatus() !== $paramount.EVENT_PAYMENT_STATUS.REQUEST_PENDING;
        });

        me.showPayMeButton = ko.computed(function () {
            return me.requestPaymentStatus() === $paramount.EVENT_PAYMENT_STATUS.REQUEST_PENDING;
        });

        me.showWithdrawPayment = ko.computed(function () {
            return me.requestPaymentStatus() !== $paramount.EVENT_PAYMENT_STATUS.NOT_AVAILABLE && me.eventOrganiserOwedAmount() > 0;
        });
    }

    EventDashboardModel.prototype.bindEditEvent = function (editEventViewModel) {
        var me = this;
        $.each(editEventViewModel.tickets, function (idx, t) {
            t.adId = editEventViewModel.adId;
            me.tickets.push(new $paramount.models.EventTicket(t));
        });

        me.adId(editEventViewModel.adId);
        me.eventId(editEventViewModel.eventId);
        me.organiserAbsorbsTransactionFee(editEventViewModel.organiserAbsorbsTransactionFee);
        me.isClosed(editEventViewModel.isClosed);
        me.totalSoldAmount(editEventViewModel.totalSoldAmount);
        me.eventOrganiserOwedAmount(editEventViewModel.eventOrganiserOwedAmount);
        me.totalSoldAmountFormatted = ko.computed(function () {
            return $paramount.formatCurrency(me.totalSoldAmount());
        });
        me.totalSoldQty(editEventViewModel.totalSoldQty);
        me.pageViews(editEventViewModel.pageViews);
        me.requestPaymentStatus(editEventViewModel.eventPaymentRequestStatus);
        me.requiresEventOrganiserConfirmation(editEventViewModel.requiresEventOrganiserConfirmation);
    }

    $paramount.models = $paramount.models || {};
    $paramount.models.EventDashboardModel = EventDashboardModel;


    function buildSurveyChartData(model) {
        if (!model.surveyStatistics ||
            !Array.isArray(model.surveyStatistics) ||
            model.surveyStatistics.length === 0) {
            return null;
        }

        var labels = model.surveyStatistics.map(function (stat) {
            return stat.optionName;
        });

        var counts = model.surveyStatistics.map(function (stat) {
            return stat.count;
        });

        var colours = model.surveyStatistics.map(function () {
            return $paramount.getRandomColor();
        });

        return {
            totalCount: _.sum(counts),
            labels: labels,
            datasets: [{
                data: counts,
                backgroundColor: colours
            }]
        }
    }

})(jQuery, ko, $paramount);;
(function ($, $paramount) {

    $paramount.ui = $paramount.ui || {};
    $paramount.ui.eventDashboard = {
        init: function (eventDashboardViewModel) {
            var adDesignService = new $paramount.AdDesignService(eventDashboardViewModel.adId);
            var eventDashoardModel = new $paramount.models.EventDashboardModel(eventDashboardViewModel, adDesignService);
            ko.applyBindings(eventDashoardModel);
        }
    };

})(jQuery, $paramount);;
/*
 * jQuery UI hooks to elements for editing details for an Event Ad
 */
(function ($, ko, $paramount, notifier) {

    var $eventEditor = $('#eventEditor');
    $paramount.ui = $paramount.ui || {};
    $paramount.ui.eventEditor = {
        init: function (options) {
            // onReady function
            $(function () {
                var eventDetailsModel,
                    adDesignService = options.adDesignService || new $paramount.AdDesignService(),
                    imageService = options.imageService || new $paramount.ImageService();

                $.extend(options, {
                    adDesignService: adDesignService,
                    imageService: imageService
                });

                // Initally load the data
                adDesignService.getCurrentEventDetails().then(function (response) {
                    eventDetailsModel = new $paramount.models.EventAd(response, options);
                    ko.applyBindings(eventDetailsModel);
                });

                var $printImg = $('#imgCropContainer > img');
                var eventPhotoFileName;

                // Image upload handler
                $paramount.upload({
                    url: imageService.uploadCropImageUrl(),
                    element: $eventEditor.find('#eventPhotoUpload'),
                    progressBar: $eventEditor.find('#eventPhotoUploadProgress'),
                    complete: function (documentId) {
                        eventPhotoFileName = documentId;
                        $('#printCropImg').attr('src', imageService.renderCropImageUrl(documentId));
                        $('#printImageCropDialog').modal('show');
                    },
                    error: function (errorMsg) {
                        eventDetailsModel.eventPhotoUploadError(errorMsg);
                    }
                });

                $('#printImageCropDialog').on('shown.bs.modal', function () {
                    $printImg.cropper({
//                        aspectRatio: 639 / 251,
                        modal: true,
                        dashed: false
                    });
                });

                $('#printImageCropDialog').on('hide.bs.modal', function (e) {
                    $printImg.cropper('destroy');
                });

                $('#btnCancelCropping').on('click', function () {
                    if (eventPhotoFileName) {
                        imageService.cancelCropImage(eventPhotoFileName);
                    }
                });

                $('#btnDoneCropping').on('click', function () {
                    var $btn = $(this);
                    $btn.button('loading');
                    var data = $printImg.cropper("getData");
                    data.documentId = eventPhotoFileName;
                    imageService
                        .cropImage(eventPhotoFileName, data.x, data.y, data.width, data.height, false)
                        .then(function (documentId) {
                            $btn.button('reset');
                            $('#printImageCropDialog').modal('hide');
                            adDesignService.assignOnlineImage(documentId, true).then(function () {
                                eventDetailsModel.eventPhoto(documentId);
                                eventDetailsModel.eventPhotoUploadError(null);
                            });
                        });
                });

                $paramount.upload({
                    url: imageService.getUploadEventFloorplanUrl(),
                    element: $eventEditor.find('#locationFloorUpload'),
                    progressBar: $eventEditor.find('#locationFloorUploadProgress'),
                    completeWithDetails : function(doc) {
                        eventDetailsModel.locationFloorPlanDocumentId(doc.documentId);
                        eventDetailsModel.locationFloorPlanFilename(doc.fileName);
                    },
                    error : function(errorMsg) {
                        eventDetailsModel.locationFloorPlanDocumentId(null);
                        notifier.error(errorMsg);
                    }
                });

                $eventEditor.find('#eventForm').on('submit', function (e) {
                    // Todo - refactor this crap and use knockout validation instead
                    if ($(this).valid() === false
                        || eventDetailsModel.eventEndDateValidation() !== ''
                        || eventDetailsModel.eventEndTimeValidation() !== '') {
                        e.preventDefault();
                        $eventEditor.find('button').button('reset');
                        return;
                    }

                    eventDetailsModel.submitChanges().then(function (resp) {
                        if (resp.nextUrl) {
                            return;
                        }
                        $eventEditor.find('button').button('reset');
                    });
                    e.preventDefault();
                });

                
            });
        }
    }

})(jQuery, ko, $paramount, toastr);;
(function ($, ko, $p) {

    function EventGroup(data) {
        var me = this;
        me.eventGroupId = ko.observable();
        me.eventId = ko.observable();
        me.groupName = ko.observable();
        me.maxGuests = ko.observable();
        me.guestCount = ko.observable();


        if (data) {
            me.bind(data);
        }

        me.maxGuestsText = ko.computed(function () {
            return me.maxGuests() === null ? "Unlimited" : me.maxGuests();
        });

        me.groupNameWithCount = ko.computed(function() {
            if (!me.maxGuests()) {
                return me.groupName();
            }

            return me.groupName() + " (" + me.guestCount() + " / " + me.maxGuests() + ")";
        });

    }

    EventGroup.prototype.bind = function (data) {
        this.eventGroupId(data.eventGroupId);
        this.eventId(data.eventId);
        this.groupName(data.groupName);
        this.maxGuests(data.maxGuests);
        this.guestCount(data.guestCount);
    }
    $p.models.EventGroup = EventGroup;
})(jQuery, ko, $paramount);
(function ($, ko, $p) {
    /*
     * Used for the EventBooked page after an EventBooking has been completed and groups are not required...
     */

    function EventGroupSelector(data) {
        var me = this;
        me.eventBookingId = ko.observable();
        me.eventBookingTickets = ko.observableArray();
        me.showGroupSelection = ko.observable();
        if (data) {
            me.bind(data);
        }
    }
    
    EventGroupSelector.prototype.bind = function (data) {
        var me = this;
        me.eventBookingId(data.eventBookingId);
        _.each(data.eventBookingTickets, function (t) {
            t.eventId = data.eventId;
            me.eventBookingTickets.push(new $p.models.EventGroupTicket(t));
        });

    }
    $p.models.EventGroupSelector = EventGroupSelector;
})(jQuery, ko, $paramount);;
(function ($, ko, $p) {
    function EventGroupTicket(data) {

        var me = this;
        me.eventId = ko.observable();
        me.eventTicketId = ko.observable();
        me.eventBookingTicketId = ko.observable();
        me.ticketName = ko.observable();
        me.guestFullName = ko.observable();
        me.selectedGroup = ko.observable();
        me.groups = ko.observableArray();
        me.isUpdating = ko.observable(false);
        me.errorMsg = ko.observable('');

        if (data) {
            me.bind(data);
        }

        me.friendlyTicketName = ko.computed(function () {
            return me.guestFullName() + ' - ' + me.ticketName();
        });

        me.isGroupSelected = ko.computed(function () {
            return _.isUndefined(me.selectedGroup()) === false;
        });


        function SelectControl(element) {
            var $el = $(element.currentTarget);
            var $formGroup = $el.closest('.form-group-lg');

            return {
                reset: function () {
                    return $formGroup.removeClass('has-error').removeClass('has-success');
                },
                error: function () {
                    return this.reset().addClass('has-error');
                },
                success: function () {
                    return this.reset().addClass('has-success');
                }
            }
        }

        var eventService = new $p.EventService();
        me.groupChanged = function (item, el) {
            var control = new SelectControl(el);
            me.errorMsg('');

            if (me.isGroupSelected()) {
                me.isUpdating(true);
                eventService.assignGroup(me.eventBookingTicketId(), me.selectedGroup().eventGroupId())
                    .then(function (resp) {
                        if (resp === true) {
                            control.success();
                        } else if (_.isArray(resp) && resp.length > 0) {
                            me.errorMsg(resp[0].value[0]);
                            control.error();
                        }
                        me.isUpdating(false);
                    });

            } else {
                // Remove group from the ticket
                control.reset();

                me.isUpdating(true);
                eventService.assignGroup(me.eventBookingTicketId(), null).then(function (resp) {
                    me.isUpdating(false);
                    if (_.isArray(resp) && resp.length > 0) {
                        me.errorMsg(resp[0].value[0]);
                        control.error();
                    }
                });
            }
        }
    }

    EventGroupTicket.prototype.bind = function (data) {
        this.eventId(data.eventId);
        this.eventBookingTicketId(data.eventBookingTicketId);
        this.ticketName(data.ticketName);
        this.guestFullName(data.guestFullName);
        this.eventTicketId(data.eventTicketId);

        var me = this;
        var service = new $paramount.EventService();
        service.getGroupsForTicket(this.eventId(), this.eventTicketId())
            .then(function (resp) {
                _.each(resp, function (gr) {
                    me.groups.push(new $p.models.EventGroup(gr));
                });
            });
    }

    $p.models.EventGroupTicket = EventGroupTicket;
})(jQuery, ko, $paramount);
(function ($, ko, $paramount) {

    function CurrentGuest(data) {
        var me = this;
        var adDesignService = new $paramount.AdDesignService(data.adId);

        me.guestFullName = ko.observable(data.guestFullName);
        me.guestEmail = ko.observable(data.guestEmail);
        me.groupName = ko.observable(data.groupName);
        me.dynamicFields = ko.observableArray();
        $.each(data.dynamicFields, function (idx, f) {
            me.dynamicFields.push(new $paramount.models.DynamicFieldValue(f));
        });

        me.editGuestUrl = ko.observable(adDesignService.editGuestUrl(data.ticketNumber));
    }

    $paramount.models = $paramount.models || {};
    $paramount.models.CurrentGuest = CurrentGuest;


})(jQuery, ko, $paramount);;
(function ($, ko, $paramount) {

    function EventPaymentRequest(data, adDesignService) {
        var me = this;
        me.selectedPaymentType = ko.observable(data.preferredPaymentType);
        me.eventId = ko.observable(data.eventId);
        me.isPayPalConfigured = ko.observable(data.payPalEmail !== null);
        me.isDirectDebitConfigured = ko.observable(data.hasDirectDebitDetails);
        me.amountOwed = ko.observable(data.amountOwed);

        me.selectPayPal = function () {
            me.selectedPaymentType($paramount.PAYMENT.PAYPAL);
        }

        me.selectDirectDebit = function () {
            me.selectedPaymentType($paramount.PAYMENT.DIRECT_DEBIT);
        }

        me.isPayPalSelected = ko.computed(function () {
            return me.selectedPaymentType() === $paramount.PAYMENT.PAYPAL;
        });

        me.isDirectDebitSelected = ko.computed(function () {
            return me.selectedPaymentType() === $paramount.PAYMENT.DIRECT_DEBIT;
        });

        me.canSubmitPaymentRequest = ko.computed(function () {
            if (me.selectedPaymentType() === $paramount.PAYMENT.PAYPAL && me.isPayPalConfigured()) {
                return true;
            }
            if (me.selectedPaymentType() === $paramount.PAYMENT.DIRECT_DEBIT && me.isDirectDebitConfigured()) {
                return true;
            }
            return false;
        });

        me.submitPaymentRequest = function (element, event) {
            var $btn = $(event.target); // Grab the jQuery element from knockout
            $btn.button('loading');

            var paymentRequest = {
                paymentMethod: me.selectedPaymentType(),
                requestedAmount : me.amountOwed(),
                eventId: me.eventId()
            }
            adDesignService.requestEventPayment(paymentRequest)
                .then(function () {
                    $btn.button('reset');
                });
        }
    }

    $paramount.models = $paramount.models || {};
    $paramount.models.EventPaymentRequest = EventPaymentRequest;


})(jQuery, ko, $paramount);;
(function ($, $paramount) {
    $paramount.ui = $paramount.ui || {};
    $paramount.ui.eventPaymentRequest = {
        init: function (eventPaymentRequestViewModel) {
            var $rootElement = $('.event-payment-request');

            /*
             * Knockout model
             */

            var adDesignService = new $paramount.AdDesignService(eventPaymentRequestViewModel.adId);
            var viewModel = new $paramount.models.EventPaymentRequest(eventPaymentRequestViewModel, adDesignService);
            ko.applyBindings(viewModel, $rootElement.get(0));
        }
    }

})(jQuery, $paramount);;
(function ($, $paramount, ko) {
    
    function EventTicket(data, maxTicketsPerBooking) {

        var me = this;

        me.adId = ko.observable();
        me.eventId = ko.observable();
        me.eventTicketId = ko.observable();
        me.ticketName = ko.observable();
        me.availableQuantity = ko.observable();
        me.price = ko.observable();
        me.isActive = ko.observable();
        me.priceFormatted = ko.computed(function () {
            return $paramount.formatCurrency(me.price());
        });
        me.selectedQuantity = ko.observable();
        me.remainingQuantity = ko.observable();
        me.soldQuantity = ko.observable();
        me.isAvailable = ko.observable();
        me.maxTicketsPerBooking = ko.observableArray();
        me.eventGroupId = ko.observable();
        me.eventGroupName = ko.observable();
        me.editTicketUrl = ko.observable();
        

        /*
         * Computed functions
         */
        me.soldOut = ko.computed(function () {
            return me.remainingQuantity() <= 0;
        });

        
        /*
         * Validation
         */
        me.validator = ko.validatedObservable({
            ticketName: me.ticketName.extend({ required: true }),
            availableQuantity: me.availableQuantity.extend({ min: 0, required: true }),
            remainingQuantity: me.remainingQuantity.extend({ min: 0, required: true }),
            price: me.price.extend({ min: 0, required: true })
        });

        if (data) {
            me.bindEventTicket(data, maxTicketsPerBooking);
        }
    }

    EventTicket.prototype.bindEventTicket = function (data, maxTicketsPerBooking) {
        var me = this;
        me.adId(data.adId);
        me.eventId(data.eventId);
        me.eventTicketId(data.eventTicketId);
        me.ticketName(data.ticketName);
        me.availableQuantity(data.availableQuantity);
        me.isActive(data.isActive);
        me.price(data.price);
        me.selectedQuantity(data.selectedQuantity);
        me.remainingQuantity(data.remainingQuantity);
        me.isAvailable(data.remainingQuantity > 0);
        me.soldQuantity(data.soldQty);
       
        me.editTicketUrl('/event-dashboard/' + data.adId + '/event-ticket/' + data.eventTicketId);

        // MaxTickets Per booking setup
        if (maxTicketsPerBooking) {
            if (data.remainingQuantity < maxTicketsPerBooking) {
                maxTicketsPerBooking = data.remainingQuantity;
            }

            for (var i = 0; i <= maxTicketsPerBooking; i++) {
                me.maxTicketsPerBooking.push({ label: i, value: i });
            }
        }

    }


    $paramount.models = $paramount.models || {};
    $paramount.models.EventTicket = EventTicket;


})(jQuery, $paramount, ko, toastr);;
(function ($, $paramount, ko) {
    
    var eventService = new $paramount.EventService();

    function EventTicketReserved(data) {

        var me = this;
        me.eventTicketId = ko.observable();
        me.eventTicketReservationId = ko.observable();
        me.ticketName = ko.observable();
        me.guestFullName = ko.observable();
        me.guestEmail = ko.observable();
        me.price = ko.observable();
        me.status = ko.observable();
        me.isReserved = ko.observable();
        me.notReserved = ko.observable();
        me.ticketFields = ko.observableArray();
        me.eventGroupName = ko.observable();
        me.isPublic = ko.observable();
        me.displayGuests = ko.observable();
        me.seatNumber = ko.observable();

        /*
         * Computed functions
         */
        me.totalCostFormatted = ko.computed(function () {
            if (data.price === 0)
                return 'FREE';

            return $paramount.formatCurrency(me.price());
        });

        me.ticketTypeAndPrice = ko.computed(function () {
            var t = data.ticketName;
            if (data.price > 0) {
                t += " " + $paramount.formatCurrency(data.price);
            }
            return t;
        });

        /*
         * Validation
         */
        me.validator = ko.validatedObservable({
            guestFullName: me.guestFullName.extend({ required: true }),
            guestEmail: me.guestEmail.extend({ required: true, email: true })
        });
        
        this.bindTicketReservation(data);

    }

    EventTicketReserved.prototype.bindTicketReservation = function (data) {
        $.extend(data, {});

        var me = this;
        me.eventTicketId(data.eventTicketId);
        me.eventTicketReservationId(data.eventTicketReservationId);
        me.ticketName(data.ticketName);
        me.price(data.price);
        me.status(data.status);
        var isReserved = data.status.toLowerCase() === 'reserved';
        me.isReserved(isReserved);
        me.notReserved(isReserved === false);
        if (data.guestFullName) {
            me.guestFullName(data.guestFullName);
        }
        if (data.guestEmail) {
            me.guestEmail(data.guestEmail);
        }
        me.isPublic(data.isPublic);
        me.displayGuests(data.displayGuests);
        me.seatNumber(data.seatNumber);
        
        /*
        * Fetch the fields required for each ticket (if any)
        */
        eventService.getFieldsForTicket(data.eventTicketId).then(function (resp) {
            $.each(resp, function (fieldIndex, f) {
                me.ticketFields.push(new $paramount.models.DynamicFieldValue(f));
            });
        });

        if (data.eventGroupId) {
            data.getGroupsPromise.then(function (groups) {
                var group = _.find(groups, { 'eventGroupId': data.eventGroupId });
                me.eventGroupName(group.groupName);
            });
        }
    }
        
    $paramount.models = $paramount.models || {};
    $paramount.models.EventTicketReserved = EventTicketReserved;


})(jQuery, $paramount, ko);;
(function(ko, $p) {
    
    $p.models.GuestSettings = function(data) {
        var me = this,
            adDesignService = new $p.AdDesignService(data.id);

        me.eventId = ko.observable(data.eventId);
        me.displayGuests = ko.observable(data.displayGuests);

        me.saveGuestSettings = function(model, event) {
            var $btn = $(event.target);
            $btn.loadBtn();

            adDesignService.updateEventGuestSettings(ko.toJS(model))
                .success(function() {
                    toastr.success('Settings updated successfully');
                });
        }
    }

})(ko, $paramount);;
(function($, $paramount) {

    $paramount.ui = $paramount.ui || {};
    $paramount.ui.invitation = {
        init: function (eventId, eventInvitationId, availableTickets) {
            
            var service = new $paramount.EventService();

            // On ready
            $(function() {
                $('button[data-ticket]').on('click', function() {
                    var $me = $(this);
                    var selected = $me.data().ticket;
                    var ticket = _.find(availableTickets, function(t) { return t.eventTicketId === selected });
                    ticket.selectedQuantity = 1;

                    var order = {
                        eventId : eventId,
                        eventInvitationId: eventInvitationId,
                        tickets: [ticket]
                    }

                    service.startTicketOrder(order);
                });
            });
        }
    }
    
})(jQuery, $paramount);
(function ($, ko, $p, $n) {
    
    var adDesignService;

    function ManageGroups(data) {

        adDesignService = new $p.AdDesignService(data.id);

        var me = this;
        me.id = ko.observable();
        me.eventId = ko.observable();
        me.groups = ko.observableArray();
        me.hasTickets = ko.observable();
        me.isCreateEnabled = ko.observable(false);
        me.newGroup = ko.observable(new GroupCreator(data));
        me.eventGroupSettings = ko.observable(new EventGroupSettings(data));

        me.createStart = function () {
            me.newGroup(new GroupCreator(data));
            me.isCreateEnabled(true);
        }

        me.createCancel = function () {
            me.isCreateEnabled(false);
        }

        me.create = function (model, event) {
            // Check validity
            if ($p.checkValidity(me.newGroup()) === false) {
                return;
            }

            // Set the available tickets

            var groupData = me.newGroup().toGroupData();

            var $btn = $(event.target);
            $btn.button('loading');
            adDesignService.addEventGroup(groupData).then(function (resp) {
                me.groups.push(new Group(groupData.availableTickets, groupData));
                me.isCreateEnabled(false);
                $n.success('Group has been created successfully');
            }).always(function () {
                $btn.button('reset');
            });
        }

        if (data) {
            me.bind(data);
        }

        me.generate = function (model, event) {
            var $btn = $(event.target);
            $btn.button('loading');

            // Create bunch of groups now based on the start and end
            me.newGroup().generateGroups(function (addedGroup) {
                me.groups.push(new Group(addedGroup.availableTickets, addedGroup));
            }, function () {
                $btn.button('reset');
                me.isCreateEnabled(false);
                $n.success('Done. Groups generated successfully.');
            });
        }

    }

    ManageGroups.prototype.bind = function (data) {
        var me = this;
        me.id(data.id);
        me.eventId(data.eventId);
        me.hasTickets(data.tickets && data.tickets.length > 0);

        _.each(data.eventGroups, function (gr) {
            me.groups.push(new Group(gr.availableTickets, gr));
        });
    }

    function GroupTicketSelection(data) {
        var me = this;
        me.eventTicketId = ko.observable(data.eventTicketId);
        me.ticketName = ko.observable(data.ticketName);
        me.isSelected = ko.observable(data.isSelected);
    }

    function GroupCreator(data) {
        var me = this;

        me.eventId = ko.observable(data.eventId);
        me.groupName = ko.observable();
        me.maxGuests = ko.observable();
        me.ticketSelection = ko.observableArray();
        me.availableTickets = ko.observableArray();
        me.guestCount = ko.observable(0);
        me.isEnabled = ko.observable(true);
        me.limitsEnabled = ko.observable(false);
        me.toggleLimits = function () {
            me.limitsEnabled(!me.limitsEnabled());
        }

        // Generation
        me.generateEnabled = ko.observable(false);
        me.generateStart = ko.observable();
        me.generateEnd = ko.observable();
        me.generateProgress = ko.observable(0);

        me.generateTotalGroups = ko.computed(function () {
            var first = parseInt(me.generateStart());
            var last = parseInt(me.generateEnd());
            return (last - first) + 1;
        });

        me.toggleGeneration = function () {
            me.generateEnabled(!me.generateEnabled());
        };

        me.generateError = ko.computed(function () {
            if (_.isUndefined(me.groupName())) {
                return 'You must provide a group name before generating.';
            }

            if (isNaN(me.generateStart()) || isNaN(me.generateEnd())) {
                return 'You must provide start and end before generating.';
            }

            var totalGroups = me.generateTotalGroups();

            if (totalGroups <= 1) {
                return 'Total groups must be equal or greater than two';
            }

            return '';
        });

        // Store all tickets for creating a new group
        _.each(data.tickets, function (t) {
            me.ticketSelection.push(new GroupTicketSelection(t));
        });

        me.toGroupData = function () {
            var jsonData = ko.toJS(me);

            jsonData.availableTickets = _.filter(jsonData.ticketSelection, function (i) { return i.isSelected === true });
            jsonData.isDisabled = !me.isEnabled();
            if (!jsonData.maxGuests || jsonData.maxGuests === '') {
                jsonData.maxGuests = null;
            }

            // Remove unused properties for submit
            delete jsonData.generateEnabled;
            delete jsonData.generateStart;
            delete jsonData.generateEnd;

            return jsonData;
        }

        me.generateGroups = function (onGroupAdded, onComplete) {
            var savedGroups = 0;

            var start = parseInt(me.generateStart());
            var end = parseInt(me.generateEnd());
            var totalGroups = end - start;

            for (var i = start; i <= end; i++) {
                var gr = me.toGroupData();
                gr.groupName += ' ' + i;

                adDesignService.addEventGroup(gr).success(function (resp) {
                    onGroupAdded(resp.group);

                    savedGroups++;
                    me.generateProgress((savedGroups / totalGroups) * 100);

                    if (savedGroups === totalGroups) {
                        onComplete();
                    }
                });
            }
        }


        /*
         * Validation
         */
        me.validator = ko.validatedObservable({
            groupName: me.groupName.extend({ required: true }),
            maxGuests: me.maxGuests.extend({ min: 0 })
        });

        me.isValid = $p.checkValidity(me);
    }

    function Group(availableTickets, groupData) {
        var me = this;
        me.eventGroupId = ko.observable(groupData.eventGroupId);
        me.groupName = ko.observable(groupData.groupName);
        me.maxGuests = ko.observable(groupData.maxGuests);
        me.maxGuestsText = ko.computed(function () {
            return me.maxGuests() === null ? "Unlimited" : me.maxGuests();
        });
        me.guestCount = ko.observable(groupData.guestCount);
        me.isEnabled = ko.observable(groupData.isDisabled === false);
        me.availableTickets = ko.observableArray();

        _.each(availableTickets, function (t) {
            me.availableTickets.push(new GroupTicketSelection(t));
        });
    }

    function EventGroupSettings(settings) {
        var me = this;
        me.eventId = ko.observable(settings.eventId);
        me.groupsRequired = ko.observable(settings.groupsRequired);

        me.update = function (model, event) {
            var $btn = $(event.target);
            $btn.loadBtn();

            var data = ko.toJS(me);
            adDesignService.updateEventGroupSettings(data).then(function () {
                $n.success('Group settings updated');
            });
        }
    }

    $p.models.ManageGroups = ManageGroups;

})(jQuery, ko, $paramount, toastr);;
(function ($, ko, toastr, $p) {

    var adDesignService;

    function ManageTickets(data) {
        adDesignService = new $p.AdDesignService(data.id);

        var me = this;
        me.id = ko.observable(data.id);
        me.eventId = ko.observable(data.eventId);
        me.ticketSettings = new TicketSettings(data.eventId, data.ticketSettings);

        me.tickets = $p.ko.bindArray(data.tickets, function (t) {
            t.adId = data.id;
            return new $p.models.EventTicket(t);
        });

        me.isCreateEnabled = ko.observable(false);

        me.removeField = function (f) {
            me.newTicket().eventTicketFields.remove(f);
        }

        me.ticketSaved = function (newTicketDetails) {
            toastr.success('Ticket ' + newTicketDetails.ticketName + ' has been added successfully.');
            newTicketDetails.soldQty = 0;
            newTicketDetails.adId = me.id();
            me.tickets.push(new $p.models.EventTicket(newTicketDetails));
            me.isCreateEnabled(false);
        }
    }

    ManageTickets.prototype.startNewTicket = function () {
        this.isCreateEnabled(true);
    }

    ManageTickets.prototype.cancelNewTicket = function () {
        this.isCreateEnabled(false);
    }

    function TicketSettings(eventId, data) {
        var me = this;

        me.eventId = ko.observable(eventId);
        me.includeTransactionFee = ko.observable(data.includeTransactionFee);
        me.closingDate = ko.observable(data.closingDate);
        me.openingDate = ko.observable(data.openingDate);

        me.updateTicketSettings = function (model, event) {
            var $btn = $(event.target);
            $btn.loadBtn();

            adDesignService.editTicketSettings(model.eventId(), ko.toJS(model))
                .success(function (resp) {
                    if (!resp.errors) {
                        toastr.success("Settings updated successfully.");
                    }
                });
        }
    }

    $p.models.ManageTickets = ManageTickets;

})(jQuery, ko, toastr, $paramount);;
/*
 * ViewEventAd.cshtml - ui hooks
 */
(function ($, ko, $paramount) {

    $paramount.ui = $paramount.ui || {};
    $paramount.ui.eventView = {
        init: function (options) {
            $(function () {
                var ticketingInterface = document.getElementById('ticketing');
                if (ticketingInterface) {
                    ko.applyBindings({}, ticketingInterface);
                }

                var guestsDialogInterface = document.getElementById('guestsDialog');
                if (guestsDialogInterface) {
                    ko.applyBindings({}, guestsDialogInterface);
                }

                var ticketSeatingInterface = document.getElementById('ticketSeating');
                if (ticketSeatingInterface) {
                    ko.applyBindings({}, ticketSeatingInterface);
                }

                var contactAdvertiserInterface = document.getElementById('contactAdvertiserForm');
                if (contactAdvertiserInterface) {
                    ko.applyBindings({}, contactAdvertiserInterface);
                }

                if (options.floorPlanDocumentId === '') {
                    $('.floor-plan').hide();
                } else if (options.floorPlanFileName.endsWith('.pdf')) {
                    var url = $paramount.baseUrl + 'Document/File/' + options.floorPlanDocumentId;
                    $('#btnViewFloorplan')
                        .removeAttr('data-target')
                        .removeAttr('data-toggle')
                        .attr('target', '_blank')
                        .attr('href', url);
                }

                $('.ticket-booth').affix({
                    offset: {
                        top: 300
                    }
                });
            });
        }
    }

})(jQuery, ko, $paramount);
(function (ko, $p) {

    var eventService = new $p.EventService($p.baseUrl);

    $p.models.EventList = function (params) {
        var me = this;
        me.events = ko.observableArray();
        me.userEnabled = params.user && params.user === true;
        me.loading = ko.observable(true);

        var query = new $p.EventQuery()
            .withMax(params.maxItems)
            .withUser(params.user)
            .build();
        
        eventService.searchEvents(query).then(function (response) {
            if (response.errors) {
                return;
            }

            if (!Array.isArray(response)) {
                throw new Error("The response does not contain an array of events.");
            }
            
            _.each(response, function (item) {
                me.events.push(item);
            });

            me.loading(false);
        });
    };

    ko.components.register('event-list', {
        viewModel: $p.models.EventList,
        template: { path: $p.baseUrl + 'Scripts/app/events/eventListing/eventList.html' }
    });


})(ko, $paramount);;
(function (ko, $p) {

    ko.components.register('event-listing', {
        viewModel: EventListing,
        template: { path: $p.baseUrl + 'Scripts/app/events/eventListing/eventListing.html' }
    });

    var imgService = new $p.ImageService($p.baseUrl);
    var eventService = new $p.EventService($p.baseUrl);

    function EventListing(params) {

        var listing = params.listing;
        this.adId = listing.adId;
        this.eventId = listing.eventId;
        this.eventName = listing.heading;
        this.eventShortName = listing.eventShortName;
        this.eventUrl = listing.eventUrl;
        this.category = listing.categoryName;
        this.parentCategory = listing.parentCategoryName;
        this.shortDescription = listing.shortDescription;
        this.startDate = $p.dateToDisplay(listing.eventStartDate);
        this.startDateHumanized = listing.eventStartDateHumanized;
        this.endDate = listing.endDate;
        this.location = listing.location.replace(', Australia', '');
        this.categoryFontIcon = "fa fa-5x fa fa-" + listing.categoryFontIcon;
        this.eventDashboardUrl = listing.editAdUrl;
        this.isPastEvent = $p.isUtcDateBeforeNow(listing.eventStartDateUtc);
        this.isComingSoon = this.isPastEvent === false;
        this.userEnabled = params.user === true;
        this.photo = getPhotoUrl(listing, params);
        this.ticketInfo = getTicketInfo(listing);
        this.isClosed = listing.isClosed;
    }

    function getPhotoUrl(listing, params) {
        if (!listing.primaryImage) {
            return null;
        }
        return imgService.getImageUrl(listing.primaryImage, {
            w: params.imgHeight || 500,
            h: params.imgWidth || 300
        });
    }

    function getTicketInfo(listing) {
        if (!listing.hasTickets) {
            return null;
        }

        if (listing.areAllTicketsFree === true) {
            return 'Free';
        }
        
        if (listing.isClosed === true) {    
            return 'Ticketing Closed';
        }

        var info = $paramount.formatCurrency(listing.cheapestTicket);
        if (listing.cheapestTicket !== listing.mostExpensiveTicket) {
            info += ' - ' + $paramount.formatCurrency(listing.mostExpensiveTicket);
        }
        return info;
    }

    $p.models.EventListing = EventListing;

})(ko, $paramount);;
(function ($p) {

    $p.EventQuery = function () {
        var me = this;
        me.query = {};

        return {
            withMax: function (max) {
                if (max) {
                    me.query.pageSize = max;
                }
                return this;
            },
            withUser: function (user) {
                if (user) {
                    me.query.user = user;
                }
                return this;
            },
            build: function () {
                return me.query;
            }
        }
    }

})($paramount);;
(function (ko, $p) {

    ko.components.register('featured-events', {
        viewModel: function (params) {
            var eventListings = ko.observableArray();
            var eventService = new $p.EventService($p.baseUrl);
            eventService.getEvents().then(function () {
                eventListings.push(new $p.models.EventListing());
            });
        },
        template: { path: $p.baseUrl + 'Scripts/app/events/featuredEvents/featuredEvents.html' }
    });

})(ko, $paramount);;
(function (ko, $p, toastr) {
    ko.components.register('add-organiser', {

        viewModel: function (params) {
            var organiserService = new $p.OrganiserService(params.eventId);

            var me = this;
            me.email = ko.observable();

            me.submit = function (model, event) {

                if (!$p.checkValidity(me)) {
                    return;
                }
                var $btn = $(event.target);
                $btn.loadBtn();

                organiserService.addOrganiser(me.email())
                    .success(function (r) {
                        if (r.errors) {
                            return;
                        }

                        me.email(null);

                        if (params.onSuccess) {
                            params.onSuccess(r);
                        }
                    });
            }

            me.cancel = function () {
                me.email(null);
                if (params.onCancel) {
                    params.onCancel();
                }
            }

            me.validator = ko.validatedObservable({
                email: me.email.extend({
                    required: true,
                    email: true,
                    maxLength: 100,
                    mustNotEqual: {
                        params: params.ownerEmail,
                        message: 'This email is already the owner'
                    }
                })
            });

        },
        template: { path: $p.baseUrl + 'Scripts/app/events/organisers/add-organiser.html' }
    });
})(ko, $paramount, toastr);;
(function ($, $p, ko, moment) {

    $p.models.EventOrganiser = function (data) {

        var me = this;

        me.eventOrganiserId = ko.observable(data.eventOrganiserId);
        me.email = ko.observable(data.email);
        me.lastModifiedDate = moment.utc(data.lastModifiedDateUtc).local().format($p.jsToDisplayDateFormat);
        me.status = ko.observable(getStatus(data));
        me.userId = ko.observable(data.userId);
        me.inviteToken = ko.observable(data.inviteToken);

        me.statusClass = ko.computed(function () {
            console.log(me.status());
            if (me.status() === 'Active') {
                return "label-success";
            }

            return 'label-warning';
        });
    }

    function getStatus(organiser) {
        if (organiser.userId !== null && organiser.userId !== '') {
            return "Active";
        }

        if (organiser.inviteToken !== null) {
            return "Invited";
        }

        return null;
    }

})(jQuery, $paramount, ko, moment);;
(function ($, $p, ko, toastr) {

    $p.models.ManageNotifications = function (data) {

        var me = this;
        var organiserService = new $p.OrganiserService(data.eventId);

        me.adId = ko.observable(data.adId);
        me.eventId = ko.observable(data.eventId);
        me.subscribeToPurchaseNotifications = ko.observable(data.subscribeToPurchaseNotifications);
        me.subscribeToDailyNotifications = ko.observable(data.subscribeToDailyNotifications);

        me.save = function (data, element) {
            var $btn = $(element.target);
            var model = ko.toJS(me);

            organiserService.setNotifications(model)
                .then(function () {
                    toastr.success("Settings updated successfully");
                    $btn.resetBtn();
                });
        }
    }

})(jQuery, $paramount, ko, toastr);;
(function ($, $p, ko, toastr) {

    $p.models.ManageOrganisers = function (data) {

        var me = this;
        var organiserService = new $p.OrganiserService(data.eventId);

        me.showAddOrganiser = ko.observable(false);
        me.organisers = $p.ko.bindArray(data.organisers, function (orgData) {
            return new $p.models.EventOrganiser(orgData);
        });

        // Triggers when add-organiser component fires
        me.organiserAdded = function (organiser) {
            toastr.success('Organiser has been invited.');
            me.organisers.push(new $p.models.EventOrganiser(organiser));
            me.showAddOrganiser(false);
        }

        me.cancelAdd = function () {
            me.showAddOrganiser(false);
        }

        me.addOrganiser = function () {
            me.showAddOrganiser(true);
        }

        me.removeOrganiser = function (model) {
            var eventOrganiserId = model.eventOrganiserId();
            organiserService.removeOrganiser(eventOrganiserId)
                .then(function (resp) {
                    if (resp === true) {
                        me.organisers.remove(model);
                        toastr.warning("Organiser " + model.email() + " has been removed");
                    }
                });
        }
    }

})(jQuery, $paramount, ko, toastr);;
(function ($, $p) {

    $p.OrganiserService = function (eventId) {
        var me = this,
            baseUrl = $p.baseUrl + 'event-dashboard/' + eventId + '/organisers';

        return {

            addOrganiser: function (email) {

                return $p.httpPost(baseUrl + '/invite', { email: email });

            },

            removeOrganiser: function (eventOrganiserId) {
                return $p.httpPost(baseUrl + '/remove', { eventOrganiserId: eventOrganiserId });
            },

            setNotifications : function(settings) {
                return $p.httpPost(baseUrl + '/notifications', settings);
            }
        }

    }

})(jQuery, $paramount);;
(function ($, $p, ko) {

    $p.models.EventPromoCode = function (data) {
        var me = this;

        me.eventPromoCodeId = ko.observable(data.eventPromoCodeId);
        me.eventId = ko.observable(data.eventId);
        me.promoCode = ko.observable(data.promoCode);
        me.discountPercent = ko.observable(data.discountPercent);
        me.isDisabled = ko.observable(data.isDisabled);
        me.createdDate = ko.observable(data.createdDate);
        me.bookingCount = ko.observable(data.bookingCount || 0);

        // Validation
        me.validator = ko.validatedObservable({
            promoCode: me.promoCode.extend({ required: true, maxlength: 50 }),
            discountPercent: me.discountPercent.extend({ min: 0, max: 100 })
        });

        me.discountDisplay = ko.computed(function() {
            if (!me.discountPercent()) {
                return "";
            }

            return me.discountPercent() + '%';
        });
    }

})(jQuery, $paramount, ko);;
(function ($, $p, ko) {

    $p.models.ManagePromoCodes = function (data) {
        var service = $p.PromoCodeService(data.eventId);
        var me = this;
        me.adId = data.adId;
        me.eventId = data.eventId;
        me.showAdd = ko.observable(false);
        me.promoCodes = $p.ko.bindArray(data.promoCodes, function (p) {
            return new $p.models.EventPromoCode(p);
        });

        me.newPromoCode = new $p.models.EventPromoCode({
            eventId: data.eventId,
            isDisabled: false
        });

        /*
        * Methods
        */

        me.cancelAdd = function () {
            me.showAdd(false);
        }

        me.displayAddPromo = function () {
            me.showAdd(true);
        }

        me.addPromoCode = function (model, event) {

            if (!$p.checkValidity(me.newPromoCode)) {
                return;
            }

            var $btn = $(event.target);
            $btn.loadBtn();


            var vm = ko.toJS(me.newPromoCode);
            service.add(vm).then(function (response) {
                if (response.errors) {
                    return;
                }

                me.promoCodes.push(new $p.models.EventPromoCode(response));
                toastr.success('Promo code has been added successfully.');
                me.showAdd(false);
                me.newPromoCode.promoCode(null);
                me.newPromoCode.discountPercent(null);

            }).always(function () {
                $btn.resetBtn();
            });
        }

        me.remove = function (model, event) {
            var $btn = $(event.target);
            $btn.loadBtn();

            service.remove(model.eventPromoCodeId()).then(function () {
                me.promoCodes.remove(model);
            });
        }
    }

})(jQuery, $paramount, ko);;
(function ($, $p) {

    $p.PromoCodeService = function (eventId) {
        var me = this,
            baseUrl = $p.baseUrl + 'event-dashboard/' + eventId + '/promos';

        return {

            add: function (eventPromo) {
                return $p.httpPost(baseUrl + '/create', { eventPromo: eventPromo });
            },

            remove: function (eventPromoCodeId) {
                return $p.httpPost(baseUrl + '/remove', { eventPromoCodeId: eventPromoCodeId });
            }

        }

    }

})(jQuery, $paramount);;
(function ($, ko, $p, eventService, notifier) {

    function Seat(seatData, rowData, ticketsData) {
        var me = this;
        me.id = ko.observable(seatData.id);
        me.seatNumber = ko.observable(seatData.seatNumber);
        me.available = ko.observable(seatData.available || false);
        me.selected = ko.observable(seatData.selected || false);
        var ticket = _.find(ticketsData, { eventTicketId: seatData.eventTicketId });
        me.ticketName = ticket.ticketName;
        me.price = $p.formatCurrency(ticket.price);
        me.ticket = new $p.models.EventTicket(ticket);
        me.style = ko.observable({ 'background-color': seatData.available === true ? ticket.colourCode : '#eee' });
        me.tooltip = ko.computed(function () {
            if (me.available() === true) {
                return me.seatNumber();
            }
            return 'Unavailable - ' + me.seatNumber();
        });
    }

    function Row(data, ticketsData) {
        var me = this;
        me.rowName = ko.observable(data.rowName);
        me.seats = ko.observableArray();

        for (var i = 0; i < data.seats.length; i++) {
            me.seats.push(new Seat(data.seats[i], me, ticketsData));
        }
    }

    function SeatSelector(params) {
        var me = this;
        me.eventId = ko.observable(params.eventId);
        me.tickets = ko.observableArray();
        me.rows = ko.observableArray();
        me.selectedSeats = ko.observableArray();
        me.loading = ko.observable(true);

        me.openingDate = ko.observable();
        me.ticketingNotOpened = ko.observable(false);
        me.ticketingClosed = ko.observable(false);
        me.ticketingOpened = ko.observable(false);

        if (params.openingDate) {
            var opening = moment.utc(params.openingDate).local();
            me.openingDate(opening);
            me.ticketingNotOpened(opening.isAfter(moment()));
        }

        if (params.closingDate) {
            var closing = moment.utc(params.closingDate).local();
            me.ticketingClosed(closing.isBefore(moment()));
        }

        if (params.eventEndDate) {
            var isTicketingClosed = $p.isUtcDateBeforeNow(params.eventEndDate);
            me.ticketingClosed(isTicketingClosed);
        }

        me.ticketingOpened(!me.ticketingNotOpened() && !me.ticketingClosed());

        me.selectSeat = function (seat) {
            if (seat.available() === false) {
                return;
            }

            if (_.includes(me.selectedSeats(), seat)) {
                me.selectedSeats.remove(seat);
                notifier.warning('Seat ' + seat.seatNumber() + ' removed.');
            } else {

                if (me.selectedSeats().length >= params.maxSeats) {
                    notifier.info('You have reached your maximum selection of ' + params.maxSeats + ' seats.');
                    return;
                }

                notifier.success('Seat ' + seat.seatNumber() + ' selected.');
                me.selectedSeats.push(seat);
            }

            seat.selected(!seat.selected());
        }

        me.removeTicket = function (seat) {
            me.selectedSeats.remove(seat);
            seat.selected(false);
        }

        me.bookSeats = function (model, event) {
            var $btn = $(event.target);
            $btn.loadBtn();

            if (me.selectedSeats().length > 0) {
                var tickets = [];
                _.each(me.selectedSeats(), function (s) {
                    var ticketData = ko.toJS(s.ticket);
                    ticketData.seatNumber = s.seatNumber();
                    ticketData.selectedQuantity = 1;
                    tickets.push(ticketData);
                });

                var order = {
                    eventId: me.eventId(),
                    tickets: tickets
                }

                eventService.startTicketOrder(order);
            }
        }

        me.seatsRenderComplete = function () {
            me.loading(false);
        }

        // Load the seating
        if (me.ticketingOpened()) {

            eventService.getEventSeating(params.eventId, params.orderRequestId).then(loadSeating);

            function loadSeating(seatingResponse) {

                _.each(seatingResponse.tickets, function (t) {
                    var remainingPercentage = parseInt((t.remainingQuantity / t.availableQuantity) * 100);
                    var isSoldOut = t.remainingQuantity <= 0;
                    var ticketNameAndPrice = isSoldOut === true
                        ? "SOLD OUT"
                        : t.ticketName + ' ' + $p.formatCurrency(t.price) + ' - ' + remainingPercentage + '% left';
                        
                    
                    me.tickets.push({
                        ticketNameAndPrice: ticketNameAndPrice,
                        soldOut: isSoldOut,
                        style: { 'background-color': t.colourCode }
                    });
                });

                // Todo - support different type of layouts? how ???
                _.each(seatingResponse.rows, function (r) {
                    me.rows.push(new Row(r, seatingResponse.tickets));
                });
            }
        }

    }

    ko.components.register('seat-selector', {
        viewModel: SeatSelector,
        template: {
            path: $p.baseUrl + 'Scripts/app/events/seatSelector/seatSelector.html'
        }
    });

})(jQuery, ko, $paramount, new $paramount.EventService(), toastr);;
(function (ko, $p, toastr) {
    ko.components.register('ticket-editor', {
        viewModel: function (params) {
            $p.guard(params.eventId, 'eventId');

            var me = this,
                adDesignService = new $p.AdDesignService(params.adId),
                eventService = new $p.EventService(),
                resendGuestNotifications = false;

            me.eventId = ko.observable(params.eventId); // Must be set!
            me.eventTicketId = ko.observable();
            me.ticketName = ko.observable();
            me.isActive = ko.observable(true);
            me.availableQuantity = ko.observable(); // Only available in create
            me.remainingQuantity = ko.observable(); // Only available in edit
            me.price = ko.observable();
            me.eventTicketFields = ko.observableArray();
            me.editMode = ko.observable(false);
            me.soldQty = ko.observable();
            me.colourCode = ko.observable();
            me.displayGuestPurchasesWarning = ko.observable(false);
            me.displayNotificationProgress = ko.observable(false);
            me.ticketHasPurchases = ko.observable(false);
            me.guestsAffected = ko.observable(0);
            me.guestsNotified = ko.observable(0);
            me.ticketImage = ko.observable();
            me.onSave = params.onSave;


            var ticketDetails = params.ticketDetails;

            if (ticketDetails) {

                me.eventTicketId(ticketDetails.eventTicketId);
                me.editMode(true);
                me.ticketName(ticketDetails.ticketName);
                me.availableQuantity(ticketDetails.availableQuantity);
                me.remainingQuantity(ticketDetails.remainingQuantity);
                me.isActive(ticketDetails.isActive);
                me.price(ticketDetails.price);
                me.colourCode(ticketDetails.colourCode);
                me.ticketHasPurchases(ticketDetails.soldQty > 0);
                me.soldQty(ticketDetails.soldQty);
                me.ticketImage(ticketDetails.ticketImage);

                _.each(ticketDetails.eventTicketFields, function (field) {
                    me.eventTicketFields.push(new $p.models.DynamicFieldDefinition(me, field));
                });
            }

            me.addField = function () {
                me.eventTicketFields.push(new $p.models.DynamicFieldDefinition(me));
                if (me.ticketHasPurchases() === true) {
                    me.displayGuestPurchasesWarning(true);
                }
            }

            me.removeField = function (field) {
                me.eventTicketFields.remove(field);
                if (me.ticketHasPurchases() === true) {
                    me.displayGuestPurchasesWarning(true);
                }
            }

            me.saveTicket = function (model, event) {
                me.saveWithoutSendingNotifications(model, event);
            }

            me.ticketName.subscribe(function () {
                if (me.ticketHasPurchases()) {
                    me.displayGuestPurchasesWarning(true);
                }
            });

            me.saveWithoutSendingNotifications = function (model, event) {
                resendGuestNotifications = false;
                save(model, event);
            }

            me.saveAndSendNotifications = function (model, event) {
                resendGuestNotifications = true;
                save(model, event);
            }

            me.removeImage = function (imageId) {
                me.ticketImage(null);
            }

            function save(model, event, options) {

                if (!$p.checkValidity(me)) {
                    return;
                }

                var $btn = $(event.target);
                $btn.loadBtn();

                // maps to UpdateEventTicketViewModel.cs
                var data = _.extend(options, {
                    eventTicket: ko.toJS(me)
                });

                if (me.editMode()) {

                    adDesignService.editTicket(data)
                        .then(handleResponse)
                        .then(notify)
                        .then(function (pr) {
                            pr.then(function () {
                                me.displayNotificationProgress(false);
                                $btn.resetBtn();
                            });
                        });
                }
                else {

                    adDesignService.addEventTicket(data.eventTicket).then(function (newTicket) {
                        if (me.onSave) {
                            me.onSave(newTicket);
                        }

                        // Clear the current data
                        me.ticketName(null);
                        me.price(null);
                        me.eventTicketFields.removeAll();
                        me.availableQuantity(null);
                        me.isActive(true);
                        me.remainingQuantity(null);
                    });
                }

            }

            function handleResponse(resp) {

                return new Promise(function (resolve, reject) {

                    if (resp.errors) {

                        if (_.some(resp.errors, ['key', 'GuestCountIncreased'])) {
                            me.displayGuestPurchasesWarning(true);
                            reject(resp);
                        }

                        reject(resp);
                    }

                    if (resendGuestNotifications === false) {
                        toastr.success("Ticket details saved successfully");
                    }

                    resolve(resp);

                });
            }

            function notify() {
                return new Promise(function (resolve, reject) {
                    if (resendGuestNotifications === false) {
                        resolve();
                        me.displayGuestPurchasesWarning(false);
                        return;
                    }

                    eventService.getGuestsForTicket(me.eventId(), me.eventTicketId()).then(function (guests) {

                        if (guests.errors) {
                            reject(guests.errors);
                        }

                        me.displayNotificationProgress(true);
                        me.guestsAffected(guests.length);
                        me.guestsNotified(1);

                        var emailFuncs = _.map(guests, function (g) {
                            return function () {
                                return new Promise(function (resendResolve) {
                                    eventService.resendGuestEmail(g.ticketNumber)
                                        .then(function (res) {
                                            resendResolve(res);
                                        });
                                });
                            }
                        });

                        $p.processPromises(emailFuncs, function () {
                            me.guestsNotified(me.guestsNotified() + 1);
                        }).then(function () {
                            resolve(guests);
                            me.displayGuestPurchasesWarning(false);
                            me.displayNotificationProgress(false);
                            toastr.success('Done! The guests should receive an email with updated ticket information.');
                        });
                    });
                });
            }
        },
        template: { path: $p.baseUrl + 'Scripts/app/events/ticketEditor/ticket-editor.html' }
    });
})(ko, $paramount, toastr);;
(function ($, ko, $p) {

    ko.components.register('ticket-purchase-warning', {

        viewModel: function (params) {

            this.save = params.save;
            this.saveWithoutNotifications = params.saveWithoutNotifications;
            this.blockOn = params.blockOn;

            
        },


        template: { path: $p.baseUrl + 'Scripts/app/events/ticketPurchaseWarning/ticket-purchase-warning.html' }
    });

})(jQuery, ko, $paramount);;
(function ($, ko, $p) {

    ko.components.register('find-tickets', {
        viewModel: Tickets,
        template: { path: $p.baseUrl + 'Scripts/app/events/ticketSelection/find-tickets.html' }
    });

    var eventService;

    function Tickets(params) {
        var me = this;

        eventService = new $p.EventService(params.baseUrl);
        me.eventGroupsPromise = eventService.getGroups(params.eventId);
        me.getTicketsPromise = eventService.getTicketsForEvent(params.eventId);

        me.availableTickets = ko.observableArray();
        me.groupsRequired = ko.observable();
        me.groups = ko.observableArray();
        me.groupSelectionEnabled = false;
        me.maxTicketsPerBooking = params.maxTicketsPerBooking;
        me.selectedGroupId = null;
        me.selectedTickets = ko.observableArray();
        me.displayNoSelectedTickets = ko.observable(false);
        me.currentPage = ko.observable(1);
        me.pageSize = 3;

        // Opening and closing dates
        me.eventEndDate = ko.observable();
        me.openingDate = ko.observable();
        me.closingDate = ko.observable();
        me.hasClosed = ko.computed(function () {
            if (!me.closingDate()) {
                return false;
            }
            return me.closingDate().isBefore(moment());
        });

        me.hasNotOpened = ko.computed(function () {
            if (!me.openingDate()) {
                return false;
            }
            return me.openingDate().isAfter(moment());
        });

        me.isPastEvent = ko.computed(function () {
            if (!me.eventEndDate()) {
                return false;
            }
            return me.eventEndDate().isBefore(moment());
        });

        me.isAvailable = ko.computed(function () {
            return !me.hasClosed() && !me.hasNotOpened() && !me.isPastEvent();
        });


        // This maps to the EventTicketReservedViewModel
        me.reservationData = {
            eventId: params.eventId,
            eventInvitationId: params.eventInvitationId,
            tickets: []
        };

        me.startOrder = function (model, event) {
            if (me.selectedTickets().length > 0) {
                me.reservationData.tickets = ko.toJS(me.selectedTickets());
                var $btn = $(event.target).loadBtn();
                eventService.startTicketOrder(me.reservationData).fail(function () {
                    $btn.resetBtn();
                }).then(function (resp) {
                    if (resp.errors) {
                        $btn.resetBtn();
                    }
                });
            } else {
                me.displayNoSelectedTickets(true);
            }
        }

        me.saveAndOrder = function (element, event) {
            saveSelectedTickets();
            me.startOrder(element, event);
        };

        me.allowToOrderTickets = ko.computed(function () {
            if (me.groupSelectionEnabled === true) {
                return true;
            }
            return me.selectedTickets().length > 0;
        });

        me.groupsPaged = ko.computed(function () {
            var chunked = _.chunk(me.groups(), me.pageSize);
            return chunked[me.currentPage() - 1];
        });

        me.ticketsPaged = ko.computed(function () {
            var chunkd = _.chunk(me.availableTickets(), me.pageSize);
            return chunkd[me.currentPage() - 1];
        });

        /*
         * Used for the findTickets.model.js page
         */
        me.onGroupSelect = function (model, event) {
            var $btn = $(event.target).loadBtn();

            me.selectedGroupId = model.eventGroupId();
            me.availableTickets.removeAll();

            eventService.getTicketsForGroup(me.reservationData.eventId, model.eventGroupId())
                .then(function (resp) {
                    _.each(resp, function (t) {
                        if (!t.isActive) {
                            return;
                        }
                        var maxTicketsAllowed = getMaxTicketsAllowed(me.selectedGroupId, t.eventTicketId, model.maxGuests(), t.remainingQuantity);
                        var eventTicket = new $p.models.EventTicket(t, maxTicketsAllowed);
                        eventTicket.eventGroupId(model.eventGroupId());
                        me.availableTickets.push(eventTicket);
                    });
                    $('#ticketSelectionModal').modal('show');
                })
                .always(function () {
                    $btn.resetBtn();
                });
        }

        me.removeSelectedTicket = function () {
            me.selectedTickets.remove(this);
        }

        me.onGroupTicketSave = function () {
            saveSelectedTickets();
            $('#ticketSelectionModal').modal('hide');
        }

        me.onGroupTicketSaveAndOrder = function (model, event) {
            saveSelectedTickets();
            me.startOrder(model, event);
        }

        me.totalGroups = ko.computed(function () {
            return me.groups().length;
        });

        me.changePage = function (pageNum) {
            me.currentPage(pageNum);
        }

        function saveSelectedTickets() {
            _.each(me.availableTickets(), function (t) {
                if (t.selectedQuantity() > 0) {

                    var existingTicket = _.find(me.selectedTickets(), function (existing) {
                        return existing.eventTicketId() === t.eventTicketId() && existing.eventGroupId() === t.eventGroupId();
                    });

                    if (existingTicket) {
                        var currentQty = existingTicket.selectedQuantity();
                        existingTicket.selectedQuantity(currentQty + t.selectedQuantity());
                        return;
                    }

                    if (t.eventGroupId() && me.eventGroupsPromise !== null) {
                        me.eventGroupsPromise.then(function (groups) {
                            var group = _.find(groups, { eventGroupId: t.eventGroupId() });
                            t.eventGroupName(group.groupName);
                            me.selectedTickets.push(t);

                            return groups;
                        });
                    } else {
                        me.selectedTickets.push(t);
                    }
                }
            });
        }

        function getMaxTicketsAllowed(eventGroupId, eventTicketId, groupMaxGuests, ticketRemainingQuantity) {
            var currentSelectedCount = _.sumBy(me.selectedTickets(), function (t) {
                if (t.eventGroupId() === eventGroupId && t.eventTicketId() === eventTicketId) {
                    return t.selectedQuantity();
                }
                return 0;
            });

            var maxTicketsAllowed = me.maxTicketsPerBooking; // Align by the maximum first
            if (!_.isNull(groupMaxGuests) && groupMaxGuests < maxTicketsAllowed) {
                maxTicketsAllowed = groupMaxGuests;
            }

            if (!_.isNull(ticketRemainingQuantity) && ticketRemainingQuantity < maxTicketsAllowed) {
                maxTicketsAllowed = ticketRemainingQuantity;
            }

            maxTicketsAllowed = maxTicketsAllowed - currentSelectedCount;

            return maxTicketsAllowed;
        }

        /*
         * Databind data from the server
         */
        this.load(params, function () {
            // Todo - toggle loader
        });
    }

    Tickets.prototype.load = function (params, done) {
        var me = this;

        eventService.getEvent(params.eventId).then(function (eventData) {
            me.groupsRequired(eventData.groupsRequired);
            me.openingDate(moment.utc(eventData.openingDateUtc).local());
            me.closingDate(moment.utc(eventData.closingDateUtc).local());

            // EndDateUtc was added a little later so we cannot rely on it. So fallback to eventEndDate (AEST time)
            if (eventData.eventEndDateUtc) {
                me.eventEndDate(moment.utc(eventData.eventEndDateUtc).local());
            } else {
                me.eventEndDate(moment(eventData.eventEndDate));  // This is for old events (pre-3.20 release)
            }

            if (eventData.groupsRequired === true) {

                me.eventGroupsPromise.then(function (groupData) {
                    _.each(groupData, function (gr) {
                        me.groups.push(new $p.models.EventGroup(gr));
                    });
                    me.groupSelectionEnabled = eventData.groupsRequired && groupData.length > 0;
                    done();

                    $(window).off('.affix');
                    $('.ticket-booth').removeClass("affix affix-top").removeData('bs.affix');

                    return groupData;
                });
            } else {
                me.getTicketsPromise.then(function (ticketData) {
                    _.each(ticketData, function (t) {
                        if (!t.isActive) {
                            return;
                        }
                        me.availableTickets.push(new $p.models.EventTicket(t, me.maxTicketsPerBooking));
                    });
                    done();
                    return ticketData;
                });
            }
        });
    }




})(jQuery, ko, $paramount);;
(function (ko) {
    ko.components.register('ticket-options', {
        viewModel : function(params) {
            this.tickets = params.ticketsObservable;
        },
        template: { path: $paramount.baseUrl + 'Scripts/app/events/ticketSelection/ticket-options.html' }
    });
})(ko);;
(function (ko, $p) {

    var eventService = new $p.EventService(),
        adDesignService = new $p.AdDesignService();

    ko.components.register('view-guests', {
        template: {
            path: $paramount.baseUrl + 'Scripts/app/events/viewGuests/viewGuests.html'
        },
        viewModel: function (params) {
            var me = this;
            me.guests = ko.observableArray();
            me.admin = params.admin || false;

            function setGuests(guests) {
                _.each(guests, function (g) {
                    me.guests.push({

                        guestFullName: g.guestFullName,
                        groupName: g.groupName,
                        email: g.guestEmail,
                        admin: me.admin,
                        ticketNumberDisplay: '#' + g.ticketNumber,
                        ticketNumber: g.ticketNumber,
                        isPublic: g.isPublic,

                        editGuest: function (model) {
                            if (!me.admin) {
                                return;
                            }
                            var url = adDesignService.editGuestUrl(model.ticketNumber);
                            window.location = url;
                        }
                    });
                });
            }

            me.guestListFilter = ko.observable();
            me.guestsFiltered = ko.computed(function () {
                var guestsToReturn;

                var filter = me.guestListFilter();
                if (!filter) {
                    guestsToReturn = me.guests(); // Just display all guests
                } else {
                    guestsToReturn = ko.utils.arrayFilter(me.guests(), function (g) {
                        return g.guestFullName.toLowerCase().indexOf(filter.toLowerCase()) > -1;
                    });
                }

                guestsToReturn = _.orderBy(guestsToReturn, ['groupName']);

                if (!me.admin) {
                    // Filter the guests where the isPublic is false
                    guestsToReturn = _.filter(guestsToReturn, { 'isPublic': true });
                }

                return guestsToReturn;
            });

            eventService.getGuests(params.eventId).then(setGuests);
        }
    });
})(ko, $paramount);;
(function (ko, $p) {

    var eventService = new $p.EventService();

    ko.components.register('view-public-guests', {
        template: {
            path: $paramount.baseUrl + 'Scripts/app/events/viewGuests/viewPublicGuests.html'
        },
        viewModel: function (params) {
            var me = this;
            me.guests = ko.observableArray();

            function setGuests(guests) {
                _.each(guests, function (g) {
                    me.guests.push({
                        guestName: g.guestName,
                        groupName: g.groupName
                    });
                });
            }

            me.guestListFilter = ko.observable();
            me.guestsFiltered = ko.computed(function () {
                var guestsToReturn;

                var filter = me.guestListFilter();
                if (!filter) {
                    guestsToReturn = me.guests(); // Just display all guests
                } else {
                    guestsToReturn = ko.utils.arrayFilter(me.guests(), function (g) {
                        return g.guestName.toLowerCase().indexOf(filter.toLowerCase()) > -1;
                    });
                }

                guestsToReturn = _.orderBy(guestsToReturn, ['groupName']);

                return guestsToReturn;
            });

            eventService.getGuestNames(params.eventId).then(setGuests);
        }
    });
})(ko, $paramount);;
(function (ko, $p) {

    var imageService = new $p.ImageService();

    ko.components.register('image-viewer', {
        viewModel: function (params) {
            
            this.hasPhoto = ko.computed(function() {
                return $p.notNullOrUndefined(params.id());
            });

            this.imageUrl = ko.computed(function() {
                if ($p.notNullOrUndefined(params.id())) {
                    return imageService.getImageUrl(params.id(), { h: params.height, w: params.width});
                }
                return '';
            });

            this.remove = function () {
                if (params.onRemove) {
                    params.onRemove(params.id());
                }
            }
        },
        template: { path: $p.baseUrl + 'Scripts/app/imageViewer/imageViewer.html' }
    });


})(ko, $paramount);;
(function (ko, $p) {

    ko.components.register('ad-listing', {
        viewModel: AdListing,
        template: { path: $p.baseUrl + 'Scripts/app/listings/adListing.html' }
    });

    var imgService = new $p.ImageService($p.baseUrl);

    function AdListing(params) {

        var listing = params.listing;
        this.adId = listing.adId;
        this.title = listing.title;
        this.shortTitle = listing.shortTitle;
        this.adUrl = listing.adUrl;
        this.editAdUrl = listing.editAdUrl;
        this.category = listing.categoryName;
        this.parentCategory = listing.parentCategoryName;
        this.startDate = $p.dateToDisplay(listing.startDate);
        this.startDateHumanized = listing.startDateHumanized;
        this.locationName = listing.locationName;
        this.locationAreaName = listing.locationAreaName;
        this.categoryFontIcon = "fa fa-5x fa fa-" + listing.categoryFontIcon;
        this.photo = getPrimaryPhoto(listing, params);
        this.userEnabled = params.user === true;
    }

    function getPrimaryPhoto(listing, params) {

        if (!listing.primaryImage)
            return null;

        return imgService.getImageUrl(listing.primaryImage, {
            w: params.imgHeight || 500,
            h: params.imgWidth || 300
        });

    }

    $p.models.AdListing = AdListing;

})(ko, $paramount);;
 (function (ko, $p) {

    $p.ListingService = function (baseUrl) {
        var me = this;
        me.baseUrl = baseUrl;


        me.search = function (query) {
            var url = this.baseUrl + 'api/listings/search';
            
            if (!query) {
                return $paramount.httpGet(url);
            }

            var queryEncoded = $paramount.encodeQuery(query);
            url += '?' + queryEncoded;

            return $paramount.httpGet(url);
        }
    }


    var listingService = new $p.ListingService($p.baseUrl);

    $p.models.Ads = function (params) {
        var me = this;
        me.user = params.user;  
        me.ads = ko.observableArray();
        me.loading = ko.observable(true);

        var query = new $p.QueryManager()
            .withPageSize(params.pageSize)
            .withUser(params.user)
            .build();

        listingService.search(query).then(function (response) {
            if (response.errors) {
                return;
            }
            
            if (!Array.isArray(response)) {
                throw new Error("The response does not contain an array of events.");
            }

            _.each(response, function (item) {
                me.ads.push(item);
            });

            me.loading(false);
        });
    };

    ko.components.register('ad-list', {
        viewModel: $p.models.Ads,
        template: { path: $p.baseUrl + 'Scripts/app/listings/ads.html' }
    });
    

})(ko, $paramount);;
(function(n){var i=parseInt(n("#hdnMaxPageRequests").val()),r=parseInt(n("#hdnResultsPerPage").val()),t=1;n(function(){n("#btnShowMore").on("click",function(){var u=n(this);u.button("loading");n.post(u.data().url,{page:t}).done(function(t){var i=n(t).find(".list-group-item");i.length>0&&n(".list-group").append(n(t).find(".list-group-item"));(i.length==0||i.length<r)&&u.hide()}).always(function(){t++;t===i&&u.hide();u.button("reset")})})})})(jQuery);
/*
//# sourceMappingURL=Find.min.js.map
*/;
(function(n){var i=parseInt(n("#hdnMaxPageRequests").val()),r=parseInt(n("#hdnResultsPerPage").val()),t=1;n(function(){n("#btnShowMore").on("click",function(){var u=n(this);u.button("loading");n.post(u.data().url,{page:t}).done(function(t){var i=n(t).find(".list-group-item");i.length>0&&n(".list-group").append(n(t).find(".list-group-item"));(i.length==0||i.length<r)&&u.hide()}).always(function(){t++;t===i&&u.hide();u.button("reset")})})})})(jQuery);
/*
//# sourceMappingURL=Find.min.js.map
*/;
(function ($p) {

    $p.QueryManager = function () {
        var me = this;
        me.query = {};

        return {
            withPageSize: function (pageSize) {
                if (pageSize) {
                    me.query.pageSize = pageSize;
                }
                return this;
            },
            withUser: function (user) {
                if (user) {
                    me.query.user = user;
                }
                return this;
            },
            build: function () {
                return me.query;
            }
        }
    }

})($paramount);;
(function ($, $paramount) {

    function LocationService(baseUrl) {
        this.baseUrl = baseUrl || $paramount.baseUrl;
    }

    LocationService.prototype.getLocationAreas = function (locationId) {
        return $.get(this.baseUrl + 'Location/GetLocationAreas?locationId=' + locationId);
    }
    
    $paramount.LocationService = LocationService;
    return $paramount;

})(jQuery, $paramount);;
(function () {
    
    function Pagination(param) {

        var me = this;
        me.currentPage = ko.observable(1);
        me.pages = ko.observableArray();
        me.totalPageCount = ko.observable();
        me.start = ko.observable(0);
        me.end = ko.observable(param.maxPagesToDisplay);

        param.dataPromise.then(function (items) {
            me.totalPageCount(Math.ceil(items.length / param.pageSize));
            if (me.totalPageCount() < param.maxPagesToDisplay) {
                me.end(me.totalPageCount());
            }

            for (var i = 1; i <= me.totalPageCount() ; i++) {
                me.pages.push(new Page({
                    number: i,
                    selectPage: function (pageNum) {
                        me.currentPage(pageNum);
                        param.changePage(pageNum);
                    }
                }));
            }
        });

        me.next = function () {
            if (me.end() === me.totalPageCount()) {
                return;
            }
            me.start(me.start() + 1);
            me.end(me.end() + 1);
        }

        me.prev = function () {
            if (me.start() === 0) {
                return;
            }
            me.start(me.start() - 1);
            me.end(me.end() - 1);
        }

        me.hidePrev = ko.computed(function () {
            return me.start() <= 0;
        });

        me.hideNext = ko.computed(function () {
            return me.end() === me.totalPageCount();
        });

        me.pagesFiltered = ko.computed(function () {
            // Slice method is 0-index based
            var pages = _.slice(me.pages(), me.start(), me.end());
            return pages;
        });
    }

    function Page(data) {
        this.number = ko.observable(data.number);
        this.selectPage = function (model) {
            if (data.selectPage) {
                data.selectPage(model.number());
            }
        }
    }

    ko.components.register('pager', {
        viewModel: Pagination,
        template: {
            path: $paramount.baseUrl + 'Scripts/app/pagination/pagination.html'
        }
    });
})(ko);;
(function(ko, $p) {

    ko.components.register('progress-bar', {
        viewModel: function(params) {

            this.message = params.message;
            this.percentComplete = ko.computed(function() {
                
                // We expect that params contains observable values

                var perc = (params.processed() / params.howMany()) * 100;

                return perc + '%';

            });

        },
        template: { path: $p.baseUrl + 'Scripts/app/progress-bar/progress-bar.html' }
    });


})(ko, $paramount);;
(function (ko, $p) {
    
    ko.components.register('upload', {
        viewModel: function (params) {

            this.id = params.id;

        },
        template: { path: $p.baseUrl + 'Scripts/app/upload/upload.html' }
    });


})(ko, $paramount);;
(function (jQuery, ko, $paramount) {

	function UserNetwork(data) {
		var me = this;

		me.fullName = ko.observable();
		me.email = ko.observable();
		me.selected = ko.observable();
	    me.bindUserNetwork(data);

		/*
         * Validation
         */
		me.validator = ko.validatedObservable({
			fullName: me.fullName.extend({ required: true }),
			email: me.email.extend({ required: true, email: true })
		});
	}

	UserNetwork.prototype.bindUserNetwork = function (data) {
        if (_.isUndefined(data)) {
            return;
        }

        this.fullName(data.fullName);
        this.email(data.email);
	    this.selected(data.selected);
	}

	$paramount.models = $paramount.models || {};
    $paramount.models.UserNetwork = UserNetwork;

})(jQuery, ko, $paramount);;
(function () {

    var baseUrl = $paramount.baseUrl + 'UserNetwork';

    function UserNetworkService() { }

    UserNetworkService.prototype.create = function (userNetwork) {
        return $paramount.httpPost(baseUrl + '/Create', userNetwork);
    };

    UserNetworkService.prototype.notifyFriends = function (notification) {
        return $paramount.httpPost(baseUrl + '/NotifyAd', notification);
    };

    $paramount.UserNetworkService = UserNetworkService;
})();;
(function (jQuery, ko, $paramount) {
    function UserNetworkAdNotifier(data) {
        var userNetworkService = new $paramount.UserNetworkService();

        var me = this;
        me.adId = ko.observable(data.adId);
        me.notified = ko.observable(false);
        me.users = ko.observableArray();
        _.each(data.users, function (u) {
            me.users.push(new $paramount.models.UserNetwork(u));
        });

        me.newFriendName = ko.observable();
        me.newFriendEmail = ko.observable();

        /*
         * Validation
         */
        me.validator = ko.validatedObservable({
            newFriendName: me.newFriendName.extend({ required: true }),
            newFriendEmail: me.newFriendEmail.extend({ required: true, email: true })
        });

        /*
         * Submit  
         */
        me.notifyFriends = function (ev, element) {
            var $btn = $(element.toElement);
            var usersJs = ko.toJS(me.users());
            var selectedUsers = _.filter(usersJs, 'selected', true);

            userNetworkService.notifyFriends({
                adId: me.adId(),
                userNetworkUsers: selectedUsers
            }).always(function() {
                $btn.button('reset');
            }).done(function() {
                me.notified(true);
            });
        }

        /*
         * add friend
         */
        me.addFriend = function () {
            if ($paramount.checkValidity(me)) {
                var newUserNetwork = new $paramount.models.UserNetwork({
                    fullName: me.newFriendName(),
                    email: me.newFriendEmail(),
                    selected: true
                });

                var promise = userNetworkService.create(ko.toJS(newUserNetwork));
                promise.then(function () {
                    me.users.push(newUserNetwork);
                    me.clearValues();
                });

                return promise;
            }
            return null;
        }

        me.clearValues = function () {
            me.newFriendName(null);
            me.newFriendName.clearError();

            me.newFriendEmail(null);
            me.newFriendEmail.clearError();
        }

        me.anyUserSelected = ko.computed(function () {
            var anySelected = _.some(me.users(), function (u) {
                return u.selected() === true;
            });
            return anySelected;
        });
    }

    $paramount.models = $paramount.models || {};
    $paramount.models.UserNetworkAdNotifier = UserNetworkAdNotifier;

})(jQuery, ko, $paramount);;
(function (jQuery, ko, $paramount) {

    $paramount.ui.notifyNetworkAdUi = {
        init: function (data) {
            $(function () {
                var $userNetworkUi = $('#userNetwork');
                if ($userNetworkUi.length === 0) {
                    throw "userNetwork element is missing for ko applyBindings";
                }

                var viewModel = new $paramount.models.UserNetworkAdNotifier(data);
                ko.applyBindings(viewModel, $userNetworkUi[0]);
            });
        }
    }

})(jQuery, ko, $paramount);;
(function ($p) {

    var routePrefix = $p.baseUrl + '/venues';

    $p.venueService = {
        getByVenueId: function (venueId) {
            return $p.httpGet(routePrefix + '/' + venueId);
        }
    };

})($paramount);
