/* Minification failed. Returning unminified contents.
(2,12): run-time error CSS1035: Expected colon, found 'name'
(3,12): run-time error CSS1035: Expected colon, found 'siteRoot'
(4,12): run-time error CSS1035: Expected colon, found 'fontAwesomeSprites'
(5,12): run-time error CSS1035: Expected colon, found 'defaultIconsFamily'
(6,12): run-time error CSS1035: Expected colon, found 'maxFileSizeDefault'
(8,12): run-time error CSS1035: Expected colon, found 'getIconsPath('
(17,1): run-time error CSS1019: Unexpected token, found '('
(17,2): run-time error CSS1019: Unexpected token, found 'function('
(17,11): run-time error CSS1019: Unexpected token, found ')'
(17,12): run-time error CSS1019: Unexpected token, found '{'
(19,30): run-time error CSS1031: Expected selector, found '='
(19,30): run-time error CSS1025: Expected comma or open brace, found '='
(25,27): run-time error CSS1031: Expected selector, found '='
(25,27): run-time error CSS1025: Expected comma or open brace, found '='
(33,30): run-time error CSS1031: Expected selector, found '='
(33,30): run-time error CSS1025: Expected comma or open brace, found '='
(40,27): run-time error CSS1031: Expected selector, found '='
(40,27): run-time error CSS1025: Expected comma or open brace, found '='
(43,1): run-time error CSS1019: Unexpected token, found '}'
(43,2): run-time error CSS1019: Unexpected token, found '('
(43,3): run-time error CSS1019: Unexpected token, found ')'
(43,4): run-time error CSS1019: Unexpected token, found ')'
(43,5): run-time error CSS1019: Unexpected token, found ';'
(45,1): run-time error CSS1019: Unexpected token, found '/'
(45,2): run-time error CSS1019: Unexpected token, found '/'
(46,1): run-time error CSS1031: Expected selector, found '$'
(46,1): run-time error CSS1025: Expected comma or open brace, found '$'
(48,2): run-time error CSS1019: Unexpected token, found ','
(48,4): run-time error CSS1019: Unexpected token, found ''Maximum file size is {0} MB''
(48,33): run-time error CSS1019: Unexpected token, found ')'
(48,34): run-time error CSS1019: Unexpected token, found ';'
(51,1): run-time error CSS1019: Unexpected token, found '/'
(51,2): run-time error CSS1019: Unexpected token, found '/'
(52,1): run-time error CSS1031: Expected selector, found '$'
(52,1): run-time error CSS1025: Expected comma or open brace, found '$'
(57,2): run-time error CSS1019: Unexpected token, found ')'
(57,3): run-time error CSS1019: Unexpected token, found ';'
(59,12): run-time error CSS1035: Expected colon, found 'undefined'
(60,13): run-time error CSS1035: Expected colon, found 'boolean'
(61,12): run-time error CSS1035: Expected colon, found 'number'
(62,12): run-time error CSS1035: Expected colon, found 'string'
(63,12): run-time error CSS1035: Expected colon, found 'object'
(64,12): run-time error CSS1035: Expected colon, found 'function'
(67,12): run-time error CSS1035: Expected colon, found 'click'
(68,12): run-time error CSS1035: Expected colon, found 'change'
(69,12): run-time error CSS1035: Expected colon, found 'blur'
(70,12): run-time error CSS1035: Expected colon, found 'focus'
(71,12): run-time error CSS1035: Expected colon, found 'keydown'
(72,12): run-time error CSS1035: Expected colon, found 'keypress'
(73,12): run-time error CSS1035: Expected colon, found 'keyup'
(74,12): run-time error CSS1035: Expected colon, found 'mousedown'
(75,12): run-time error CSS1035: Expected colon, found 'mouseenter'
(76,12): run-time error CSS1035: Expected colon, found 'mouseleave'
(77,12): run-time error CSS1035: Expected colon, found 'mousemove'
(78,12): run-time error CSS1035: Expected colon, found 'mouseout'
(79,12): run-time error CSS1035: Expected colon, found 'mouseover'
(80,12): run-time error CSS1035: Expected colon, found 'mouseup'
(83,12): run-time error CSS1035: Expected colon, found 'div'
(84,12): run-time error CSS1035: Expected colon, found 'button'
(85,12): run-time error CSS1035: Expected colon, found 'ul'
(86,12): run-time error CSS1035: Expected colon, found 'li'
(87,12): run-time error CSS1035: Expected colon, found 'a'
(88,12): run-time error CSS1035: Expected colon, found 'template'
(89,12): run-time error CSS1035: Expected colon, found 'i'
(90,12): run-time error CSS1035: Expected colon, found 'span'
(91,12): run-time error CSS1035: Expected colon, found 'h1'
(92,12): run-time error CSS1035: Expected colon, found 'h2'
(93,12): run-time error CSS1035: Expected colon, found 'h3'
(94,12): run-time error CSS1035: Expected colon, found 'h4'
(95,12): run-time error CSS1035: Expected colon, found 'h5'
(96,12): run-time error CSS1035: Expected colon, found 'h6'
(99,12): run-time error CSS1035: Expected colon, found 'thin'
(100,12): run-time error CSS1035: Expected colon, found 'light'
(101,12): run-time error CSS1035: Expected colon, found 'regular'
(102,12): run-time error CSS1035: Expected colon, found 'solid'
(103,12): run-time error CSS1035: Expected colon, found 'duotone'
(104,12): run-time error CSS1035: Expected colon, found 'brands'
(107,12): run-time error CSS1035: Expected colon, found 'micrositesRestrictedContent'
(117,12): run-time error CSS1035: Expected colon, found 'isVisible('
(256,12): run-time error CSS1035: Expected colon, found 'randomId('
(267,12): run-time error CSS1035: Expected colon, found '#overlayCss'
(268,12): run-time error CSS1035: Expected colon, found '#noScrollCss'
(269,12): run-time error CSS1035: Expected colon, found '#buttonClasses'
(275,12): run-time error CSS1035: Expected colon, found 'showLoading('
(525,12): run-time error CSS1035: Expected colon, found 'async'
(554,12): run-time error CSS1035: Expected colon, found '#formRowCss'
(555,12): run-time error CSS1035: Expected colon, found '#validIcon'
(556,12): run-time error CSS1035: Expected colon, found '#invalidIcon'
(557,12): run-time error CSS1035: Expected colon, found '#invalidFieldCss'
(558,12): run-time error CSS1035: Expected colon, found '#validatedFieldCss'
(559,12): run-time error CSS1035: Expected colon, found '#errorCss'
(560,12): run-time error CSS1035: Expected colon, found '#validCss'
(562,12): run-time error CSS1035: Expected colon, found '#baseConfiguration'
(595,12): run-time error CSS1035: Expected colon, found '#baseInputImageConfiguration'
(608,5): run-time error CSS1062: Expected semicolon or closing curly-brace, found '/'
(729,12): run-time error CSS1035: Expected colon, found 'disableForm('
(857,12): run-time error CSS1035: Expected colon, found 'setCookie('
(884,5): run-time error CSS1062: Expected semicolon or closing curly-brace, found '#articleId'
(885,5): run-time error CSS1062: Expected semicolon or closing curly-brace, found '#companyIdId'
(886,5): run-time error CSS1062: Expected semicolon or closing curly-brace, found '#isRestrictedId'
(887,5): run-time error CSS1062: Expected semicolon or closing curly-brace, found '#hasHubSpotFormId'
(888,5): run-time error CSS1062: Expected semicolon or closing curly-brace, found '#modalId'
(889,5): run-time error CSS1062: Expected semicolon or closing curly-brace, found '#formId'
(890,5): run-time error CSS1062: Expected semicolon or closing curly-brace, found '#isCampaignId'
(892,5): run-time error CSS1062: Expected semicolon or closing curly-brace, found '#articleIdElement'
(893,5): run-time error CSS1062: Expected semicolon or closing curly-brace, found '#companyIdElement'
(894,5): run-time error CSS1062: Expected semicolon or closing curly-brace, found '#isRestrictedElement'
(895,5): run-time error CSS1062: Expected semicolon or closing curly-brace, found '#hasHubSpotFormElement'
(896,5): run-time error CSS1062: Expected semicolon or closing curly-brace, found '#isCampaignElement'
(898,5): run-time error CSS1062: Expected semicolon or closing curly-brace, found '#'
(900,5): run-time error CSS1062: Expected semicolon or closing curly-brace, found '#cookieName'
(902,5): run-time error CSS1062: Expected semicolon or closing curly-brace, found 'constructor('
: error : Index was outside the bounds of the array.
 */
class EnvironmentConfiguration{
    static name = '';
    static siteRoot ='';
    static fontAwesomeSprites = '/content/font-awesome/sprites/';
    static defaultIconsFamily = '';
    static maxFileSizeDefault = 5;
    
    static getIconsPath(family = '') {
        
        const currentFamily = family === ''
            ? EnvironmentConfiguration.defaultIconsFamily
            : family;
        
        return `${EnvironmentConfiguration.fontAwesomeSprites}${currentFamily}.svg`;
    }
}
(function(){
    /**Adds a '.' at the beginning of the string to turn it into an id selector */
    String.prototype.toClass = function () {
        if (this === '') return this;
        return '.' + this;
    }

    /**Adds a '#' at the beginning of the string to turn it into a class selector */
    String.prototype.toId = function() {
        if (this === '') return this;
        return '#' + this;
    }

    /**
     * Check if the string is for a css class (starts with .)
     */
    String.prototype.isClass = function() {
        return this.indexOf('.') === 0;
    }

    /**
     * Checks if the string is for a css class (starts with #)
     */
    String.prototype.isId = function () {
        return this.indexOf('#') === 0;
    }
}());

//Validation method to check file size
$.validator.addMethod('filesize', function (value, element, param) {
    return this.optional(element) || (element.files[0].size <= (param * 1024 * 1024))
}, 'Maximum file size is {0} MB');


//Validation method to check if at least one of the checkboxes in the list is checked and enabled
$.validator.addMethod('checkboxlistany', function (value, element, message) {
    return $(element)
        .parents('form__group')
        .siblings('input[type="checkbox"]:checked')
        .not(':disabled').length !== 0;
});
class DataTypes {
    static undefined = 'undefined';
    static  boolean = 'boolean';
    static number = 'number';
    static string = 'string';
    static object = 'object';
    static function = 'function';
}
class DomEvents {
    static click = 'click';
    static change = 'change';
    static blur = 'blur';
    static focus = 'focus';
    static keydown = 'keydown';
    static keypress = 'keypress';
    static keyup = 'keyup';
    static mousedown = 'mousedown';
    static mouseenter = 'mouseenter';
    static mouseleave = 'mouseleave';
    static mousemove = 'mousemove';
    static mouseout = 'mouseout';
    static mouseover = 'mouseover';
    static mouseup = 'mouseup';
}
class HTMLElements {
    static div = 'div';
    static button = 'button';
    static ul = 'ul';
    static li = 'li';
    static a = 'a';
    static template = 'template';
    static i = 'i';
    static span = 'span';
    static h1 = 'h1';
    static h2 = 'h2';
    static h3 = 'h3';
    static h4 = 'h4';
    static h5 = 'h5';
    static h6 = 'h6';
}
class FontawesomeFamilies{
    static thin = 'thin';
    static light = 'light';
    static regular = 'regular';
    static solid = 'solid';
    static duotone = 'duotone';
    static brands = 'brands';
}
class CookieNames {
    static micrositesRestrictedContent = 'microsites_restricted';
}
class DomUtils {
    
   

    /**
    * Checks if an element is visible
    * @param {any} id Id of the element to check the visibility for
    */
    static isVisible(id) {
        const _id = id.isId()
            ? id.replace('#', '')
            : id;

        const element = document.getElementById(_id);

        if (element !== null) {
            return window.getComputedStyle(element).display !== 'none';
        }
    }

    static isElementVisible(element) {
        if (element !== null) {
            return window.getComputedStyle(element).display !== 'none';
        }
    }

    /**
     * Makes an element/elements visible
     * @param {any} selector Selector to get the element/elements to make visibel
     * @param {any} showValue Value to set the display property to (anything but none)
     */
     static show(selector, showValue) {

        //class name
        if (selector.isClass()) {
            const elements = document.getElementsByClassName(selector.replace('.', ''));
            if (elements.length) {
                for (let i = 0; i < elements.length; i++) {
                    elements[i].style.display = showValue;
                }
            }
            return;
        }

        //id
        if (selector.isId()) {
            const element = document.getElementById(selector.replace('#', ''));

            if (element !== null) {
                element.style.display = showValue;
            }
        }
    }

    /**
     * Hides an element/elements
     * @param {any} selector Selector to locate the element/elements to hide
     */
     static hide(selector) {
        //class name
        if (selector.isClass()) {
            const elements = document.getElementsByClassName(selector.replace('.', ''));
            if (elements.length) {
                for (let i = 0; i < elements.length; i++) {
                    elements[i].style.display = 'none';
                }
            }
            return;
        }

        //id
        if (selector.isId()) {
            const element = document.getElementById(selector.replace('#', ''));
            if (element !== null) {
                element.style.display = 'none';
            }
        }
    }

    /**
     * Shows the element in the list by setting the display property 
     * @param {any} element Element to show
     * @param {any} showValue Value of the display property to show the element with
     */
     static showElement(element, showValue) {

        if (typeof element === DataTypes.undefined) {
            return;
        }

        element.style.display = showValue || 'block';
    }

    /**
     * Hides an element
     * @param {any} element Element to hide
     */
     static hideElement(element) {

        if (typeof element === DataTypes.undefined) {
            return;
        }

        element.style.display = 'none';
    }

    /**
     * Shows all the elements in the list by setting the display property 
     * @param {any} listOfElements
     * @param {any} showValue
     */
     static showElements(listOfElements, showValue) {
        const _showValue = showValue || 'block';
        if (!listOfElements.length) {
            return;
        }

        for (let i = 0; i < listOfElements.length; i++) {
            listOfElements[i].style.display = _showValue;
        }
    }

    static hideElements(listOfElements) {

        if (!listOfElements.length) {
            return;
        }

        for (let i = 0; i < listOfElements.length; i++) {
            listOfElements[i].style.display = 'none';
        }
    }

    static fadeIn(element, ms, callback) {
    }

    static fadeOut(element, ms, callback) {
    }

    static slideDown(element, ms, callback) {
    }

    static slideUp(element, ms, callback) {
    }
}

class Utils {
    static randomId() {
        function s4() {
            return Math.floor((1 + Math.random()) * 0x10000)
                .toString(16)
                .substring(1);
        }
        return s4() + s4() + s4() + s4() + s4() + s4();
    }
}
class UIUtils {

    static #overlayCss = 'overlay';
    static #noScrollCss = 'no-scroll';
    static #buttonClasses = ['button', 'btn'];

    /**
     * Attaches the loading layer to the target element specified in the config
     * @param  config {{target: HTMLElement, message:string, fixed:boolean, icon:string}}
     */
    static showLoading(config) {
        const defaultValues = {
            target: document.body,
            message: '',
            fixed: false,
            icon: 'compact-disc'
        };

        const configuration = Object.assign({}, defaultValues, config);

        const loadingTemplate = document.createElement(HTMLElements.template);
        loadingTemplate.innerHTML = UIUtils.#getLoadingHtml(configuration).trim();

        const overlayElement = loadingTemplate.content.firstElementChild;

        //Position fixed when attaching to the body
        if (configuration.fixed) {
            overlayElement.style.position = 'fixed';
            document.body.classList.add(UIUtils.#noScrollCss)
        }
        configuration.target.appendChild(overlayElement);
    }

    static #getLoadingHtml(configuration) {
        return `
            <div class="${UIUtils.#overlayCss}">
                <div class="loading__content-wrapper">
                    ${
                        configuration.message !== ''
                        ? '<div class="loading__message">${configuration.message}</div>'
                        : ''
                    }
                </div>
            </div>
        </div>`
    }

    /**
     * Removes the loading layer from the $target specified in the config object
     * @param {any} config
     */
    static hideLoading(config) {
        const defaultValues = {
            target: document.body,
            fixed: false
        };

        const configuration = Object.assign({}, defaultValues, config);

        //remove overlay
        configuration.target.querySelectorAll(UIUtils.#overlayCss.toClass())
            .forEach((element) => {
                element.remove();
            });

        if (configuration.fixed) {
            document.body.classList.remove(UIUtils.#noScrollCss);
        }
    }

    /***
     * Shows overlay layer
     * @param config {{target, noScroll, hideOnClick, callbackWhenClicked}}
     */
    static showOverlay(config) {
        const defaultValues = {
            target: document.body,
            noScroll: true,
            hideOnClick: true,
            callbackWhenClicked: null
        };

        const configuration = Object.assign({}, defaultValues, config);

        const overlayElement = document.createElement(HTMLElements.div);
        overlayElement.classList.add(UIUtils.#overlayCss);

        if (configuration.hideOnClick) {
            overlayElement.addEventListener(DomEvents.click, function () {
                if (configuration.callbackWhenClicked !== null &&
                    typeof configuration.callbackWhenClicked === DataTypes.function) {
                    configuration.callbackWhenClicked();
                }
                UIUtils.hideOverlay();
            });
        }

        if (configuration.noScroll) {
            document.body.classList.add(UIUtils.#noScrollCss)
        }
        configuration.target.appendChild(overlayElement);
    }

    static hideOverlay() {
        document.querySelectorAll(UIUtils.#overlayCss.toClass())
            .forEach(element => {
                element.remove();
            });

        //We could check before but remove will check anyways
        document.body.classList.remove(UIUtils.#overlayCss);
    }

    /***
     * 
     * @param buttonElement: HTMLButtonElement
     * @param options {{disableAll:boolean, iconFamily:string, icon:string}}
     */
    static showButtonLoading(buttonElement, options = {}) {

        const defaultOptions = {
            disableAll: false,
            iconFamily: FontawesomeFamilies.light,
            icon: 'circle-notch'
        };

        const configuration = Object.assign({}, defaultOptions, options);

        //Hide icons if any
        buttonElement.querySelectorAll('i')
            .forEach(icon => {icon.style.display = 'none'});

        buttonElement.classList.add('button--loading');

        const loadingSpinnerHtml = `
            <span class="button__loading-icon-wrap pop">
                 ${
                    UIUtils.getSvgIconHtml(configuration.icon,{
                        cssClass: 'button__loading-icon',
                        iconFamily: configuration.iconFamily
                    })
                }
            </span>
        `;

        buttonElement.style.width = `${buttonElement.offsetWidth}px`;
        buttonElement.dataset.hiddenContent = buttonElement.innerHTML;
        buttonElement.innerHTML = loadingSpinnerHtml;
        
        if (buttonElement.tagName === 'BUTTON') {
            buttonElement.disabled = true;
        } else {
            buttonElement.classList.add('button--disabled');
        }

        // if (disableAll) {
        //     const buttons = $('.button').not($button);
        //     if ($buttons.length) {
        //         for (let i = 0; i < $buttons.length; i++) {
        //             const $currButton = $($buttons[i]);
        //
        //             if ($currButton.get(0).tagName === 'BUTTON') {
        //                 $currButton.prop('disabled', true);
        //                 continue;
        //             }
        //             $currButton.addClass('button--disabled');
        //         }
        //     }
        // }
    }

    static hideButtonLoading(buttonElement) {
        buttonElement.querySelectorAll('.button__loading-icon')
            .forEach(icon => {
                icon.remove();
            });

        buttonElement.classList.remove('button--loading');
        buttonElement.disabled = false;
        buttonElement.innerHTML = buttonElement.dataset.hiddenContent;

        document.querySelectorAll('.button--disabled, button[disabled]')
            .forEach(button => {
                button.classList.remove('button--disabled');
                button.disabled = false;
            });
    }

    static getSvgIconHtml(iconName, options){
        
        const defaultOptions = {
            cssClass: 'svg-icon',
            iconFamily: FontawesomeFamilies.light
        };
        
        const config = Object.assign({}, defaultOptions, options); 
        
        return `
            <svg class="${config.cssClass}">
                <use xlink:href="${EnvironmentConfiguration.fontAwesomeSprites}${config.iconFamily}.svg#${iconName}"></use>
            </svg>
        `;
    }

    /***
     * 
     * @param iconName 
     * @param options 
     * @param options.cssClass
     * @param options.iconFamily
     * @returns {Element}
     */
    static getSvgIconElement(iconName, options){
        const defaultOptions = {
            cssClass: 'svg-icon',
            iconFamily: FontawesomeFamilies.light
        };
        
        const config = Object.assign({}, defaultOptions, options);

        const iconContainer = document.createElement(HTMLElements.template);
        iconContainer.innerHTML = `
            <svg class="${config.cssClass}">
                <use xlink:href="${EnvironmentConfiguration.fontAwesomeSprites}${config.iconFamily}.svg#${iconName}"></use>
            </svg>
        `.trim();
       
        return iconContainer.content.firstElementChild;
    }

    static getLoadingIconHtml(options){
        return this.getLoadingIconElement(options).outerHTML;
    }
    
    static getLoadingIconElement(options){
        const defaults = {
            size: Sizes.medium, 
            fontFamily: FontawesomeFamilies.light,
            centerAbsolute: false
        };
        
        const values = Object.assign({}, defaults, options);
        const icon = UIUtils.getSvgIconElement('circle-notch',{
            cssClass: `icon--loading icon--${values.size}`,
            iconFamily: values.fontFamily
        });
        
        const spinningContainer = document.createElement(HTMLElements.div);
        spinningContainer.classList.add('icon--spinning');
        
        if(values.centerAbsolute){
            spinningContainer.classList.add('icon--spinning-centered');
        }
        
        spinningContainer.appendChild(icon);
        
        return spinningContainer;
    }
}
class HttpService{
    static async get(url, params = null){
        const _url = new URL(`${EnvironmentConfiguration.siteRoot}${url}`);
        
        if(params != null){
            _url.search = new URLSearchParams(params).toString();
        }
        
        const response = await fetch(_url.toString());
        return response.json();
    }

    /***
     * 
     * @param formElement : HTMLFormElement
     */
     static async postForm(formElement){
        const formData = new FormData(formElement);

        const response = await fetch(formElement.action, {
            method: 'POST',
            body: formData
        });
        
        const data  = await response.json();
        return data;
    }
}
class ValidationService {
    
    static #formRowCss = 'form__group';
    static #validIcon = 'check';
    static #invalidIcon = 'diamond-exclamation';
    static #invalidFieldCss = 'form__element--invalid';
    static #validatedFieldCss = 'form__element--valid';
    static #errorCss = 'icon--error';
    static #validCss = 'icon--valid';
    
    static #baseConfiguration = {
        ignore: '.ignore',
        highlight: function (element, errorClass) {
            ValidationService.#validationIcon(element, false);
        },
        unhighlight: function (element) {
            ValidationService.#validationIcon(element, true);
        },
        focusInvalid: false,
        onfocusout: function (element) {
            if (element.type === 'file' || element.type === 'checkbox') {
                return;
            }
            $(element).valid();
        },
        onkeyup: false,
        onclick: false,
        invalidHandler: function (event, validator) {
            //Scroll to first invalid element

            const form = document.getElementById(event.target.id);
            const firstInvalidLabelEl = form.querySelector('[name="' + Object.keys(validator.invalid)[0] + '"]');
            
            if(firstInvalidLabelEl != null ){
                const formGroup = firstInvalidLabelEl.closest('.form__group');
                
                if(formGroup != null){
                    formGroup.scrollIntoView({behavior: "smooth"});
                }
            }
        }
    };

    static #baseInputImageConfiguration = {
        rule: {
            filesize: EnvironmentConfiguration.maxFileSizeDefault,
            accept: 'image/bmp, image/gif, image/jpeg, image/png, image/tiff',
            extension: 'bmp|jpg|png|gif|tiff'
        },
        message:{
            required: 'Please select an image to upload',
            accept: 'Only bmp, jpg, png, gif and tiff documents allowed',
            extension: 'Only bmp, jpg, png, gif and tiff documents allowed'
        }
    };
    
    //PUBLIC FUNCTIONALITY
    /**
     * Attaches client validation to a form
     * @param {any} formId Id of the form to attach the validation to
     * @param {any} config Validation object with rules/messages/handlers/...
     * @returns {Object} Jquery validation object for the form/config
     */
    static addValidation(formId, config) {
        //Build the validation object by merging the base configuration with the configuration for the form
        const validationObject = $.extend(true, {}, ValidationService.#baseConfiguration, config);
        ValidationService.#addOnChangeValidation(formId, 'select, input[type="checkbox"],input[type="date"], input[type="radio"]');
        return $('#' + formId).validate(validationObject);
    }
    
    static addUpsertValidation(formId, config){
        const submitConfig = {
           submitHandler: function (form) {
                FormService.disableForm(form.id);
                UIUtils.showButtonLoading(form.querySelector('button[type="submit"]'));
                form.submit();
            }
        };
        const upsertConfiguration = $.extend(true, {}, ValidationService.#baseConfiguration,submitConfig, config);
        return ValidationService.addValidation(formId, upsertConfiguration);
    }
    
    /*static addValidationOnChange(elementId){
        const element = document.getElementById(elementId);
        if(element !== null){
            element.addEventListener(DomEvents.change,  function(){
               $(this).valid(); 
            });
        }
    }*/

    static addValidationOnChange(selector){
        const elements = document.querySelectorAll(selector);

        if(elements !== null && elements.length){
            elements.forEach(element => {
                element.addEventListener(DomEvents.change, function (e) {
                    $(e.target).valid();
                });
            });
        }
    }
    
    static get imageConfiguration(){
        return ValidationService.#baseInputImageConfiguration;
    }
    
    //PRIVATE FUNCTIONALITY
    /**
     * Validates the elements in the form matched by the selector when the onChange event is fired
     * @param {any} formId Id of the form
     * @param {any} selector Elements to validate on change
     */
    static #addOnChangeValidation(formId, selector) {
        $('#' + formId).find(selector).change(function () {
            const $element = $(this);
            $element.valid();
        });
    }

    /***
     *
     * @param element
     * @param isValid
     */
    static #validationIcon(element, isValid) {
        const formGroup = element.closest(ValidationService.#formRowCss.toClass())

        if (!isValid) {
            if (formGroup.querySelectorAll(`svg.${ValidationService.#errorCss}`).length > 0) {
                return;
            }

            ValidationService.#removeIcon(formGroup,ValidationService.#validCss);
            element.classList.remove(ValidationService.#validatedFieldCss);

            formGroup.appendChild(UIUtils.getSvgIconElement(ValidationService.#invalidIcon, {
                cssClass: ValidationService.#errorCss,
                iconFamily: FontawesomeFamilies.solid
            }));

            element.classList.add(ValidationService.#invalidFieldCss);
            return;
        }

        if (element.type !== 'hidden' && (element.type === 'checkbox' && !element.checked || $(element).val() === '')) {
            ValidationService.#removeIcon(formGroup,ValidationService.#validCss);
            ValidationService.#removeIcon(formGroup,ValidationService.#errorCss);
            element.classList.remove(ValidationService.#invalidFieldCss);
            element.classList.remove(ValidationService.#validatedFieldCss);
            return;
        }

        ValidationService.#removeIcon(formGroup,ValidationService.#errorCss);
        element.classList.remove(ValidationService.#invalidFieldCss);

        if (!formGroup.querySelectorAll(`svg.${ValidationService.#validCss}`).length &&
            !formGroup.classList.contains('ignore')) {

            formGroup.appendChild(UIUtils.getSvgIconElement(ValidationService.#validIcon , {
                cssClass: ValidationService.#validCss,
                iconFamily: FontawesomeFamilies.solid
            }));

            element.classList.add(ValidationService.#validatedFieldCss);
        }
    }

    static #removeIcon(formGroup, icon) {
        formGroup.querySelectorAll(`svg.${icon}`)
            .forEach(validIcon => {
                validIcon.remove();
            });
    }
}

class FormService {
    static disableForm(formId = '') {
        
        if(formId === ''){
            return;
        }
        
        const form = document.getElementById(formId);
        
        if(typeof  form === 'undefined'){
            return;
        }
        
        for(const element of form.elements){
            if(element.tagName.toUpperCase() !== 'BUTTON'){
                element.readOnly = true;
                continue;
            }
            element.disabled = true;
        }
    }

    static enableForm(formId = '') {

        if(formId === ''){
            return;
        }

        const form = document.getElementById(formId);

        if(typeof  form === 'undefined'){
            return;
        }

        for(const element of form.elements){
            if(element.tagName.toUpperCase() !== 'BUTTON'){
                element.readOnly = false;
                continue;
            }
            element.disabled = false;
        }
    }
    
    static addTextLimitCounters(formId, inputContainerCss = 'form__group' ){
        
        const form = document.getElementById(formId);
        
        if(form === null){
            return;
        }
        
        form.querySelectorAll('input[type="text"], textarea')
            .forEach(textElement => {
                if(textElement.hasAttribute('maxlength')){
                    FormService.addCounter(textElement, inputContainerCss)
                }
            });
    }
    
    
    static addCounter(textElement, inputContainerCss){
        const textElementContainer = textElement.closest(inputContainerCss.toClass());

        const counterValueEl = document.createElement(HTMLElements.span);
        counterValueEl.id = `${textElement.id}_Counter`;
        counterValueEl.classList.add('form__counter-value');
        counterValueEl.innerText = textElement.maxLength;
        counterValueEl.dataset.maxLength = textElement.maxLength;

        const counterEl = document.createElement(HTMLElements.span);
        counterEl.classList.add('form__counter');
        counterEl.appendChild(counterValueEl);
        counterEl.append (counterValueEl, ' characters remaining.');

        textElementContainer.appendChild(counterEl);

        textElement.addEventListener(DomEvents.keyup, function(e)  {
            counterValueEl.innerText = `${+counterValueEl.dataset.maxLength - this.value.length}`;
        });

        //Init just in case it is loaded with text
        counterValueEl.innerText = `${+counterValueEl.dataset.maxLength - textElement.value.length}`
    }
    
    static imageFileInput(fieldId) {
        const imageFileEl = document.getElementById(fieldId);
        
        if(imageFileEl === null){
            throw new Error("File input id not valid");
        }
        
        imageFileEl.addEventListener(DomEvents.change, function () {
            const hasImageCss = 'image-field__image--with-src'; 
            const wrapperEl = this.closest('.image-field__form-wrapper');
            const imageEl = wrapperEl.querySelector('.image-field__image');

            //New file selected
            if (this.files && this.files[0]) {
                const reader = new FileReader();

                reader.onload = (e) => {
                    if($(this).valid()){
                        //Show logo
                        imageEl.src = e.target.result;
                        if (!imageEl.classList.contains(hasImageCss)) {
                            imageEl.classList.add(hasImageCss);
                        }
                    }else {
                        if (imageEl.classList.contains(hasImageCss)) {
                            imageEl.classList.remove(hasImageCss);
                            imageEl.src = "#";
                        }
                    }
                }
                
                reader.readAsDataURL(this.files[0]);
                return;
            }

            //No file selected empty if needed
            if (imageEl.classList.contains(hasImageCss)) {
                imageEl.classList.remove(hasImageCss);
                imageEl.src = "#";
            }
        });
    }
}
class CookieService {
    
    static setCookie(cname, cvalue, exdays) {
        const date = new Date();
        date.setTime(date.getTime() + (exdays * 24 * 60 * 60 * 1000));
        const expires = "expires=" + date.toUTCString();
        document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
    }

    static getCookie(cname) {
        const name = cname + "=";
        const cookieParts = document.cookie.split(';');
        for (let i = 0; i < cookieParts.length; i++) {
            let c = cookieParts[i];
            while (c.charAt(0) === ' ') {
                c = c.substring(1);
            }
            if (c.indexOf(name) === 0) {
                return c.substring(name.length, c.length);
            }
        }
        return null;
    }

    static deleteCookie(cname) {
        document.cookie = cname + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;';
    }
}
class RestrictedArticle {
    #articleId = 'Id';
    #companyIdId = 'CompanyId';
    #isRestrictedId = 'IsRestricted';
    #hasHubSpotFormId = 'HasHubSpotForm';
    #modalId = 'restrictedContentModal';
    #formId = 'restrictedContentForm';
    #isCampaignId = 'is-campaign'; 
    
    #articleIdElement;
    #companyIdElement;
    #isRestrictedElement;
    #hasHubSpotFormElement;
    #isCampaignElement;
    
    #$modal;
    
    #cookieName;
    
    constructor() {
        this.#articleIdElement = document.getElementById(this.#articleId);
        this.#companyIdElement = document.getElementById(this.#companyIdId);
        this.#isRestrictedElement = document.getElementById(this.#isRestrictedId);
        this.#hasHubSpotFormElement = document.getElementById(this.#hasHubSpotFormId);
        this.#isCampaignElement = document.getElementById(this.#isCampaignId);
        
        if(this.#companyIdElement === null || this.#isRestrictedElement === null){
            console.log('Error initialising RestrictedContentService')
            return;
        }
        
        if(this.#isRestrictedElement.value.toLowerCase() === 'false'){
            return;
        }
        
        console.log(this.#isCampaignElement.value === 'false')
        
        this.#cookieName = `${CookieNames.micrositesRestrictedContent}_${this.#companyIdElement.value}`
        if(this.#isCampaignElement.value === 'false' && CookieService.getCookie(this.#cookieName) != null){
            return;
        }
        
        if(this.#hasHubSpotFormElement.value.toLowerCase() === 'true'){
            const hubSpotModalService = new HubspotFormModalService();
            hubSpotModalService.loadModalForm({
                id: this.#articleIdElement.value,
                title: 'Keep reading',
                allowClose: false,
                type: 'article'
            }).then(() => {});
        }
        else {
            this.#initForm();
            this.#$modal = $(`#${this.#modalId}`).modal({
                backdrop: 'static',
                keyboard: false,
                show: true
            });
        }
    }
    
    #initForm() {
        
        //Append companyId to form
        const formElement = document.getElementById(this.#formId);
        formElement.appendChild(this.#companyIdElement);
        
        const submitForm = (form) => {
            
            const submitButton = form.querySelector('button[type="submit"]');
            UIUtils.showButtonLoading(submitButton);
            
            HttpService.postForm(form)
                .then((data) => {
                    if(data.Succeeded){
                        CookieService.setCookie(this.#cookieName, this.#companyIdElement.value);
                        this.#$modal.modal('hide');
                    }
                });
        }
        
        ValidationService.addValidation(this.#formId, {
            rules:{
                'FirstName':{
                    required:true
                },
                'LastName':{
                    required:true
                },
                'Company':{
                    required:true
                },
                'EmailAddress':{
                    required:true,
                    email:true
                }
            },
            submitHandler(form) {
                submitForm(form);
            }
        });
    }
}
class HubspotFormModalService {

    #companyIdId = 'CompanyId';
    #modalId = 'hubspot-form-modal';
    #closeButtonId = 'modal-close-button';
    #$modal;
    #cookieName;
    #scriptElement = null;
    #companyIdElement;
    #loadingSpinnerHtml = `<div class="modal-spinner">
                                    <div class="fa fa-circle-o-notch fa-spin fa-3x fa-fw"></div>
                                </div>`;

    constructor() {
        this.#init();
    }

    async loadModalForm({
        id = null,
        title = '',
        allowClose = false,
        type = 'article'
    } = {}) {

        try {
            const response = await HttpService.get('/microsites/GetFormModalHtml', {
                id: id,
                defaultTitle: title,
                type: type
            });

            if (!response.ModalHtml) {
                return;
            }

            this.#openModal({
                modalHtml: response.ModalHtml,
                hubSpotFormGuid: response.HubSpotFormGuid,
                hubSpotFormPortalId: response.HubSpotFormPortalId,
                allowClose: allowClose,
            });
        }
        catch (error) {
            console.error(error);
        }
    }

    #init() {
        this.#companyIdElement = document.getElementById(this.#companyIdId);
        this.#cookieName = `${CookieNames.micrositesRestrictedContent}_${this.#companyIdElement.value}`;
    }

    #openModal({
        modalHtml = '',
        hubSpotFormGuid = '',
        hubSpotFormPortalId = '',
        allowClose = false
    } = {}) {

        document.body.insertAdjacentHTML('beforeend', modalHtml);
        const modalElement = document.getElementById(this.#modalId);

        if (!allowClose) {
            const closeButton = document.getElementById(this.#closeButtonId);
            closeButton.remove();
        }

        this.#$modal = $(modalElement).modal({
            backdrop: 'static',
            keyboard: false
        });

        this.#$modal.on('shown.bs.modal', () => {
            this.#appendScript(hubSpotFormGuid, hubSpotFormPortalId);
        });

        this.#$modal.on('hidden.bs.modal', () => {
            this.#scriptElement.remove();
            this.#$modal.remove();
        });
        
        this.#addLoadingSpinner();
        this.#$modal.modal('show');
    }

    #addLoadingSpinner() {
        this.#$modal.get(0).querySelector('#modal-body-main').innerHTML = this.#loadingSpinnerHtml;
    }

    #appendScript(hubspotFormGuid, hubspotFormPortalId) {

        this.#scriptElement = document.createElement('script');

        this.#scriptElement.id = hubspotFormGuid;
        this.#scriptElement.src = '//js.hsforms.net/forms/shell.js';
        this.#scriptElement.onload = () => {
            hbspt.forms.create({
                region: 'eu1',
                portalId: hubspotFormPortalId,
                formId: hubspotFormGuid,
                target: `#modal-body-main`,
                onFormReady: () => {
                    // this.#bindCloseModal(this.#$modal);
                },
                onFormSubmitted: () => {
                    CookieService.setCookie(this.#cookieName, this.#companyIdElement.value);
                    this.#$modal.modal('hide');
                    this.#enableRestrictedContent();
                }
            });
        };
        document.body.appendChild(this.#scriptElement);
    }

    #enableRestrictedContent() {
        const restrictedLinks = document.querySelectorAll('.ms-download--disabled a');
        restrictedLinks.forEach(link => {
            link.href = decodeURIComponent(escape(window.atob(link.dataset.link)));
            link.target = '_blank';
        });
    }
}
class RestrictedDownloadsService {
    
    #companyIdId = 'CompanyId';
    #modalId = 'restrictedContentModal';
    #formId = 'restrictedContentForm';
    #disabledDownloadClass = 'ms-download--disabled';
    
    #companyIdElement;
    #$modal;
    #$formValidator;
    
    #cookieName;
    
    #hubSpotFormModalService = new HubspotFormModalService();
    
    constructor() {
        this.#companyIdElement = document.getElementById(this.#companyIdId);
        
        if(this.#companyIdElement === null){
            throw new Error('Error initialising RestrictedDownloadsService');
        }
        
        this.#cookieName = `${CookieNames.micrositesRestrictedContent}_${this.#companyIdElement.value}`;
        if(CookieService.getCookie(this.#cookieName) != null){
            return;
        }
        
        if(!document.querySelectorAll(this.#disabledDownloadClass.toClass()).length){
            return;
        }
        
        this.#restrictDownloads();
        this.#initForm();
        this.#initModal();
    }

    #restrictDownloads() {
        const restrictedDownloadLinks = document.querySelectorAll(`${this.#disabledDownloadClass.toClass()} a`);
        restrictedDownloadLinks.forEach(restrictedLink => {
            
            restrictedLink.addEventListener(DomEvents.click, async (e) => {
                if(CookieService.getCookie(this.#cookieName) != null){
                    return;
                }
                
                e.preventDefault();
                if (restrictedLink.dataset.hubspotForm) {
                    await this.#hubSpotFormModalService.loadModalForm({
                        id: restrictedLink.dataset.articleId,
                        title: 'Downloads',
                        allowClose: true,
                        type: 'download'
                    });
                    return;
                } 
                this.#$modal.modal('show');
            });
        });
    }
    
    #initForm() {
        
        //Append companyId to form
        const formElement = document.getElementById(this.#formId);
        formElement.appendChild(this.#companyIdElement);
        
        const submitForm = (form) => {
            const submitButton = form.querySelector('button[type="submit"]');
            UIUtils.showButtonLoading(submitButton);
            form.submit();
        }
        
        this.#$formValidator = ValidationService.addValidation(this.#formId, {
            rules:{
                'FirstName':{
                    required:true
                },
                'LastName':{
                    required:true
                },
                'Company':{
                    required:true
                },
                'EmailAddress':{
                    required:true,
                    email:true
                }
            },
            submitHandler(form) {
                submitForm(form);
            }
        });
    }
    
    #initModal() {
        this.#$modal = $(`#${this.#modalId}`).modal({
            backdrop: 'static',
            keyboard: false,
            show: false
        });

        this.#$modal.on('hidden.bs.modal', (e) => {
            //Reset Form
            const invalidInputClass = 'form__element--invalid';
            const modalEl = this.#$modal.get(0);
            
            modalEl.querySelectorAll('input')
                .forEach(input => {
                    input.value = '';
                });
            
            modalEl.querySelectorAll(invalidInputClass.toClass())
                .forEach(invalidElement => {
                    invalidElement.classList.remove(invalidInputClass);
                });

            modalEl.querySelectorAll('svg')
                .forEach(icon => {
                    icon.remove();
                });

            this.#$formValidator.resetForm();
        });
    }
}
