var SKIP = true;
var uniqueId = 0;
function getUniqueId(){
    return ++uniqueId;
}

function IE(v) {
    if( typeof v != 'undefined'){
        return RegExp('msie' + (!isNaN(v)?('\\s'+v):''), 'i').test(navigator.userAgent);
    }else{
        return (
            navigator.userAgent.indexOf('MSIE')!==-1
            || navigator.appVersion.indexOf('Trident/') > -1
        ) ? true : false;
    }
}

function IElte(v){
	if( !IE() ) return false;
	var minIE = 7;
	for( i = minIE; i <= v; i ++ ){
		if( IE(v) ){
			return true;
		}
	}
	return false;
}

var displayLimitsFor = [
//    'all',
//    'mmenu',
//    'uid-ref-block-carousel-7',
//    'uid-ref-block-carousel-8',
//    'uid-vp-item-1',
//    'hp-header',
//    'work-process-step-idea',
//    'filter-box',
//    'work-process-step-plan',
//    'work-process-step-create',
//    'work-process-step-it-works'
//    'uid-vp-item-8',
//    'it-works',
//    'uid-ref-block-carousel-7'
    'xxx'
];


window.addEventListener('DOMContentLoaded', init);
//window.addEventListener('DOMContentLoaded', initBlog);
//window.addEventListener('DOMContentLoaded', initIntro);



var initiated = 0;
var sumInits;
function initIntro(){
//    console.log('initiated: ' + (initiated+1) );
	if(sumInits == undefined){
//        log(document.querySelectorAll('img[onload="initIntro()"]'));
        sumInits = document.querySelectorAll('img[onload="initIntro()"]').length + 1;
//        alert('sumInits: ' + sumInits);
    }
	if( ++initiated === ( sumInits ) && sumInits ){
        setTimeout(scroll, 1000);
	}else{
	}
}

var vw/* = document.getElementsByTagName('html')[0].clientWidth*/;
var vh/* = document.getElementsByTagName('html')[0].clientHeight*/;

var butterScroll;
var resizeObserver;
var viewportObjects;
var showCaseCLV;
var jsAddedStyles;
var isTouchDevice = 'ontouchstart' in document.documentElement;
isTouchDevice = false;

// mockup carousels
var MockupCarouselsReference = {};
var YTPlayersQueue = {};
var MockupCarouselsBlocks = {};

// selecting category
var blocksPage = 0;
var numBlocksPerPage = 6;
var selectingRefCategory = false;

function initBlog(){
    log('initBlog');
    var articles = document.querySelectorAll('#blog .article');
    if( !articles.length ) return;
    var pos = {
        left: 0,
        right: 0
    };
    articles.forEach(function(article){
        if( pos.left <= pos.right ){
            article.addClass('left');
            article.removeClass('right');
            article.style.top = pos.left + 'px';
            pos.left += article.offsetHeight;
        }else{
            article.addClass('right');
            article.removeClass('left');
            article.style.top = pos.right + 'px';
            pos.right += article.offsetHeight;
        }
    });
    articles.item(0).parentNode.style.height = Math.max(pos.left, pos.right) + 'px';
}

function init(){
    log('init');

    if( !IE() ) console.time('init');
    /*
    */
    
    if( IE(10) ) document.querySelector('body').addClass('ie10');
    if( IE() ) document.querySelector('body').addClass('ie');
    
    vw = document.getElementsByTagName('html')[0].clientWidth;
    vh = document.getElementsByTagName('html')[0].clientHeight;
    
    log('viewport: ' + vw + '×' + vh);
    
    window.addEventListener('scroll', scroll);
    window.addEventListener('resize', response);
    window.addEventListener('orientationchange', response);
    window.addEventListener('hashchange', hashChange);
    
    jsAddedStyles = document.getElementById('js-added');
    
    
    viewportObjects = new ViewportObjects ( vh, scrollChangePrecision );
    
    // scroll flip 3d sections
    /* var scrollFlip3dVPOOptions = {
        category: viewportObjects.CATEGORIES.SECTION_FLIP_3D,
        behavior: viewportObjects.BEHAVIORS.TOP_ABOVE_LIMIT_CSS,
        cssSwitch: 'flat',
        viewportLimit: .25,
        presise: true
    };
    viewportObjects.addItems('.scroll-flip-3d', scrollFlip3dVPOOptions, false); */
    
    // image stripe sections
    /* var imageStripeVPOOptions = {
        category: viewportObjects.CATEGORIES.SECTION_IMAGE_STRIPE,
        behavior: viewportObjects.BEHAVIORS.TOP_ABOVE_LIMIT_CSS,
        cssSwitch: 'above',
        viewportLimit: .25,
        presise: true
    };
    viewportObjects.addItems('section.image-stripe', imageStripeVPOOptions, false); */
    
    initCopyBoxes();
    initMockupCarousels();
    
    // CLV HEADER
    /* document.querySelectorAll ( 'header .width-box.clv .mockup' ).forEach( function(element){
        var options = JSON.parse( element.getAttribute('data-options') );
        showCaseCLV = new MockupCarousel ( element, options );
        //viewportObjects.addItems ( mc, mockupCarouselVPOOptions, false );
    }); */
    
    // mockup content area PLAY/PAUSE
    /*
    document.querySelectorAll ( '.content-area' ).forEach( function(element){
        element.addEventListener( 'click', function(){
            this.toggleClass( 'content-animation-paused' );
        }, false);
    });
    */
    
    // sections in viewport
    var sectionVPOOptions = {
        category: ViewportObjects.CATEGORIES.SECTION,
        behavior: ViewportObjects.BEHAVIORS.ENTER_VP_CSS,
        cssSwitch: 'vp',
        viewportLimit: .25,
        presise: true
    };
    viewportObjects.addItems('header, section', sectionVPOOptions, true);
    
    // sections in viewport only once
    /* var sectionVPOOptions = {
        category: ViewportObjects.CATEGORIES.SECTION,
        behavior: ViewportObjects.BEHAVIORS.ENTER_VP_CSS,
        once: true,
        cssSwitch: 'vp',
        viewportLimit: .25,
        presise: true
    };
    viewportObjects.addItems('.persons', sectionVPOOptions, true); */
    
    // nav in viewport
    /* var mmenuVPOOptions = {
        category: ViewportObjects.CATEGORIES.NAV,
        recievers: document.querySelectorAll('nav, #mobile-mmenu-box'),
        behavior: ViewportObjects.BEHAVIORS.BOTTOM_BELOW_LIMIT_CSS,
        cssSwitch: 'vp',
        viewportLimit: 1,
        presise: true
    };
    viewportObjects.addItems('#mmenu', mmenuVPOOptions, true); */
    
    /*
    // homepage/work process vp anims
    document.querySelectorAll('#work-process .step').forEach( function(el){
        el.addEventListener('transitionend', enableNextWorkProcessItem ); // use bubble otherwise it will capture
    }, this);
    var workProcessVPOOptions = {
        category: ViewportObjects.CATEGORIES.WORK_PROCESS,
        behavior: ViewportObjects.BEHAVIORS.ENTER_VP_CSS,
        cssSwitch: 'vp',
        once: true,
        elementLimit: 1,
        viewportLimit: .5,
        presise: true
    };
    viewportObjects.addItems('#work-process .step', workProcessVPOOptions, false);
    // HP showcase vp anims
    var hpShowcaseVPOOptions = {
        category: ViewportObjects.CATEGORIES.HP_SHOWCASE,
        behavior: ViewportObjects.BEHAVIORS.ENTER_VP_OBJECT,
        enterFx: 'enterViewport',
        leaveFx: 'leaveViewport',
        loadControl: false,
        viewportLimit: 0,
        presise: false
    };
        
    document.querySelectorAll ( '#hp-showcase' ).forEach( function(element){
        var o = {
            id: 'hp-showcase', // for viewportItem
            target: element, // on which limits are based on
            enterViewport: switchShowcaseTo,
            leaveViewport: function(){
                switchShowcaseTo( this.target.getAttribute('data-stages').split(',').shift() );
            }
        };
        viewportObjects.addItems ( o, hpShowcaseVPOOptions, false );
    }, this);
        
    // refs filter box top switch
    var filterBoxTopVPOOptions = {
        category: viewportObjects.CATEGORIES.FILTER_BOX,
        behavior: viewportObjects.BEHAVIORS.BOTTOM_ABOVE_LIMIT_CSS,
        recievers: document.querySelectorAll('#filter-box-fixed'),
        cssSwitch: 'active',
        viewportLimit: 1,
        presise: true
    };
    viewportObjects.addItems ('#filter-box', filterBoxTopVPOOptions, false );
    
    // refs filter box bottom switch
    var filterBoxBottomVPOOptions = {
        category: viewportObjects.CATEGORIES.FILTER_BOX,
        behavior: viewportObjects.BEHAVIORS.TOP_ABOVE_LIMIT_CSS,
        recievers: document.querySelectorAll('#filter-box-fixed'),
        cssSwitch: 'passed',
        viewportLimit: .5,
        presise: false
    };
    viewportObjects.addItems ( '#work-process', filterBoxBottomVPOOptions, false );
    
    
    addArrowToDotsHoverHoutEvents();
    */
    
    // main menu / mobile menu
    jsAddedStyles.innerHTML += '#mobile-mmenu-switch.opened .hide-box {width: ' + document.getElementById('mobile-mmenu').offsetWidth + 'px}';
    document.querySelectorAll('#mobile-mmenu-box ul li.other-service, #mobile-mmenu-box ul li.online-service').forEach((li) => {
        li.style.display = 'none';
    });
    document.getElementById('mobile-mmenu-switch-btn').addEventListener('click', toggleMobileMenu);

    //updateNotebooksPerspective();
    
    //setFilterBoxLining();
    
       
    //initAgencyBoldDrawAttention();
    
    
    /* FORMS */
    document.querySelectorAll('#contact-form form').forEach(function(form){
        //onsubmit="return sendForm(this); "
        form.addEventListener('submit', sendForm.bind(form));
    });
    document.querySelectorAll('.input-box .error-text').forEach(function(input){
		input.addEventListener('click', inputErrorTextClick);
	});
	
	document.querySelectorAll('.input-box input').forEach(function(input){
		input.addEventListener('focus', fieldBoxFocus);
		input.addEventListener('blur', inputBoxBlur);
		input.addEventListener('change', inputBoxBlur);
		input.addEventListener('input', inputBoxBlur);
		input.addEventListener('paste', inputBoxBlur);
	});
    
    /* combo */
    document.querySelectorAll('.select-box select').forEach(function(input){
		input.addEventListener('focus', fieldBoxFocus);
		input.addEventListener('blur', selectBoxBlur);
		input.addEventListener('change', checkHasValue);
	});
    
    /* checkbox */
//    document.querySelectorAll('.checkbox-box input').forEach(function(input){
//		input.addEventListener('click', toggleCheckbox);
//		input.addEventListener('blur', inputBoxBlur);
//		input.addEventListener('change', checkHasValue);
//		input.addEventListener('input', checkHasValue);
//		input.addEventListener('paste', checkHasValue);
//	});
    
    document.querySelectorAll('.field-box.checkbox-box').forEach(function(fieldBox){
        var btnToggleCheckbox = fieldBox.querySelector('a.btn-toggle-checkbox');
        var input = fieldBox.querySelector('input.data-field[type="hidden"]');
        
        input.value = btnToggleCheckbox.hasClass('on') ? 1 : 0;
        btnToggleCheckbox.addEventListener('click', toggleCheckbox);
        //fieldBox.addEventListener('mouseout', checkboxBoxBlur.bind(btnToggleCheckbox));
        input.addEventListener('change', checkboxBoxBlur);
    });
    // accidentRecord
    document.querySelectorAll('.field-box.checkbox-box[data-field-name="accidentRecord"]').forEach(function(fieldBox){
        var input = fieldBox.querySelector('input.data-field[type="hidden"]');
        input.addEventListener('change', accidentRecordCheckboxBoxBlur);
    });
	
	/* textarea */
	document.querySelectorAll('.textarea-box .error-text').forEach(function(input){
		input.addEventListener('click', textareaErrorTextClick);
	});
	
	document.querySelectorAll('.textarea-box textarea').forEach(function(textarea){
		textarea.addEventListener('focus', fieldBoxFocus);
		textarea.addEventListener('blur', textareaBoxBlur);
		textarea.addEventListener('change', textareaBoxBlur);
		textarea.addEventListener('input', textareaBoxBlur);
		textarea.addEventListener('paste', textareaBoxBlur);
	});
    
    document.querySelectorAll('#contact-message #message').forEach(function(textarea){
        textarea.addEventListener('change', updateCharCount);
        textarea.addEventListener('input', updateCharCount);
        textarea.addEventListener('paste', updateCharCount);
    });
    
    
    /* file */
    document.querySelectorAll('.field-box.file-box').forEach(function(fieldBox){
        var maxFiles = parseInt( fieldBox.getAttribute('data-max-files') );
        var multiple = !maxFiles || maxFiles > 1 ? true : false;
        
//        fieldBox.addClass( multiple ? fieldBoxClasses.multipleFiles : fieldBoxClasses.singleFile ); // errors showing switch
    });
	document.querySelectorAll('.field-box.file-box').forEach(function(fileBox){
        var fileField = fileBox.querySelector('input[type="file"]');
        var btnFileSelect = fileBox.querySelector('.btn-file-select');
        btnFileSelect.addEventListener('click', browseFilesForSelection.bind(fileField));
        btnFileSelect.addEventListener('click', fieldBoxFocus.bind(fileField));
    });
    
    document.querySelectorAll('.field-box.file-box input.filenames-list').forEach(function(filenamesListField){
        var fieldBox = filenamesListField.closest('.field-box');
        var fileField = fieldBox.querySelector('input[type="file"]');
        
        updateFilenameList.bind( filenamesListField )();
        filenamesListField.addEventListener('click', browseFilesForSelection.bind(fileField));
    });
    document.querySelectorAll('.field-box.file-box input[type="file"]').forEach(function(fileField){
        fileField.addEventListener('change', uploadPublicFiles);
        fileField.addEventListener('focus', fieldBoxFocus);
        fileField.addEventListener('blur', fileBoxBlur);
        fileField.value = ''; // resets filefield onload to prevent browser's stored preselection
    });

    // mobile menu submenus toggles
    document.querySelectorAll('#mobile-mmenu a.btn-toggle-items').forEach((btn) => {
        btn.addEventListener('click', toggleMobileServiceGroup);
    });
    
    // mmenu submenus hides
    document.querySelectorAll('#mmenu a.btn-toggle-items span').forEach((btn) => {
        btn.addEventListener('mouseover', hideServiceGroups);
    });
    
    // mmenu submenus toggles
    document.querySelectorAll('#mmenu a.btn-toggle-items').forEach((btn) => {
        btn.addEventListener('click', toggleServiceGroup);
    });
    
    
    scroll();
    
    if( !IE() ) console.timeEnd('init');
    
}


function uploadPublicFiles(){
    // this == file field
    var files = this.files;
    var fieldBox = this.getParentByClass( fieldBoxClasses.fieldBox );
    var field = fieldBox.querySelector('input[type="file"]');
    // reset previous file
    fieldBox.querySelectorAll('.uploaded-file').forEach(function(uploadedFile){
        uploadedFile.remove();
    });
    fieldBox.setHasValue(false);
    
    updateFilenameList.bind(field)();
    
//    this.focus();
    var filesOverCount = [];
    var filesOverDataLimit = [];
    var numFiles, unavailableFrameFrom;
    var maxFiles = parseInt(fieldBox.getAttribute('data-max-files'));
    var dataSizeLimitMB = parseInt(fieldBox.getAttribute('data-size-limit-mb'));
    var dataSizeLimit = dataSizeLimitMB * Math.pow(1024, 2);
    for( var i = 0; i < this.files.length; i++ ){
        
        if( this.files[i] == undefined ) continue;
        
        log( this.files[i].size + '/' + dataSizeLimit);
        // before upload checks
        
        if( this.files[i].size > dataSizeLimit ){
            filesOverDataLimit.push( this.files[i].name );
            continue;
        }
        
        numFiles = fieldBox.querySelectorAll('.uploaded-file').length;
        if( maxFiles && numFiles == maxFiles ){
            filesOverCount.push( this.files[i].name );
            continue;
        }
        publicUploadFile.bind(this, i)();
    }
    
    log(filesOverDataLimit);
    log(filesOverCount);
    this.value = ''; // reset file field
    
    // notifications
    // over max files
    if( filesOverCount.length ){
        var replaces = {
            '{{NUM_MAX_FILES}}': maxFiles,
            '{{FILENAMES_LIST}}': filesOverCount.join(', ')
        };
        var content = dictionary.fileField.notifications.overMaximumFiles.replace(fragmentsRegex, function(match){
            return replaces[match];
        });
        addNotification.bind(fieldBox, content, 'warning')();
    }
    // over size limit
    if( filesOverDataLimit.length ){
        var replaces = {
            '{{MAXIMUM_FILESIZE_MB}}': dataSizeLimitMB,
            '{{FILENAMES_LIST}}': filesOverDataLimit.join(', ')
        };
        var content = dictionary.fileField.notifications.overDataLimitSingle.replace(fragmentsRegex, function(match){
            return replaces[match];
        });
        addNotification.bind(fieldBox, content, 'warning')();
    }
    
    // trigger blur
    var blur = new Event('blur');
    this.dispatchEvent(blur);
    
    // add blank frames to frame-list
//    addBlankFramesToFrameList.bind(fieldBox)();

}

function publicUploadFile(i){

    var fieldBox = this.getParentByClass( fieldBoxClasses.fieldBox );
    var field = fieldBox.querySelector('input[type="file"]');
    var alreadyUploaded = fieldBox.querySelectorAll('.uploaded-file').length;
    var fieldNamePath = fieldBox.getAttribute('data-field-name-path');
    var uid = fieldBox.getAttribute('data-uid');
//    var storage = fieldBox.getAttribute('data-storage');
//    var structure = fieldBox.getAttribute('data-structure');
//    var fileType = fieldBox.getAttribute('data-file-type');
//    var postProcess = fieldBox.getAttribute('data-postprocess');

    removeNotifications.bind(fieldBox, true, false)();
    
    var fileList = fieldBox.querySelector('.file-list');
    var replaces = {
        '{{LOADED}}': '',
//        '{{PARENT_RELATED}}': 0,
        '{{FILE_ID}}': '0',
//        '{{FILE_TYPE}}': fileType,
//        '{{STYLE}}': '',
        '{{FILE_URI}}': '',
        '{{NAME}}': fieldNamePath + '[]'
    };
    var uploadedFileBoxHtml = fragments.publicUploadedFile.replace(fragmentsRegex, function(match){
        return replaces[match];
    });
    var fileUploadBox = fileList.appendChild( htmlToElement( uploadedFileBoxHtml ) );

//    fileUploadBox.querySelector('a.btn-shift-left').addEventListener('click', swapNodeUp.bind( fileUploadBox, updateFilenameList.bind( fileUploadBox ) ));
//    fileUploadBox.querySelector('a.btn-shift-right').addEventListener('click', swapNodeDown.bind( fileUploadBox, updateFilenameList.bind( fileUploadBox ) ));
    
    // just visual switch for file preview buttons positions
    if( !alreadyUploaded ){
        fieldBox.addClass('single-file-uploaded');
    }else{
        fieldBox.removeClass('single-file-uploaded');
    }
    
    var btnPreview = fileUploadBox.querySelector('a.btn-preview');
//    var btnDelete = fileUploadBox.querySelector('a.btn-delete');
    var btnAbort = fileUploadBox.querySelector('a.btn-abort');
//    var fileUploadPreviewBox = fileUploadBox.querySelector('.uploaded-file-box');
    var fileInput = fileUploadBox.querySelector('input[type="hidden"]');
    var loadingBar = fileUploadBox.querySelector('.loading-bar');
    var loadingProgress = fileUploadBox.querySelector('.loading-progress');
    
    // XHR
    var xhr, formData;
    var url = fieldBox.getAttribute('data-upload-url');
    
    xhr = new XMLHttpRequest();
    formData = new FormData();
    
    var filename = this.files[i]['name'].split(/(\.[a-zA-Z0-9_-]+)$/, 2);
    filename[0] = normalize(filename[0]);
    filename[1] = filename[1].toLowerCase();
    
    formData.append('file', this.files[i], filename.join('') );
    formData.append('uid', uid );
//    formData.append('storage', storage );
//    formData.append('structure', structure );
//    formData.append('fileType', fileType );
//    formData.append('postprocess', postProcess );
    
    xhr.open('POST', url, true);
    xhr.upload.addEventListener('progress', function(event){
        if( event.lengthComputable ){
            var percentLoaded = Math.round( 100 * event.loaded / event.total );
            loadingBar.style.width = percentLoaded + '%';
            loadingProgress.innerHTML = percentLoaded + '&nbsp;%';
        }
    });
    xhr.addEventListener('readystatechange', function(){
//        log( xhr );
        if(
            xhr.readyState == XMLHttpRequest.DONE
            &&
            (
                xhr.status == 0 ||
                (
                    xhr.status >= 200 &&
                    xhr.status < 400
                )
            )
        ){
            var data;
            try{
                data = JSON.parse(xhr.responseText);
                
                if( data.notifications && Array.isArray( data.notifications ) && data.notifications.length ){
                        
                    addNotifications.bind( fieldBox, data.notifications )();

                }
                log(data);
                if( data.success ){
                    fileUploadBox.setAttribute('data-file', data.file);
                    fileInput.value = data.idUserUpload;
                    btnPreview.setAttribute('href', data.file);
                    
                    fileUploadBox.addClass('loaded');
                    fieldBox.addClass( fieldBoxClasses.hasValue );
                    
                }else{
                    
                    fileUploadBox.remove();
                    
                }
                
                fileBoxBlur.bind(field)();
                updateFilenameList.bind(field)();
                
//                log(data);
//                if( data.REQUEST ) log( data.REQUEST );
//                if( data.FILES ) log( data.FILES );
//                if( data.COOKIES ) log( data.COOKIES );
//                if( data.CHECKS ) log( data.CHECKS );
//                if( data.QUERIES ) log( data.QUERIES );
            }catch(e){
                log('xhr.readystatechange');
                log(e);
                log(xhr.responseText);
                
                var userAbort = fileUploadBox.hasClass('user-aborted');
                
                if( !userAbort ){
                    addNotification.bind(fieldBox, USER_NOTICE_PARSE_ERROR, notificationClasses.warning )();
                }
                
                fileUploadBox.remove();
            }
        }
    });
    xhr.addEventListener('error', function(e){
        log('xhr.error');
        log( xhr );
        log(e);
        
        fileUploadBox.remove();
        fileBoxBlur.bind(field)();
        updateFilenameList.bind(field)();
        addNotification.bind(fieldBox, USER_NOTICE_NETWORK_OR_SERVER_ERROR, notificationClasses.warning )();
        
    });
    xhr.addEventListener('abort', function(e){
        log('xhr.abort');
        log( xhr );
        log(e);
        
        var userAbort = fileUploadBox.hasClass('user-aborted');

        fileUploadBox.remove();
        fileBoxBlur.bind(field)();
        updateFilenameList.bind(field)();
        
        if( !userAbort ){
            addNotification.bind(fieldBox, USER_NOTICE_NETWORK_OR_SERVER_ERROR, notificationClasses.warning )();
        }
    });
    xhr.send( formData );
    
    btnAbort.addEventListener('click', abortXHR.bind(xhr, fileUploadBox) );
    
}


function normalize(str, lowerCase, dashes, trimNonWordNonDigitChars){
    if( typeof lowerCase == 'undefined' ) lowerCase = true;
    if( typeof dashes == 'undefined' ) dashes = true;
    if( typeof trimNonWordNonDigitChars == 'undefined' ) trimNonWordNonDigitChars = true;
    
    str = str.trim().normalize('NFD').replace(/[\u0300-\u036f]/g, '').replace(/[\s+]/g, ' '); // trim whitespace / normalize / multiple to single whitespace
    if( lowerCase ) str = str.toLowerCase();
    if( dashes ) str = str.replace(/([^a-z0-9]+)/g, '-'); // multiple (nonword or nondigit) characters to single dash
    if( trimNonWordNonDigitChars ) str = str.replace(/^([^a-z0-9]+)|([^a-z0-9]+)$/g, ''); // remove dashes @begining/end
    
    return str;
}

function updateCharCount(){
    log('updateCharCount');
    var fieldBox = this.hasClass( fieldBoxClasses.fieldBox ) ? this : this.getParentByClass( fieldBoxClasses.fieldBox );
    log(fieldBox);
    var charCount = fieldBox.querySelector('.char-count');
    var field = fieldBox.querySelector('textarea');
    var maxlength = field.hasAttribute('maxlength') ? field.getAttribute('maxlength') : 'N/A';
    if( !charCount ) return;

    charCount.innerHTML = field.value.length + '/' + maxlength;
    log(field.value.length + '/' + maxlength);

}

function selectRefCategory(currBtn, jumpToTop){
    
    if( selectingRefCategory ) return;
    
    // prevent overload / disable filtering for short time
    selectingRefCategory = true;
    setTimeout( function(){selectingRefCategory = false}, 1050 );
    
    // CTAG
    var categoryName = currBtn.querySelector('span span').innerText;
    log('gtmFilterClick: ' + categoryName);
    window['dataLayer'] = window['dataLayer'] || [];
    window['dataLayer'].push({
        'event': 'select_content',
        'type': categoryName
    });
    
    // process
    var category = currBtn.getAttribute('data-ref-category');
    
    var allCategoryBtns = document.querySelectorAll('.filter-box a.btn-rounded.category');
    
    if( !category ){ // ALL clicked
        log('no category');
        document.querySelectorAll('.filter-box a.btn-rounded.all').forEach(function(btn){
            btn.addClass('viewed');
        });
        document.querySelectorAll('.filter-box a.btn-rounded.category').forEach(function(btn){
            btn.removeClass('viewed');
        });
    }else{ // OTHER toggled
        log('category');
        if( !currBtn.hasClass('viewed') ){ // activated filter
            
            log('activated filter');
            document.querySelectorAll('.filter-box a[data-ref-category="' + category + '"]').forEach(function(btn){ // two menus (every btn is doubled)
                btn.addClass('viewed');
            });
            
            document.querySelectorAll('.filter-box a:not([data-ref-category="' + category + '"])').forEach(function(btn){
                btn.removeClass('viewed');
            });
            
        }else{ // deactivated filter
            
            log('deactivated filter');
            document.querySelectorAll('.filter-box a[data-ref-category="' + category + '"]').forEach(function(btn){ // two menus (every btn is doubled)
                btn.removeClass('viewed');
            });
            
            document.querySelectorAll('.filter-box a.btn-rounded.all').forEach(function(btn){
                btn.addClass('viewed');
            });
            document.querySelectorAll('.filter-box a.btn-rounded.category').forEach(function(btn){
                btn.removeClass('viewed');
            });
            
        }
    }
    
    var selectedCategoryBtns = document.querySelectorAll('.filter-box a.btn-rounded.category.viewed');
    if( allCategoryBtns.length == selectedCategoryBtns.length ){ // ALL SELECTED --> ALL
        document.querySelectorAll('.filter-box a.btn-rounded.all').forEach(function(btn){
                btn.addClass('viewed');
        });
        document.querySelectorAll('.filter-box a.btn-rounded.category').forEach(function(btn){
                btn.removeClass('viewed');
        });
    }else if( !selectedCategoryBtns.length ){ // NONE SELECTED --> ALL
        document.querySelectorAll('.filter-box a.btn-rounded.all').forEach(function(btn){
                btn.addClass('viewed');
        });
    }else{
        document.querySelectorAll('.filter-box a.btn-rounded.all').forEach(function(btn){
                btn.removeClass('viewed');
        });
    }
    
    if( jumpToTop ) document.location.hash = 'reference';
    listRefBlocks(0); // set timeout
    // set scroll if click is from fixed filters menu
}

function listRefBlocksPage(page, jumpToTop){
    
    if( page == blocksPage ) return;
    /*
    document.querySelectorAll('#ref-blocks-pagination .item-dots>div').forEach(function(itemDot, i){
        if( i == page ){
            itemDot.addClass('curr');
        }else{
            itemDot.removeClass('curr');
        }
    });
    */
    if( jumpToTop ) document.location.hash = 'reference';
    
    listRefBlocks(page)
}

function onlyUnique(value, index, self) {
    return self.indexOf(value) === index;
}

function listRefBlocks(page){
    
    if( typeof page != 'undefined' ) blocksPage = page;
    
    var blocks = [];
    
    if( !IE() ) console.time('listRefBlocks();');
    
    // GET CURRENT FILTERS
    var filters = [];
    document.querySelectorAll('.filter-box').item(0).querySelectorAll('a.category.viewed').forEach(function(btn){
        filters.push( btn.getAttribute('data-ref-category') );
    });
    
    
    refs.categories.forEach(function(category){
        log( category );
        if( !filters.length || filters.indexOf( category.name ) != -1 ){
            blocks = blocks.concat( category.blocks );
        }
    });
    blocks.sort(function(a, b){return a - b;});
    
    blocks = blocks.filter(onlyUnique);
    
    // pagination
    var numPages = Math.ceil( blocks.length / numBlocksPerPage );
    document.querySelectorAll('#ref-blocks-pagination .item-dots>div').forEach(function(itemDot, i){
        if( i >= numPages || numPages == 1 ){
            itemDot.addClass('inactive');   
        }else{
            itemDot.removeClass('inactive');   
        }
        if( i == page ){
            itemDot.addClass('curr');
        }else{
            itemDot.removeClass('curr');
        }
    });
    log('REF BLOCK PAGE: ' + ( blocksPage + 1 ) + '/' + Math.ceil( blocks.length / numBlocksPerPage ) + ' (' + blocks.length + ' blocks)' );
    
    
    
    
    // PAGE BLOCKS
    blocks = blocks.slice( blocksPage * numBlocksPerPage, blocksPage * numBlocksPerPage + numBlocksPerPage );
    
    
    // GET
    //slice = ( slice + numSliced ) % refs.blocks.length;
    //refs.blocks.slice(slice, slice + numSliced)

    var copyReplaceRegex = /\{\{COPY_STATE\}\}|(\{\{UNIQUE_BLOCK_ID\}\})|(\{\{BLOCK_COPY\}\})/g;
    var visualReplaceRegex = /\{\{FLAG_FIRST\}\}|\{\{VISUAL_DEPTH\}\}|(\{\{URL_PRIMARY_VISUAL\}\})|(\{\{URL_PREVIEW_VISUAL\}\})|(\{\{HTML_COMMENT_BEGIN\}\})|(\{\{HTML_COMMENT_END\}\})|(\{\{VISUAL_WIDTH\}\})|(\{\{VISUAL_HEIGHT\}\})/g;
    var mockupReplaceRegex = /\{\{MOCKUP_CSS_ID\}\}|(\{\{UNIQUE_BLOCK_ID\}\})|(\{\{WIDTH_BOX_STATE\}\})|(\{\{MOCKUP_OPTIONS\}\})|(\{\{VISUALS\}\})/g;
    var sectionRefBoxes = document.querySelectorAll('.ref-list section .ref-block');

    // PARSE ALL SECTIONS WITH REF BLOCK
    sectionRefBoxes.forEach(function(refBox, s){
        
        var removePrevious = true;
        var addNew = true;
        var blockData = refs.blocks[ blocks[s] ];
        var uniqueBlockDataId = blockData ? blockData.uid : null;
        var copy = refBox.querySelector('.copy');
        var mockupArea = refBox.querySelector('.mockup-area');
        var activeWidthBoxes = refBox.querySelectorAll('.width-box.active');
        
        var copyHeight = {begin: 0, end: 0}
        var prevMockupAreaMockup;
        var currMockupAreaMockup;
        var currMockupIndex = null;
        var blockMockupsHTML = [];
        
//        log( 'copyHeight--------------------0' );
//        log( copyHeight );
        copyHeight.begin = copy.offsetHeight;
//        log( copyHeight );
        
        // curr mockup index
        // set first .curr mockup params within block WHEN FILTERS OFF / MATCHING FILTER criteria
        if( blockData ){
            
            filters.forEach(function(category){
                if( blockData.categories[category] ){ // category present within block mockups
                    currMockupIndex = blockData.categories[category][0];
                    return;
                }
            });
            currMockupIndex = currMockupIndex === null ? 0 : currMockupIndex; // if filters empty, set index to first mockup

            currMockupAreaMockup = blockData.mockups[ currMockupIndex ].mockup.toLowerCase();
            log( 'currMockupAreaMockup: ' + currMockupAreaMockup + ' of ' + currMockupIndex + 'th blocks\'s mockup' );
            
        }
        
        
        // no data for section --> hiding section
        if( uniqueBlockDataId === null ){
            
            log('no block data for section');
            
            addNew = false;
            
            if( activeWidthBoxes.length ){
                log('hiding ref block section');
                removePrevious = true;
                refBox.addClass('empty');
            }else{
                log('block section already hidden');
                removePrevious = false;
            }
            
        }else{
            log('keeping visible/showing ref block section');
            var activeUID = activeWidthBoxes.length ? activeWidthBoxes.item( activeWidthBoxes.length - 1 ).getAttribute('data-uid-block') : null;
            // check if block equals --> change just category to filtered (or [0] if filter is 'ALL'
            log( 'UIDs COMPARE: ' + activeUID + '/' + uniqueBlockDataId );
            if( activeUID == uniqueBlockDataId ){
                log( 'UIDs EQUALS' );
                
                log( 'copyHeight--------------------1' );
                log( copyHeight );
                copyHeight.end = copyHeight.begin;
                log( copyHeight );
                
                addNew = false;
                removePrevious = false;
                
                var mockupCarouselToSwitchTo = window['MockupCarouselsReference'][ refBox.querySelectorAll('.width-box.' + uniqueBlockDataId + ' .mockup').item(currMockupIndex).getAttribute('id') ];
                mockupCarouselToSwitchTo.switchToMockup(event);
                
            }else if( activeUID === null ){
                log('showing ref block section');
                removePrevious = false;
                refBox.removeClass('empty');
            }
            
        }
        
        log('ADD/REMOVE: ' + addNew + ' / ' + removePrevious );
        
        /*
            COPY
        */
        
        
        if( removePrevious ){
            
            // bind delayed removal OF previous text contents
            var prevContents = copy.querySelectorAll('.content.active');
            prevContents.forEach(function(content, i){
                
                // hide content
                var animationEndElement = document.createElement('div');
                animationEndElement.addClass('ref-block-copy-switch');
                content.appendChild( animationEndElement );
                animationEndElement.addEventListener( 'animationend', content.remove.bind(content) );
                
                // trigger hiding
                content.removeClass('active');
                
            });
            
        }
        
        if( addNew ){
            
            /*
                COPY
            */
            
            var prevContents = copy.querySelectorAll('.content.active');
            prevContents.forEach(function(content, i){
                
                // hide content
                var animationEndElement = document.createElement('div');
                animationEndElement.addClass('ref-block-copy-switch');
                content.appendChild( animationEndElement );
                animationEndElement.addEventListener( 'animationend', content.remove.bind(content) );
                
                // trigger hiding
                content.removeClass('active');
                
            });

            // next copy html prep
            var replaces = {
                '{{COPY_STATE}}': '',
                '{{UNIQUE_BLOCK_ID}}': blockData.uid,
                '{{BLOCK_COPY}}': blockData.copy
            };
            var copyHtml = refs.fragments.copy.replace(copyReplaceRegex, function(match){
              return replaces[match];
            });
            
            var currContent = copy.appendChild( htmlToElement(copyHtml) );
            log( 'copyHeight--------------------2' );
            log( copyHeight );
            copyHeight.end = currContent.offsetHeight;
            log( copyHeight );
            

            /*
                MOCKUPS
            */
                
            // create new with-boxes html
            blockData.mockups.forEach( function(mockupData, m){
                var mockup = mockupData.mockup;
                var mockupCssId = mockupData.mockup.toLowerCase();
                var mockupVisualsHTML = '';
                var widthBoxState = '';
                
                
                
                var htmlComment = { // preload curr mockup visuals in page load phase
                    begin: widthBoxState ? '' : '<!--',
                    end: widthBoxState ? '' : '-->'
                };
                
                mockupData.visuals.forEach( function(visual, v){
                    var flagFirst = !v ? 'first' : ''; // sets the first visual to be in mockups viewport rather than sliding in etc. (just css solution)
                    var primaryVisual;
                    var previewVisual;
                    var visualWidth = '';
                    var visualHeight = '';
                    log('MOCKUP: ' + mockup);
                    if( mockup == 'html5-banner' ){
                        primaryVisual = visual['preview']; 
                        previewVisual = visual['html5-banner']; 
                        visualWidth = mockupData['options']
                    }else{
                       primaryVisual = visual; 
                    }
                    log(primaryVisual);
                    log(previewVisual);
                    var replaces = {
                        '{{FLAG_FIRST}}': flagFirst,
                        '{{VISUAL_DEPTH}}': v,
                        '{{URL_PRIMARY_VISUAL}}': primaryVisual,
                        '{{URL_PREVIEW_VISUAL}}': previewVisual,
                        '{{HTML_COMMENT_BEGIN}}': htmlComment.begin,
                        '{{HTML_COMMENT_END}}': htmlComment.end,
                        '{{VISUAL_WIDTH}}': visualWidth,
                        '{{VISUAL_HEIGHT}}': visualHeight
                    };
                    mockupVisualsHTML += refs.fragments[ mockup ].visual.replace(visualReplaceRegex, function(match){
                        return replaces[match];
                    });

                });

                var replaces = {
                    '{{MOCKUP_CSS_ID}}': mockupCssId,
                    '{{UNIQUE_BLOCK_ID}}': uniqueBlockDataId,
                    '{{WIDTH_BOX_STATE}}': widthBoxState,
                    '{{MOCKUP_OPTIONS}}': JSON.stringify( mockupData['options'] ).toHtmlEntities(),
                    '{{VISUALS}}':mockupVisualsHTML
                };
                blockMockupsHTML.push(
                    refs.fragments[ mockup ].mockup.replace(mockupReplaceRegex, function(match){
                        return replaces[match];
                    })
                );
                
            });
            
        }
        
        // COPY HEIGHT transition set
//        log( 'copyHeight--------------------3' );
//        log( copyHeight );
        if( Math.abs( copyHeight.begin - copyHeight.end ) > 1 ){
//            log('setting copy: ' + s);
//            log(copy);
            copy.setHeight( copyHeight.begin );
            setTimeout(copy.setHeight.bind(copy, copyHeight.end), 100); // trigger transition to curr height of copy box
        }else{
            log( 'SAME copyHeight--------------------2' );
            copy.querySelectorAll('.content.active').forEach(function(content, i){
                content.addClass('curr');
            });
            copy.setHeight('auto');
        }
        
        
        if( removePrevious ){    
            /*
                MOCKUPS
            */

            
            // remove/bind delayed removal OF previous width-boxes
            mockupArea.querySelectorAll('.width-box.active').forEach(function(widthBox){
                
                if( !widthBox.hasClass('init') ){ // skip non previously initiated
                    
                    if( widthBox.hasClass('curr') ){
    //                    log( 'CURR FOUND' );
                        widthBox.removeClass('active');
                        prevMockupAreaMockup = widthBox.getAttribute('data-mockup');
    //                    log( widthBox );
    //                    log( prevMockupAreaMockup );
                        var currMockup = widthBox.querySelector('.mockup'); // .curr mockup before blocks switch
                        currMockup.addEventListener('transitionend', function(){
                            if( event && event.target == this )
                                this.parentNode.remove();
                        }.bind(currMockup) );
                        widthBox.removeClass('curr');
                    }else{
                        widthBox.remove();
                    }

                }
                
            });
            
        }
        
        if( addNew ){
            /*
                MOCKUPS
            */

            // append new width-boxes
            blockMockupsHTML.forEach(function(blockMockupHTML, m){
                var mockup = mockupArea.appendChild( htmlToElement( blockMockupHTML ) );
                
                if( m == currMockupIndex ){ // curr mockup
                    setTimeout(function(currContent, m){
                        this.addClass('curr'); //  mockup
                        if( currContent ){
                            currContent.querySelectorAll('.categories a').item(m).addClass('viewed'); // category switch
                        }
                    }.bind(mockup, currContent, m), 150);
                }
            });
            
        }
        
        if( removePrevious ) mockupArea.removeClass(prevMockupAreaMockup);
        if( addNew ) mockupArea.addClass(currMockupAreaMockup);
        
    });
    
    //initCopyBoxes();
    initMockupCarousels();
    setTimeout( response, 950 );
    if( !IE() ) console.timeEnd('listRefBlocks();');
}

// sets the copy holders to automaticly set height after it's transition to "auto"
function initCopyBoxes(){
    document.querySelectorAll('.ref-block .copy').forEach(function(copy, i){
        copy.addEventListener('transitionend', function(event){
            // capture only own height transition
//            log( event );
            if( this == event.target && event.propertyName == 'height' ){
                this.querySelectorAll('.content.active').forEach(function(content, i){
                    content.addClass('curr');
                });
                this.setHeight('auto');
            }
        }.bind(copy));
    });
}

var delayedYTPlayersInitBase = 800;
var delayedYTPlayersInitIncrement = 150;
var delayedYTPlayersInit;
function initMockupCarousels(){
    
    delayedYTPlayersInit = delayedYTPlayersInitBase; // reset delay to base (increments solved within mockup carousel player's init)
    
    // mockup carousels options
    var mockupCarouselVPOOptions = {
        category: ViewportObjects.CATEGORIES.MOCKUP_CAROUSEL,
        behavior: ViewportObjects.BEHAVIORS.ENTER_VP_OBJECT,
        enterFx: 'enterViewport',
        leaveFx: 'leaveViewport',
        loadControl: true,
        elementLimit: .5,
        viewportLimit: .25,
        presise: false
    };
    
    // init Mockup Carousels (BB, Notebook, CLV, Smartphone, ..)
    document.querySelectorAll ( 'section .width-box.init .mockup' ).forEach( function(element){
        var options = JSON.parse( element.getAttribute('data-options') );

        var mc = new MockupCarousel ( element, options );
        viewportObjects.addItems ( mc, mockupCarouselVPOOptions, false );
        
        // mockup carousel & block references
        MockupCarouselsReference[mc.id] = mc; // allow MockupCarousel instance reference
//        log( mc.uidBlock );
        if( typeof MockupCarouselsBlocks[mc.uidBlock] == 'undefined' ){
            log( 'adding: ' + mc.uidBlock );
            MockupCarouselsBlocks[mc.uidBlock] = {
                switchesSet: false
            };
        }
        
        // mark mockup's width-boxes as initiated
        element.getParentByClass('width-box').removeClass('init');
    });
    
    // set block features
    for( var uidBlock in MockupCarouselsBlocks ){

        var block = MockupCarouselsBlocks[uidBlock];
        if( block.switchesSet ) continue; // skip for already set
        
        block.switchesSet = true;
        
        
        // set switches
        var categorySwitches = document.querySelectorAll('.ref-block .copy .content.active.' + uidBlock + ' .categories > a.init');
        var blockMockups = document.querySelectorAll('.ref-block .mockup-area .width-box.active.' + uidBlock + ' .mockup');
        
        categorySwitches.forEach(function(cs, i){
            var mockupCarouselInstance = MockupCarouselsReference[ blockMockups.item(i).id ];
            mockupCarouselInstance.setBlockParams(i, blockMockups);
            if( this.length > 1 ){ // bind click for multiple block mockups
                cs.addEventListener('click', mockupCarouselInstance.switchToMockup.bind(mockupCarouselInstance) );
            }
            cs.removeClass('init'); // mark as already initiated
            if( blockMockups.item(i).parentNode.hasClass('curr') ) cs.addClass('viewed'); // mark as currently viewed
        }, categorySwitches);
        /*
        if( categorySwitches.length > 1 && categorySwitches.length == blockMockups.length ){
            
            
        }else if( categorySwitches.length == 1 && categorySwitches.length == blockMockups.length ){
            categorySwitches.item(0).addClass('viewed');
        }
        */
        // remove passed initiated uid block
        delete( MockupCarouselsBlocks[uidBlock] );
    }
    
    addArrowToDotsHoverHoutEvents();
    
}

function addArrowToDotsHoverHoutEvents(){
    // arrow-to-dot hover/hout
    document.querySelectorAll('a.arrow-to-dot.init').forEach(function(a){
        a.removeClass('init');
        a.addEventListener('mouseenter', linkHover);
        a.addEventListener('mouseleave', linkHout);
    }, this);
}

var hoverCssClass = 'hover';
var houtCssClass = 'hout';
function linkHover(){
    this.addClass(hoverCssClass);
    this.removeClass(houtCssClass);
    this.removeEventListener('transitionend', endLinkHoutTransition);
}

function linkHout(){
    this.addClass(houtCssClass);
    this.removeClass(hoverCssClass);
    log('adding hout end event listener');
    this.addEventListener('transitionend', endLinkHoutTransition);
}

function endLinkHoutTransition(event){
    log('ending hout hout');
    this.removeClass(houtCssClass);
    this.removeEventListener('transitionend', endLinkHoutTransition);
}

function enableNextWorkProcessItem(event){
//    log(event);
    event.stopPropagation();

    if( event.propertyName != 'opacity' || !event.target.hasClass('top') ) return;

    var next = this;
    while( next = next.nextElementSibling ){
        next.addClass('anim-enabled');
        if( next.hasClass('step') ) break;
    }
}

var scrollChangePrecision = 20;
var body = document.getElementsByTagName('body');
var y = 0;
function scroll(){
    
    currY = Math.round( window.scrollY ? window.scrollY : window.pageYOffset );
    
    viewportObjects.updateItemsHTML(currY, y);

    y = currY;
    
    //log('scroll: ' + y);
    
    document.querySelectorAll('.ref-block .copy .text').forEach(function(t){
        var attr = t.style.paddingTop;
        t.querySelector('h3').innerHTML += attr;
    });
}


var delayedResponse;
function response(event, forceScroll){
    /*
    log(event);
    log(forceScroll);
    */
    vw = document.getElementsByTagName('html')[0].clientWidth;
    vh = document.getElementsByTagName('html')[0].clientHeight;
    
    log('viewport: ' + vw + '×' + vh);

    // delayed response
    clearTimeout ( delayedResponse );
    delayedResponse = setTimeout(function(){
        
        vw = document.getElementsByTagName('html')[0].clientWidth;
        vh = document.getElementsByTagName('html')[0].clientHeight;
        
        viewportObjects.setItemsLimits(vh/*, y*/); //
        
        viewportObjects.updateItemsHTML(currY, forceScroll ? undefined : y);

        updateNotebooksPerspective();
        
        initBlog();
        
        createSlideMagnets();
        
        createFadeSides();
        
    }, 100);
    
    document.querySelectorAll('.infobox').forEach(function(infobox){
        if( !infobox.hasClass('hide') ){
            var infoboxContent = infobox.querySelector('.content-box');
            infobox.style.height = infoboxContent.offsetHeight + 'px';
        }
    });
    
    setFilterBoxLining();
    
}

function setFilterBoxLining(){

    document.querySelectorAll('.filter-box .content').forEach(function(fb, fbIndex){
        
        var lining = {
            w: fb.offsetWidth,
            totalLength: 0,
            rows: 0,
            items: []
        }
        
        fb.querySelectorAll('a.btn-rounded').forEach(function(btn){
            
            var style = window.getComputedStyle(btn);
            var w = btn.offsetWidth + parseFloat(style.marginLeft) + parseFloat(style.marginRight);
            this.totalLength += w;
            this.items.push(w);
            
        }, lining);
        
        fb.querySelectorAll('.break').forEach(function(br){
            br.removeClass('active');
        });
        
        lining.rows = Math.ceil( lining.totalLength / lining.w );
        
        var avgRowWidth;
        var passNextRow = 2;
        var lengths;
        var widths;
        
        while( passNextRow ){
            
            avgRowWidth = lining.totalLength / lining.rows;
            
            fb.querySelector('.avg-width').style.width = avgRowWidth + 'px';
            
            lengths = [0];
            widths = [[]];
            
            lining.items.forEach(function(itemW, i){
                
                var added = lengths[lengths.length-1] + itemW;
                if( added < avgRowWidth ){
                    //log('adding before avg width');
                    lengths[lengths.length-1] = added;
                    widths[widths.length-1].push(itemW);
                }else if( added >= avgRowWidth && added <= lining.w ){
                    //log('adding after avg width but before total width');
                    lengths[lengths.length-1] = added;
                    widths[widths.length-1].push(itemW);
                    // set for new line
                    if( i < ( lining.items.length - 1) ){
                        lengths.push(0);
                        widths.push([]);
                    }
                }else{
                    //log('after total width setting new line');
                    lengths.push( itemW );
                    widths.push( [itemW] );
                }
                
            });
        /*
            log( '-------------------' );
            log( lining );
            log( lengths );
            log( widths );
            log( '-------------------' );
        */
            if( widths.length > lining.rows ){
                lining.rows ++;
                passNextRow --;
            }else{
                passNextRow = false;
            }
        }
        
        var breakPos = 0;
        widths.forEach(function(rowWidths, i){
            breakPos += rowWidths.length;
            log('breakPos: ' + breakPos);
            breakEl = fb.querySelector('.break:nth-of-type(' + breakPos + ')');
            if( breakEl ) breakEl.addClass('active');
        });
        
        // set visibility for first filter box (fixed)
        if( !fbIndex && lining.rows > 2 ){
            fb.addClass('too-high');
        }else if( !fbIndex && lining.rows <= 2 ){
            fb.removeClass('too-high');
        }
        
    });
}

function updateNotebooksPerspective(){
    log('notebooks: ' + document.querySelectorAll('.width-box.notebook .medium').length );
    document.querySelectorAll('.width-box.notebook .medium').forEach(function(element){
        element.setNotebookMockupPerspective();
    });
}

function htmlToElement(html) {
    var template = document.createElement('template');
    html = html.trim(); // Never return a text node of whitespace as the result
    template.innerHTML = html;

    return template.content.firstChild ? template.content.firstChild : template.children[0];
}

function toggleMobileMenu(event){
    log('toggleMobileMenu()');
    var menuSwitch = document.getElementById('mobile-mmenu-switch');
    menuSwitch.toggleClass('opened');
    
    if( menuSwitch.hasClass('opened') ){
        document.getElementsByTagName('body')[0].addEventListener('click', toggleMobileMenu);
        event.stopPropagation();
    }else{
        document.getElementsByTagName('body')[0].removeEventListener('click', toggleMobileMenu);
    }
}

var showcaseSwitchTimer;
var showcaseVideo = {
    player: null,
    unmuted: false,
    loop: 0,
    byUser: false
};
function switchShowcaseTo(stage, byUser){

    log('switchShowcaseTo()');
    log(stage);
    
    if( typeof stage != 'string' ) stage = null;
    /*
    if( !showcaseVideo ){
        showcaseVideo = document.getElementById('showcase-video');
    }*/
//    log('switchShowcaseTo(' + stage + ')');
    var header = document.querySelector('header#hp-header');
    var showcase = document.querySelector('.showcase');
    var showcaseDots = document.querySelectorAll('.showcase-item-dots>div');
    var showcaseCurrDot = document.querySelector('.showcase-item-dots>div.curr');
    var stages = showcase.getAttribute('data-stages').split(',');
    
    clearTimeout( showcaseSwitchTimer );
    
    if( stage && showcase.hasClass( stages[0] ) ){ // skip switch if already not in initial stage
//        log('skipping showcase switch');
        return;
    }
    
        
    showcase.removeClass( stages.join(' ') );
    if( stage ){
        showcase.addClass(stage);
    }else{
        stage = 'foxo';
    }

    if( stage == 'dtp' ){
        showCaseCLV.bindOnloadCallback(showCaseCLV, 'enterViewport'); 
        showCaseCLV.enterViewport();
    }else{
        if( showCaseCLV ) showCaseCLV.leaveViewport();
    }
//    log(showcaseVideo.player);
    if( stage == 'video' && showcaseVideo.player ){
        showcaseVideo.loop = 0;
        showcaseVideo.player.playVideoAt(0);
    }else if( stage != 'video' && showcaseVideo.player ){
        showcaseVideo.player.pauseVideo();
    }
    
    stages.shift(); // remove intro
    
    curr = stages.indexOf(stage);
    
    // set dots
    if( showcaseCurrDot ) showcaseCurrDot.removeClass('curr');
    if( curr != -1 ) showcaseDots[curr].addClass('curr');
    
    // timed next
    if( !byUser ){
        showcaseVideo.byUser = false;
        next = stages[ ( curr + 1 ) % stages.length ];
        if( stage != 'video' ){
            showcaseSwitchTimer = setTimeout( switchShowcaseTo.bind(null, next, false ), stages.indexOf(stage) ? 4000 : 2500 );
        }
    }else{
        showcaseVideo.byUser = true;
    }
}

function toggleShowcaseVideoMuted(){
    if( showcaseVideo.player && document.querySelector('#hp-showcase').hasClass('video') ){
        
        var muteBtn = document.querySelector('#hailer-cone');
        
        if( showcaseVideo.player.isMuted() ){
            showcaseVideo.player.unMute();
            muteBtn.addClass('unmuted');
        }else{
            showcaseVideo.player.mute();
            muteBtn.removeClass('unmuted');
        }
    }
}

function toggleShowcaseVideoPaused(){
    if( showcaseVideo.player && document.querySelector('#hp-showcase').hasClass('video') ){
        
        var playerState = showcaseVideo.player.getPlayerState();
        
        if( playerState == window.YT.PlayerState.PAUSED ){
            showcaseVideo.player.playVideo();
        }else{
            showcaseVideo.player.pauseVideo();
        }
    }
}

function showcaseVideoReady(event){
//    log('showcaseVideoReady');
//    log(event.target);
    var playlist = JSON.parse( document.querySelector('#tv').getAttribute('data-youtube-ids') );
    
    event.target.addEventListener('onStateChange', showcaseVideoStateChange.bind( showcaseVideo ) );
    event.target.cuePlaylist( playlist );
    event.target.setLoop(true);
    event.target.mute();
    
//    event.target.setVolume(10);
}

function showcaseVideoStateChange(event){
    switch( event.data ){
        case -1:
//            log('-------showcaseVideo StateChange');
//            log(event);
//            log('video index: ' + event.target.getPlaylistIndex());
//            log( 'this.loop: ' + this.loop )
            if( this.loop && !showcaseVideo.byUser ){
                var stages = document.querySelector('.showcase').getAttribute('data-stages').split(',');
                stages.shift(); // remove intro
                var nextAfterVideo;
                stages.forEach(function(stage, i){
                    if( stage == 'video' ) nextAfterVideo = stages[ (i + 1) % stages.length ];
                });
                switchShowcaseTo(nextAfterVideo);
                this.player.pauseVideo();
            }
//            log( event.target.getPlaylist() );
//            log( event.target.getPlaylist().length );
            if( event.target.getPlaylistIndex() == ( event.target.getPlaylist().length - 1 ) ) this.loop ++
            break;
        case window.YT.PlayerState.PLAYING:
            break;
        case window.YT.PlayerState.CUED:
//            log('-------showcaseVideoStateChange');
//            log(event);
            showcaseVideo.player = event.target;
//            log('video index: ' + event.target.getPlaylistIndex());
//            window[ this.id + '_callback' ](event);
            break;
        default:
            break;
    }
}



var inactiveHashName = "_";
function hashChange(e){
    e.preventDefault();
    e.stopPropagation();
    var hash = window.location.hash.indexOf('#') === 0 ? window.location.hash.substr(1) : window.location.hash;
    if( hash == inactiveHashName ) return;
    var target = document.querySelector('*[data-anchor="' + hash + '"]');
    if( target ){
        window.scrollTo(0, target.cumulativeOffsetTop());
    }
    window.location.hash = inactiveHashName;
}


function clearDisplayedLimits(){
//    document.getElementsByClassName('limits')[0].innerHTML = '';
}

function displayLimit(id, name, y, css){
    var showLimit = displayLimitsFor.length && displayLimitsFor[0] != 'all' ? false : true;
    for( i in displayLimitsFor ){
        if( displayLimitsFor[i] == id ){
            showLimit = true;
            break;
        }
    }
    //log('showLimit: ' + id + ' / ' + showLimit);
    
//    log('y: ' + y);
    if( !showLimit ) return;
    if( !css ) css = '';
    var limit = document.getElementsByClassName('limits')[0].appendChild( htmlToElement( '<div class="limit ' + css + '" style="top: ' + y + 'px"><span>' + id + ' ' + name + '</span></div>' ) );
}


function roundToDecimals( n, d ){
    var decimals = Math.pow( 10, d);
    return Math.round( ( n /*+ Number.EPSILON*/ ) * decimals ) / decimals;
}






var initAgencyBoldDrawAttentionTimer;
var currAgencyBoldIndex = null;
function initAgencyBoldDrawAttention(){
    
    var bolds = document.querySelectorAll('#agency p span.draw-attention');
    
    if( !bolds.length ) return;

    if( !initAgencyBoldDrawAttentionTimer ){
        initAgencyBoldDrawAttentionTimer = setTimeout(initAgencyBoldDrawAttention, Math.round( 3000 + Math.random() * 3000 ) );
    }else{
        if( currAgencyBoldIndex !== null ){
            bolds.item(currAgencyBoldIndex).removeClass('underline');
        }else{
            currAgencyBoldIndex = -1;
        }
        
        currAgencyBoldIndex = ( currAgencyBoldIndex + 1 ) % bolds.length;
        
        bolds.item(currAgencyBoldIndex).addClass('underline');
        initAgencyBoldDrawAttentionTimer = setTimeout(initAgencyBoldDrawAttention, Math.round( 3000 + Math.random() * 3000 ) );
    }
}






var youtubeAPIReady = false;
function onYouTubeIframeAPIReady(){
    youtubeAPIReady = true;
    log('youtubeAPIReady: ' + youtubeAPIReady);
    
    if( document.querySelector('#showcase-video') ){
        
        setTimeout(function(){
            log('SETTING PLAYER');
            var videoPlayer = new YT.Player('showcase-video', {
                host: 'https://www.youtube-nocookie.com',
                width: '640',
                height: '360',
                playerVars: {
                    origin: window.location.host,
                    autoplay: 0,
                    controls: 0,
                    playsinline: 1,
                    showinfo: 0,
                    loop: 1,
                    color: 'white',
                    modestbranding: 1,
                    cc_load_policy: 0
                },
                events: {
                    onReady: showcaseVideoReady,
                }
            });
            
        }, 800);
        

    }
    
}

/*

    C L I E N T S   S L I D E   B O X
    

*/
function openClientLink(){
    log('openClientLink()');
    log(clientSlider);
    if( clientSlider.isDragged ){
        log('link click canceled');
    }else{
        window.location = this.getAttribute('data-url');
    }
}

function initClientsSlideBox(){
    
    if( !document.querySelector('#clients-slide-box') ) return;
    
    document.querySelectorAll('#clients-slide-box a.client').forEach(function(link){
        link.setAttribute('data-url', link.getAttribute('href'));
        link.removeAttribute('href');
        link.addEventListener('mouseup', openClientLink, true);
        link.addEventListener('touchend', openClientLink, true);
    });
    
    clientSlider.target.node = document.querySelector('#clients-slide-box .slide-box');
    var slideBox = clientSlider.target.node;
    
    slideBox.addEventListener('mousedown', startClientsDrag);
    slideBox.addEventListener('touchstart', startClientsTouchDrag);
    
    createSlideMagnets();
    
    createFadeSides();
    
}

function startClientsDrag(event){
    
    event.preventDefault();
    
    window.addEventListener('mousemove', dragClients);
    window.addEventListener('mouseup', stopClientsDrag);
    
    
    clientSlider.target.node.addClass('dragged');
//    clientSlider.target.minX = - ( clientSlider.target.node.offsetWidth - clientSlider.target.node.parentElement.offsetWidth );
    
    clientSlider.target.startX = clientSlider.target.node.offsetLeft;
    log(clientSlider.target.startX);
    
    clientSlider.startX = event.clientX;
    clientSlider.startY = event.clientY;
    clientSlider.target.x = clientSlider.target.node.offsetLeft;
    clientSlider.target.y = clientSlider.target.node.offsetTop;
    
}

function dragClients(event){
    log('dragClients()');
    event.preventDefault();
//    var body = document.querySelector('body');
//    var dot = htmlToElement('<div style="width: 20px; height: 20px; background: #faf; z-index:50000; position: absolute; left: ' + ( event.clientX + window.scrollX ) + 'px; top: ' + ( event.clientY + window.scrollY) + 'px"></div>');
//    body.appendChild(dot);
    
    clientSlider.x = event.clientX;
    clientSlider.y = event.clientY;
    
    deltaX = clientSlider.x - clientSlider.startX;
    
    if( Math.abs(deltaX) > 5 ) clientSlider.isDragged = true;
    
    var x = Math.min( clientSlider.target.maxX, Math.max(clientSlider.target.x + deltaX, clientSlider.target.minX) );
    
    clientSlider.target.node.style.left = x + 'px';
}

function stopClientsDrag(){
    log('stopClientsDrag()');
    window.removeEventListener('mousemove', dragClients);
    window.removeEventListener('mouseup', stopClientsDrag);
    
    clientSlider.target.endX = clientSlider.target.node.offsetLeft;
    log(clientSlider.target.endX);
    
    clientSlider.target.node.removeClass('dragged');
    
    clientSlider.target.node.offsetWidth; // force redraw
    
    if( Math.abs( clientSlider.target.endX - clientSlider.target.startX ) > clientSlider.minDragX ){
        setClientsMagnet(clientSlider.target.startX, clientSlider.target.endX - clientSlider.target.startX);
    }else{
        clientSlider.target.node.style.left = clientSlider.target.startX + 'px';
    }
    
    
    clientSlider.isDragged = false;
}

function startClientsTouchDrag(event){

    event.preventDefault();
    
    window.addEventListener('touchmove', touchDragClients);
    window.addEventListener('touchend', stopClientsTouchDrag);
    
    clientSlider.target.node.addClass('dragged');
//    clientSlider.target.minX = - ( clientSlider.target.node.offsetWidth - clientSlider.target.node.parentElement.offsetWidth );
    
    clientSlider.target.startX = clientSlider.target.node.offsetLeft;
    log(clientSlider.target.startX);
    
    clientSlider.startX = event.touches[0].clientX;
    clientSlider.startY = event.touches[0].clientY;
    clientSlider.target.x = clientSlider.target.node.offsetLeft;
    clientSlider.target.y = clientSlider.target.node.offsetTop;
    
}


function touchDragClients(event){
    log('touchDragClients()');
    event.preventDefault();
//    var body = document.querySelector('body');
//    var dot = htmlToElement('<div style="width: 20px; height: 20px; background: #faf; z-index:50000; position: absolute; left: ' + ( event.clientX + window.scrollX ) + 'px; top: ' + ( event.clientY + window.scrollY) + 'px"></div>');
//    body.appendChild(dot);
    
    clientSlider.x = event.touches[0].clientX;
    clientSlider.y = event.touches[0].clientY;
    
    deltaX = clientSlider.x - clientSlider.startX;
    
    if( Math.abs(deltaX) > 5 ) clientSlider.isDragged = true;
    
    var x = Math.min( clientSlider.target.maxX, Math.max(clientSlider.target.x + deltaX, clientSlider.target.minX) );
    
    clientSlider.target.node.style.left = x + 'px';
}

function stopClientsTouchDrag(){
    log('stopClientsTouchDrag()');
    window.removeEventListener('touchmove', touchDragClients);
    window.removeEventListener('touchend', stopClientsTouchDrag);
    
    clientSlider.target.endX = clientSlider.target.node.offsetLeft;
    log(clientSlider.target.endX);
    
    clientSlider.target.node.removeClass('dragged');
    
    clientSlider.target.node.offsetWidth; // force redraw
    
    if( Math.abs( clientSlider.target.endX - clientSlider.target.startX ) > clientSlider.minDragX ){
        setClientsMagnet(clientSlider.target.startX, clientSlider.target.endX - clientSlider.target.startX);
    }else{
        clientSlider.target.node.style.left = clientSlider.target.startX + 'px';
    }
    
    clientSlider.isDragged = false;
}

function createFadeSides(){
    
    if( !document.querySelector('#clients-slide-box') ) return;
    
    var sides = ['left', 'right'];
    var underlayingGradientElement = document.querySelector('section#clients .fill');
    var bgRect = underlayingGradientElement.getBoundingClientRect();
    
    sides.forEach(function(side, i){
        

        var canvas = document.getElementById('fade-' + side);
        var canvasRect = canvas.getBoundingClientRect();

        var ctxt = canvas.getContext('2d',{ alpha: true });

        ctxt.globalAlpha = 1;  // ensure alpha is on full
        ctxt.globalCompositeOperation = "source-over"; // ensure correct filter 

        // background gradient
        var bgGrad = ctxt.createLinearGradient(0, Math.round(bgRect.top - canvasRect.top), 0, Math.round(bgRect.top - canvasRect.top) + underlayingGradientElement.offsetHeight);
        bgGrad.addColorStop(0, "#d1d8dfff");
        bgGrad.addColorStop(1, "#ffff");
        ctxt.fillStyle = bgGrad;
        ctxt.fillRect(0, 0,canvas.width,canvas.height);

        var maskGrad = ctxt.createLinearGradient(0, 0, canvas.width, 0);
        maskGrad.addColorStop( i , "#000f");
        maskGrad.addColorStop(.5, "#000f");
        maskGrad.addColorStop( ( i + 1 )%2, "#0000");

        ctxt.globalCompositeOperation = "destination-in"; // set filter to mask letting only opaque pixels in   
        ctxt.fillStyle = maskGrad;
        ctxt.fillRect(0, 0, canvas.width, canvas.height);
        
    });
}

var clientSlider = {
    sliderOuterBoxW: null,
    sliderBoxW: null,
    slideStep: null,
    minDragX: 30,
    startX: null,
    startY: null,
    endX: null,
    endY: null,
    x: null,
    y: null,
    isDragged: false,
    magnets: [],
    target: {
        node: null,
        minX: null,
        maxX: 0,
        startX: 0,
        endX: 0,
        x: 0,
        y: 0
    }
}

function createSlideMagnets(){
    
    if( !document.querySelector('#clients-slide-box') ) return;
    
    clientSlider.sliderOuterBoxW = clientSlider.target.node.parentElement.offsetWidth;
    clientSlider.sliderBoxW = clientSlider.target.node.offsetWidth;
    
    clientSlider.target.minX = - ( clientSlider.target.node.offsetWidth - clientSlider.target.node.parentElement.offsetWidth );
    
    log(clientSlider);
    
    var clients = document.querySelectorAll('#clients-slide-box a.client');
    
    var layout = [];
    
    clients.forEach(function(client){
        log('client: ' + client.offsetLeft + '/' + client.offsetWidth);
        layout.push({left: client.offsetLeft, width: client.offsetWidth});
    });
    
    var hgap = layout[1].left - ( layout[0].left + layout[0].width);
    log('hgap:' + hgap);
    log(clientSlider.target.node);
//    var sidePadding = clientSlider.target.node.offsetWidth - ( layout[layout.length - 1].left + layout[layout.length - 1].width );
    var sidePadding = layout[0].left;
    log('sidePadding:' + sidePadding);
    
    clientSlider.slideStep = clientSlider.target.node.parentElement.offsetWidth - 2*sidePadding;
    
    x = 0;
    clientSlider.magnets = [x];
    while( -x > clientSlider.target.minX ){
        
        x += clientSlider.slideStep;
        var magnet;
        layout.forEach(function(client, i){
            if( client.left + client.width < x ){
                magnet = layout.length > (i+1) ? Math.max( -( layout[i+1].left - sidePadding ), clientSlider.target.minX ) : clientSlider.target.minX;
            }
        });
        clientSlider.magnets.push(magnet);
    }
    log(clientSlider.magnets);
    clientSlider.target.node.style.left = 0 + 'px';
}


function setClientsMagnet(curr, delta){
    if( curr === null ) curr = clientSlider.target.node.offsetLeft;
    
    var magnet;
    // slide right
    if( delta < 0 ){
        log('slide left: ' + delta);
        var cancel = false;
        clientSlider.magnets.forEach(function(x){
            if( !cancel && x < (curr + delta) ){
                log(x);
                magnet = x;
                cancel = true;
            }
        });
    // slide right
    }else{
        log('slide right: ' + delta);
        for(var i = (clientSlider.magnets.length - 1); i >= 0; i--){
            x = clientSlider.magnets[i];
            if( x > (curr + delta) ){
                log(x);
                magnet = x;
                break;
            }
        }
    }
    
    log('magnet: ' + magnet);
    clientSlider.target.node.style.left = magnet + 'px';
    
}

function contactFormGTM_n_clear(){
    var form = this;
    log(form);
    log('contactFormGTM_n_clear');
    log('gtmContactForm');
    window['dataLayer'] = window['dataLayer'] || [];
    window['dataLayer'].push({
        'event': 'generate_lead',
        'type': 'form_success'
    });
    
}

function removeDOMElement(element){
    log('removeDOMElement==========================');
    if( typeof element == 'undefined' || !(element instanceof Element) ) element = false;
    if( !element && this && typeof this === 'object' && this instanceof Element) element = this;
    log(element);
    if( element ) element.remove();
}

function hideServiceGroups(event){
    event.stopPropagation();
    log(this);
    log(event.target.tagName.toLowerCase());
    if( event.target.tagName.toLowerCase() != 'span') return;
    log('hiding');
    var allWrappersLi = document.querySelectorAll('#mmenu li.toggle-items-wrapper');
    
    allWrappersLi.forEach((li)=>{
        li.removeClass('opened');
    });
}

function toggleServiceGroup(event){
    event.stopPropagation();
    var btnToggle = this;
    var wrapperLi = btnToggle.closest('li');
    var currDisplayed = wrapperLi.hasClass('opened');
    var groupClass = btnToggle.getAttribute('data-service');
    var allWrappersLi = document.querySelectorAll('#mmenu li.toggle-items-wrapper');
    
    if( currDisplayed ){
        wrapperLi.removeClass('opened');
    }else{
        allWrappersLi.forEach((li)=>{
            li.removeClass('opened');
        });
        wrapperLi.addClass('opened');
    }
}

function toggleMobileServiceGroup(event){
    event.stopPropagation();
    var btnToggle = this;
    var groupClass = btnToggle.getAttribute('data-service');
    var services = document.querySelectorAll('#mobile-mmenu li.' + groupClass);
    var currDisplay = services[0].style.display;
    
    if( currDisplay == 'block' ){
        btnToggle.removeClass('opened');
    }else{
        btnToggle.addClass('opened');
    }

    services.forEach((li)=>{
        li.style.display = currDisplay == 'block' ? 'none' : 'block';
    });
}

function toggleEquipment(btn){
    var equipment = document.querySelector('section.all-equipment');

    equipment.style.display = equipment.style.display == 'block' ? 'none' : 'block';
    
    var btnText = equipment.style.display == 'block' ? btn.getAttribute('data-btn-hide-equipment') : btn.getAttribute('data-btn-show-equipment');
    log(btnText);
    btn.querySelectorAll('span').forEach((span) => {
        span.innerHTML = btnText;
    });
}

function gotoContactForm(){
    var form = document.querySelector('#contact-form');
    if( form ){
        var target = form.closest('section');
        target.style.display = 'block';
        window.scrollTo(0, target.cumulativeOffsetTop() - document.querySelector('nav').offsetHeight - 20);
    }
}




function accidentRecordCheckboxBoxBlur(){
    var accidentRecortCheckboxField = this;
    var accidentRecordFileFieldBox = document.querySelector('#accidentRecordFile');
    log(this);
    log(accidentRecordFileFieldBox);
    if( accidentRecortCheckboxField.value == '0' ){
        accidentRecordFileFieldBox.style.display = 'none';
        accidentRecordFileFieldBox.removeClass('required');
    }else{
        accidentRecordFileFieldBox.style.display = 'block';
        accidentRecordFileFieldBox.addClass('required');
    }
        
}

function addFileBox(){
    var fileBoxHolder = document.querySelector('#additional-file-html');
    var fileBoxContainer = document.querySelector('#additional-files');
    var btnBoxAddFile = document.querySelector('#btn-box-add-file');
    var numAdditionalFileBoxes = fileBoxContainer.querySelectorAll('.field-box').length;
    if( numAdditionalFileBoxes < 3){
        fileBoxContainer.append(htmlToElement(fileBoxHolder.innerHTML));
        var fieldBox = fileBoxContainer.querySelector('.field-box.file-box:last-child');
        log(fieldBox);

        // event binding
        var fileField = fieldBox.querySelector('input[type="file"]');
        var btnFileSelect = fieldBox.querySelector('.btn-file-select');
        btnFileSelect.addEventListener('click', browseFilesForSelection.bind(fileField));
        btnFileSelect.addEventListener('click', fieldBoxFocus.bind(fileField));
        
        var filenamesListField = fieldBox.querySelector('input.filenames-list');
        var fileField = fieldBox.querySelector('input[type="file"]');
        updateFilenameList.bind( filenamesListField )();
        filenamesListField.addEventListener('click', browseFilesForSelection.bind(fileField));
            
        fileField.addEventListener('change', uploadPublicFiles);
        fileField.addEventListener('focus', fieldBoxFocus);
        fileField.addEventListener('blur', fileBoxBlur);
        fileField.value = ''; // resets filefield onload to prevent browser's stored preselection

    }
    if( numAdditionalFileBoxes == ( 3 - 1) ){
        btnBoxAddFile.remove();
    }
    
}