// размеры рабочей области окна браузера
var window_width 	= window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
var window_height 	= window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;	


// ------------------------
// leftpad
// ------------------------
function leftpad(str, len, ch){
    str = String(str);
    var i = -1;
    if (!ch && ch !== 0) ch = ' ';
    len = len - str.length;
    while (++i < len) {
        str = ch + str;
    }
    return str;
  }



// ------------------------
// проверка массива на дубли значений
// ------------------------
var array_has_duplicate = function(array) {
    return array.some(function(value) {                            // .some will break as soon as duplicate found (no need to itterate over all array)
       return array.indexOf(value) !== array.lastIndexOf(value);   // comparing first and last indexes of the same value
    })
}


// ------------------------
// вырезаем из строки все переносы строк
// replace = "" | " "
// ------------------------
function remove_line_breaks(str, replace = ""){
    return str.replace(/\n/g, replace);
}

// ------------------------
// ресайзим картинку, если она большая
// ------------------------
function resize_image_base64(file, params = {}, callback = null){

	var max_size 	= params.max_size || 1600;	// ресайзим, если больше этого размера
	var min_size 	= params.min_size || 150; // меньше этого размера не принимаем
	var quality 	= params.quality || 0.9;

    var reader = new FileReader();
    reader.onload = function (e) {

        // создаем изображение
        var image = new Image();            
        image.onload = function (imageEvent){

            // оригинальные размеры картинки
            var width = image.width;
            var height = image.height;
			
			var orig_width = image.width;
            var orig_height = image.height;

			if(width < min_size || height < min_size){
				// в калбек функцию возвращаем картинку
				if (typeof callback === 'function') {
					callback({'status': 'err', 'error': 'Изображение слишком маленькое (необходимо > '+min_size+'px)'});
					return;
				}
			}

            // горизонтальная
            if (width > height) {
                if (width > max_size) {
                    height *= max_size / width;
                    width = max_size;
                }
            // вертикальная
            } else {
                if (height > max_size) {
                    width *= max_size / height;
                    height = max_size;
                }
            }

            // создаем канвас нужного размера
            var canvas = document.createElement('canvas');
            canvas.width = width;
            canvas.height = height;
            canvas.getContext('2d').drawImage(image, 0, 0, width, height);
            
            // уже ресайзнутая картинка в base64
            var image_raw = canvas.toDataURL('image/jpeg', quality);

            // в калбек функцию возвращаем картинку
            if (typeof callback === 'function') {
                //callback(image_raw);
				callback({
					'status': 'ok', 
					'orig_sizes': [orig_width, orig_height], 
					'result_sizes': [width, height], 
					'status': 'ok', 
					'image_raw': image_raw
				});
            }

            return image_raw;
        }

        image.src = e.target.result;
    }

    reader.readAsDataURL(file);

}


// ======================================	
// первую букву строки делаем заглавной
// ======================================
function firstToUp(string){
    return string.charAt(0).toUpperCase() + string.slice(1);
}

// ======================================	
// формирование падежных окончаний
// ======================================
function ending(number, e1, e2, e3) {

    var endingx;
    var num = number.toString();
    var x0 = num.slice(-2);

    if (x0 == '11' || x0 == '12' || x0 == '13' || x0 == '14') {
        endingx = e3;
    } else {
        var num = number.toString();
        var x = num.slice(-1);
        if (x == '1') {
            endingx = e1;
        }
        if (x == '2' || x == '3' || x == '4') {
            endingx = e2;
        }
        if (x == '5' || x == '6' || x == '7' || x == '8' || x == '9' || x == '0') {
            endingx = e3;
        }
    }
    return endingx;
}


// конвертировние base64 файла в blob
function DataURIToBlob(dataURI) {
	
	const splitDataURI = dataURI.split(',');
	const byteString = splitDataURI[0].indexOf('base64') >= 0 ? atob(splitDataURI[1]) : decodeURI(splitDataURI[1]);
	const mimeString = splitDataURI[0].split(':')[1].split(';')[0];
	const ia = new Uint8Array(byteString.length);

	for (let i = 0; i < byteString.length; i++)
		ia[i] = byteString.charCodeAt(i)
	return new Blob([ia], { type: mimeString })
  }


// установить курсор в конец элемента
function placeCaretAtEnd(el) {
    el.focus();
    if (typeof window.getSelection != "undefined"
            && typeof document.createRange != "undefined") {
        var range = document.createRange();
        range.selectNodeContents(el);
        range.collapse(false);
        var sel = window.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
    } else if (typeof document.body.createTextRange != "undefined") {
        var textRange = document.body.createTextRange();
        textRange.moveToElementText(el);
        textRange.collapse(false);
        textRange.select();
    }
}


// копировать строку в клипборд (устаревшее, но рабочее)
function fallbackCopyTextToClipboard(text) {
	var textArea = document.createElement("textarea");
	textArea.value = text;
	
	// Avoid scrolling to bottom
	textArea.style.top = "0";
	textArea.style.left = "0";
	textArea.style.position = "fixed";
  
	document.body.appendChild(textArea);
	textArea.focus();
	textArea.select();
  
	try {
	  	var successful = document.execCommand('copy');
	  	var msg = successful ? 'successful' : 'unsuccessful';
	  	//console.log('Fallback: Copying text command was ' + msg);
	} catch (err) {
	  	//console.error('Fallback: Oops, unable to copy', err);
	}
  
	document.body.removeChild(textArea);
  }

// копировать строку в клипборд
function copyTextToClipboard(text) {

	if (!navigator.clipboard) {
	  fallbackCopyTextToClipboard(text);
	  return;
	}
	navigator.clipboard.writeText(text).then(function() {
	  	//console.log('Async: Copying to clipboard was successful!');
	}, function(err) {
	  	//console.error('Async: Could not copy text: ', err);
	});
}



// -------------------------------------
// генерация hex-цвета из строки (имени юзера)
// -------------------------------------
function stringToColor(str) {
    
    var hash = 0;
    var color = '#';
    var i;
    var value;
    var strLength;

    // дефолтный цвет
    if(!str) {return color + '333333';}

    strLength = str.length;

    for (i = 0; i < strLength; i++) {
        hash = str.charCodeAt(i) + ((hash << 5) - hash);
    }

    for (i = 0; i < 3; i++) {
        value = (hash >> (i * 8)) & 0xFF;
        color += ('00' + value.toString(16)).substr(-2);
    }

    return color;
}


// -------------------------------------
// корректный json?
// -------------------------------------
function is_valid_json(str) {
    try {
        JSON.parse(str);
    } catch (e) {
        return false;
    }
    return true;
}


// -------------------------------------
// проверка устройства (наличие класса body.mobile)
// -------------------------------------
function is_mobile() {
    return $('body').hasClass('mobile');
}

// обертка над функцией strip_tags() + доп очистка атрибутов тегов
function html_strip_tags(html, allowed, remove_attr = true){
    
    html = strip_tags(html, allowed);

	// обрезаем пробелы по краям
    html = html.trim();

    // вырезаем все атрибуты тегов
    if(remove_attr){
        html = html.replace(/\s*\S*\="[^"]+"\s*/gm, "");
    }

    return html;
}


// очистка от тегов, кроме разрешенных
// strip_tags(text, '<br><b><strong><i><u><s><strike><mark>');
function strip_tags(input, allowed) {
    //  discuss at: http://phpjs.org/functions/strip_tags/
    // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // improved by: Luke Godfrey
    // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    //    input by: Pul
    //    input by: Alex
    //    input by: Marc Palau
    //    input by: Brett Zamir (http://brett-zamir.me)
    //    input by: Bobby Drake
    //    input by: Evertjan Garretsen
    // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // bugfixed by: Onno Marsman
    // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // bugfixed by: Eric Nagel
    // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // bugfixed by: Tomasz Wesolowski
    //  revised by: Rafał Kukawski (http://blog.kukawski.pl/)
    //   example 1: strip_tags('<p>Kevin</p> <br /><b>van</b> <i>Zonneveld</i>', '<i><b>');
    //   returns 1: 'Kevin <b>van</b> <i>Zonneveld</i>'
    //   example 2: strip_tags('<p>Kevin <img src="someimage.png" onmouseover="someFunction()">van <i>Zonneveld</i></p>', '<p>');
    //   returns 2: '<p>Kevin van Zonneveld</p>'
    //   example 3: strip_tags("<a href='http://kevin.vanzonneveld.net'>Kevin van Zonneveld</a>", "<a>");
    //   returns 3: "<a href='http://kevin.vanzonneveld.net'>Kevin van Zonneveld</a>"
    //   example 4: strip_tags('1 < 5 5 > 1');
    //   returns 4: '1 < 5 5 > 1'
    //   example 5: strip_tags('1 <br/> 1');
    //   returns 5: '1  1'
    //   example 6: strip_tags('1 <br/> 1', '<br>');
    //   returns 6: '1 <br/> 1'
    //   example 7: strip_tags('1 <br/> 1', '<br><br/>');
    //   returns 7: '1 <br/> 1'

    allowed = (((allowed || '') + '')
    .toLowerCase()
    .match(/<[a-z][a-z0-9]*>/g) || [])
    .join(''); // making sure the allowed arg is a string containing only tags in lowercase (<a><b><c>)
    
    var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
    commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;

    return input.replace(commentsAndPhpTags, '')
    .replace(tags, function($0, $1) {
        return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '';
    });
}


// -------------------------------------
// валидация форм внутри модалок
// -------------------------------------
function modal_validate($parent){

	var is_valid = true;

	// обязательное поле (проверяем на пустоту)
	$('[required]', $parent).each(function(i, elem){

		var elem = $(this);

		// wysiwyg-editor (div)
		if(elem.hasClass('editor')){

			if(elem.text()==''){
				elem.addClass('error');				
				is_valid = false;
			}else{
				elem.removeClass('error');
			}

		// textarea, input, select
		}else{

			if(elem.val()==''){
				elem.addClass('error');
				is_valid = false;
			}else{
				elem.removeClass('error');
			}

		}

		
	});

	// сбрасываем класс ошибки при изменении поля
	$parent.on('input focus', '[required]', function(){
		if($(this).val()!='' || $(this).text()!=''){
			$(this).removeClass('error');
		}
	});

	return is_valid;
}




// READY
document.addEventListener('DOMContentLoaded', function (){
	
	// устройства до какой ширины считаем "мобильными"
	var mobile_window_width = 1000;

	// ======================================
	// добавляем в тег body класс body.mobile
	// ======================================
	if(window_width < mobile_window_width){
		document.getElementsByTagName('body')[0].classList.add("mobile");
	}

	// при ресайзе обновляем класс
	window.onresize = function(event) {
		
		window_width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
		
		if(window_width < mobile_window_width){		
			document.getElementsByTagName('body')[0].classList.add("mobile");
			
		}else{		
			document.getElementsByTagName('body')[0].classList.remove("mobile");
		}
	};

	
	// инициализируем все модальные окна 'zmodal'
	$('.zmodal_btn').zmodal();

	$('.autosize').autosize(); 


	// ----------------------------
	// закрытие выпадушек по эскейпу
	// ----------------------------
	$(document).keydown(function(event) {
		if (event.keyCode == 27) {    
			// закрываем выпадушки       
			$(".top_menu_role_select").removeClass('is_expand');
			$(".top_menu_select").removeClass('is_expand');
		}
	});

	// ----------------------------
	// закрытие выпадушек по клику вне
	// ----------------------------
	$(document).on('click', function(event){  
		             
		// закрываем выпадушки  
		if(!$(event.target).closest('.top_menu_role').length && !$(event.target).is('.top_menu_role')) {
			$(".top_menu_role_select").removeClass('is_expand');
		}   
		
		// закрываем выпадушки  
		if(!$(event.target).closest('.top_menu').length && !$(event.target).is('.top_menu')) {			
			$(".top_menu_select").removeClass('is_expand');
		}         
	});
    
});





// ------------------------
// смена табов в модалках (курса, урока)
// ------------------------
$(document).on('click', '[data-tabs-btn]', function(e){

    e.preventDefault();
    
    var wr = $(this).closest('[data-tabs-wr]');
    var current_tab_name = $(this).data('tab');
    
    $('[data-tabs-btn]', wr).removeClass('is_active');
    $(this).addClass('is_active');

    $('[data-tabs-content]', wr).removeClass('is_active');
    $('[data-tabs-content][data-tab="'+current_tab_name+'"]', wr).addClass('is_active');

});


// ======================================
// Диалог с подтверждением
// ======================================
function confirmation(desc){
	if(confirm(desc)){return true;}else{return false;}
}


// поменять местами элементы
//  $('.left').swap('.right');
//  $elem1.swap($elem2);
jQuery.fn.swap = function(b) {
	b = jQuery(b)[0];
	var a = this[0],
		a2 = a.cloneNode(true),
		b2 = b.cloneNode(true),
		stack = this;

	a.parentNode.replaceChild(b2, a);
	b.parentNode.replaceChild(a2, b);

	stack[0] = a2;
	return this.pushStack( stack );
};


// полифил: возможность искать индекс элемента по значению
if (!Array.prototype.indexOf){
  Array.prototype.indexOf = function(elt /*, from*/)
  {
    var len = this.length >>> 0;
    var from = Number(arguments[1]) || 0;
    from = (from < 0)
         ? Math.ceil(from)
         : Math.floor(from);
    if (from < 0)
      from += len;
    for (; from < len; from++)
    {
      if (from in this &&
          this[from] === elt)
        return from;
    }
    return -1;
  };
}

// -----------------------------------------
// строка содержит кириллические символы?
// -----------------------------------------
function is_cyrillic(text) {
    return /[а-яё]/i.test(text);
}

// -----------------------------------------
// вырезаение всех html тегов из строки
// -----------------------------------------
function stripHtml(html){
    let tempHolder = document.createElement("DIV");
    tempHolder.innerHTML = html;
    return tempHolder.textContent || tempHolder.innerText || "";
 }


// -----------------------------------------
// рандомная строка
// -----------------------------------------
function gen_random_str(length = 6){
    
    var abc = "abcdefghijklmnopqrstuvwxyz0123456789";
    var str = "";
    while (str.length < length){
        str += abc[Math.floor(Math.random() * abc.length)];
    }
    return str;    
}


// -----------------------------------------
// рандомное целое число
// -----------------------------------------
function get_random_int(min, max) {
    return Math.floor(Math.random() * (max - min)) + min;
}

// -----------------------------------------
// [1,2,3,4].max();
// -----------------------------------------
Array.prototype.max = function() {
    return Math.max.apply(null, this);
};
  
// -----------------------------------------
// [1,2,3,4].min();
// -----------------------------------------
Array.prototype.min = function() {
    return Math.min.apply(null, this);
};

  


// -----------------------------------------
// определение арабского языка
// чтобы преключить направление письменности
// -----------------------------------------
function is_arabic_str(string){
    return /[\u0600-\u06FF]/.test(string);
}


function change_elem_lang_direction(elem, dir){
    
	if(dir=='rtl'){
        $(elem).attr('dir', 'rtl');
    }else{
        $(elem).attr('dir', 'ltr');
    }

}


// -----------------------------------------
// jquery плагин для перемешивание элементов внутри родителя
// $('.elems').shuffle();
// -----------------------------------------
(function(d){d.fn.shuffle=function(c){c=[];return this.each(function(){c.push(d(this).clone(true))}).each(function(a,b){d(b).replaceWith(c[a=Math.floor(Math.random()*c.length)]);c.splice(a,1)})};d.shuffle=function(a){return d(a).shuffle()}})(jQuery);

// -----------------------------------------
// перемешивание массива v2 (или такая же?)
// -----------------------------------------
function shuffle(array) {
	let currentIndex = array.length,  randomIndex;
	// While there remain elements to shuffle.
	while (currentIndex > 0) {
		// Pick a remaining element.
		randomIndex = Math.floor(Math.random() * currentIndex);
		currentIndex--;
		// And swap it with the current element.
		[array[currentIndex], array[randomIndex]] = [
		array[randomIndex], array[currentIndex]];
	}
	return array;
}

// -----------------------------------------
// перемешивание массива
// -----------------------------------------
function shuffleArray(array) {
    for (let i = array.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
    }
}

// -----------------------------------------
//поменять местами два елемента
// пример: $('.col1').swapWith('.col2');
// -----------------------------------------
jQuery.fn.swapWith = function(to) {
    return this.each(function() {
        var copy_to = $(to).clone(true);
        var copy_from = $(this).clone(true);
        $(to).replaceWith(copy_from);
        $(this).replaceWith(copy_to);
    });
};


// -----------------------------------------
// кастомный <select>
// -----------------------------------------
function selectbox_init(el){

	var options = [];
	var	option = el.children('option');
	var customSelect;

	el.hide(); // скрываем select
	
	// переносим в массив все значения <option>
	$(option).each(function(){ 
		options.push($(this).html());
	});

	// создаем кастомный селект
	el.after('<div class="selectbox" data-selected-value="' + options[0] + '">');
	customSelect = el.siblings('.selectbox');

	// добавляем блок с опциями
	$(customSelect).append('<div class="selected-option"><span>' + options[0] + '</span>');
	$(customSelect).children('.selected-option').append('<div class="selectbox_options">');

	// перебираем все значения
	for(var i = 1; i < options.length; i++) {
		//console.log(options[i]);
		$(customSelect).find('.selectbox_options').append('<div data-value="' + options[i] + '">' + options[i] + '</div>');
	}
	
	// Click action & synchronization with origin select for submitting form     
	$(customSelect).click(function(){

		$(this).toggleClass('open');
		$('.selectbox_options',this).toggleClass('open');

		// закрываем другие селекты на странице
		$('.selectbox').not($(this)).find('.selectbox_options').removeClass('open'); 

	});


	$(customSelect).find('.selectbox_options div').click(function(){

		var selection = $(this).text();
		var dataValue = $(this).attr('data-value');
		var selected = $(customSelect).find('.selected-option span').text(selection);
		for(var i = 1; i < option.length; i++) {
			if($(option[i]).text() === selected.text()) {
				$(option[i]).attr('selected', 'true');
				$(option[i]).siblings().removeAttr('selected');
			}
		};

		el.trigger('change');

		$(customSelect).attr('data-selected-value',dataValue);
	});
};



// ======================
// инициализация "number_selector" 
// пример: <input class="number" type="text" value="3" data-min="1" data-max="9">
// ======================
function number_selector_init($elems){

    $elems.each(function(){

        var $el = $(this);
   
        $el.attr('disabled', 'disabled');
        $el.wrap('<div class="number_selector_wr"/>');
        var $el_wr = $el.closest('.number_selector_wr');
        $el_wr.append('<button data-plus></button>');
        $el_wr.prepend('<button data-minus></button>');

        if($el.val() == $el.data('min')){$('[data-minus]', $el_wr).attr('disabled', 'disabled');}
        if($el.val() == $el.data('max')){$('[data-plus]', $el_wr).attr('disabled', 'disabled');}

        $('button', $el_wr).off('click').on('click', function(e){

            e.preventDefault();
            var wr = $(this).closest('.number_selector_wr');
            var input = $('input', wr);
            var min = +input.data('min');
            var max = +input.data('max');
            var val = +input.val();
            var btn_plus = $('[data-plus]', wr);
            var btn_minus = $('[data-minus]', wr);
            var action = $(this).is('[data-plus]') ? '+' : '-';        

            if(action=='+'){
                btn_minus.removeAttr('disabled');
                if((val+1) <= max){
                    val++;
                    input.val(val);
                }

                if(val == max){btn_plus.attr('disabled', 'disabled');}

            }else if(action=='-'){
                btn_plus.removeAttr('disabled');
                if((val-1) >= min){
                    val--;
                    input.val(val);
                }

                if(val == min){btn_minus.attr('disabled', 'disabled');}

            }

        });

    });

}


// инициализируем тултипы
// <span data-tip="тест подсказки"></span>
function tippy_init(interactive = true, maxWidth = 350){

    tippy('[data-tip]', {
        delay: [200, 200],
        interactive: interactive,
        maxWidth: maxWidth,
        content: (reference) => reference.dataset.tip
    });
}