//PREFIXES
//additional_ - additional code
//replace_ - replace standard code
//if_ - replace standard code if returns true
//custom_ - custom function to call inside custom theme object



var poip_product_default = function(params, $product_container) {
	this.params = params || poip_params; // "|| poip_params" for compatibility with previously created adaptations to themes
	
	this.stored_image_elements_by_collections = [];
	if ( $product_container ) {
		this.$product_container = $product_container;
	}
	this.init();
	if ( typeof(this.custom_init) == 'function') {
		this.custom_init();
	}
};

poip_product_default.prototype.each = function(collection, fn){
	for ( var i_item in collection ) {
		if ( !collection.hasOwnProperty(i_item) ) continue;
		if ( fn(collection[i_item], i_item) === false ) {
			return;
		}
	}
};

poip_product_default.prototype.init = function(call_cnt) {
	let this_object = this;
	
	call_cnt = call_cnt || 1;
	//if ( typeof(jQuery) == 'undefined' ) { // try to wait for jquery initialization
	//	if ( call_cnt < 100 ) {
	//		setTimeout(function(){
	//			this_object.init(call_cnt+1);
	//		}, 100);
	//	}
	//	return; // no jquery
	//}
	
	this_object.set_visible_images_timer_id = false;
	this_object.set_visible_images_first_call = true;
	this_object.update_zoom_image_timer_id = false;
	this_object.function_event_option_value_select_is_still_working = false;
	this_object.function_event_option_value_select_timer_id = 0;
	
	// determine option name prefix
	this_object.option_prefix = "option";
	if (this_object.getElement('[name^="option_oc["]').length) {
		this_object.option_prefix = "option_oc";
	}
	this_object.option_prefix_length = this_object.option_prefix.length;
	
	// usage of colorbox
	this_object.use_refresh_colorbox = this_object.useColorboxRefreshing();
	
			
	// get standard main image data		
	this_object.std_href = typeof(this_object.params.poip_std_href) != 'undefined' ? this_object.params.poip_std_href : this_object.getMainImage().closest('a').attr('href');
	this_object.std_src = typeof(this_object.params.poip_std_src) != 'undefined' ? this_object.params.poip_std_src : this_object.getMainImage().attr('src');
	
	if ( typeof(this_object.additional_setMainImageInitialHref) == 'function' ) {
		this_object.additional_setMainImageInitialHref();
	}
			
	// main product image may be included to the list, we should take it into account
	if ( typeof(this_object.additional_useAddInitialMainImageToPoipImages) != 'function' || this_object.additional_useAddInitialMainImageToPoipImages() ) {
		let images_popup_reordered = [];
		let new_images_are_added = false;
		this_object.getAdditionalImagesBlock().find('a').each(function() {
			let img_href = '';
			if ( $(this).attr('data-zoom-image') ) {
				img_href = $(this).attr('data-zoom-image');
			} else if ( $(this).attr('data-image') ) {
				img_href = $(this).attr('data-image');
			} else if ( $(this).attr('href') && $(this).attr('href').substr(0,1) != "#" ) {
				img_href = $(this).attr('href');
			}
			let img_src = $(this).find('img:first').attr('src');
			if (img_href && img_src) {
				let poip_img = this_object.getImageBySrc(img_href);
				if ( !poip_img ) {
				//if ( !this_object.getImageBySrc(img_href, 'popup') && !this_object.getImageBySrc(img_href, 'main') && !this_object.getImageBySrc(img_src, 'thumb') ) {
					this_object.params.images.unshift({
						product_id:this_object.params.product_id,
						product_image_id:["-1"],
						popup:"",
						main:"",
						thumb:"",
						product_sort_order:-1,
					});
					poip_img = this_object.params.images[0];
					poip_img.popup = img_href;
					poip_img.main = img_href;
					poip_img.thumb = img_src;
					new_images_are_added = true;
				}
				images_popup_reordered.push(poip_img.popup);
			}
		});
		if ( new_images_are_added ) { // necessary to use the sort order like it was on the page
			this_object.each(this_object.params.images, function(poip_img){
				if ( $.inArray(poip_img.popup, images_popup_reordered) == -1 ) {
					images_popup_reordered.push(poip_img.popup);
				}
			});
			let new_poip_images = [];
			this_object.each(images_popup_reordered, function(popup){
				poip_img = this_object.getImageBySrc(popup);
				new_poip_images.push(poip_img);
			});
			this_object.params.images = new_poip_images;
		}
	}
	
	let ready_callback = function(){
		this_object.refreshPopupImages();
		if ( typeof(this_object.additional_documentReady) == 'function' ) {
			this_object.additional_documentReady();
		}
		
		this_object.setDefaultOptionsByURL();
	};
	
	if ( typeof(this_object.additional_useOldOCStyleInit) == 'function' && this_object.additional_useOldOCStyleInit() ) {
	
		// old style
		
		this_object.checkEventsForSelects(true);
		
		this_object.getElement('div.options').click(function(){
			this_object.checkEventsForSelects();
		});
		
		// more compatible
		this_object.getContainer().on('change', 'input:radio[name^="'+this_object.option_prefix+'["]', function() {
			this_object.eventOptionValueSelect(this);
		});
		
		if ( typeof(this_object.additional_makeInitActions) == 'function' ) {
			this_object.additional_makeInitActions();
		}
		
		this_object.getElement("input[type=checkbox][name^="+this_object.option_prefix+"\\[]").each(function () {
			$(this).change(function(){
				this_object.eventOptionValueSelect(this);
			});
		});
		
		if (this_object.params.poip_settings.img_hover) {
			if ( typeof(this_object.replace_turnOnAdditionalImagesMouseover) == 'function' ) {
				this_object.replace_turnOnAdditionalImagesMouseover();
			} else { // standard way
				// more compatible
				this_object.getAdditionalImagesBlock().on('mouseover', 'a' ,function(){
					this_object.eventAdditionalImageMouseover(this);
				});
			}
		}

		
		$().ready(function(){
			
			if ( this_object.params.poip_product_option_ids.length ) {
				this_object.changeAvailableImages(this_object.params.poip_product_option_ids[0], ready_callback);
				//ready_callback();
			} else {
				this_object.setVisibleImages(this_object.getBasicVisibleImages(), ready_callback);
			}
			
		});
	} else {

		// new style
		if ( $.magnificPopup ) {
			this_object.getAdditionalImagesBlock().find('a').each(function(){
				if ( this_object.anchorIsVideo( $(this) ) ) {
				//if ( this_object.hrefIsVideo( $(this).attr('href') ) ) {
					if ( !$(this).hasClass('mfp-iframe') ) {
						$(this).addClass('mfp-iframe');
					}
				}
			});
		}
		
		this_object.getElement('#product, .product-options, .product-info .options, .product-info, #product_quickw, #option-select, #popup-product, .option_products, #view-form, [id^="product"][id$="OptionBlock"]').on('change', 'select[name^="'+this_object.option_prefix+'["], input[type=radio][name^="'+this_object.option_prefix+'["], input[type=checkbox][name^="'+this_object.option_prefix+'["]', function(){
			this_object.eventOptionValueSelect(this);
		});
		
		if ( typeof(this_object.additional_makeInitActions) == 'function' ) {
			this_object.additional_makeInitActions();
		}
		
		if (this_object.params.poip_settings.img_hover) {
			if ( typeof(this_object.replace_turnOnAdditionalImagesMouseover) == 'function' ) {
				this_object.replace_turnOnAdditionalImagesMouseover();
			} else { // standard way
				// more compatible
				this_object.getAdditionalImagesBlock().on('mouseover', 'a' ,function(){
					this_object.eventAdditionalImageMouseover(this);
				});
			}
		}
		
		$().ready(function(){
			
			// fix of a kind of autoupdate module removing first empty values of options
			if ( this_object.getElement('select[name^="'+this_object.option_prefix+'["]').length && this_object.getElement('select[name^="'+this_object.option_prefix+'["] option[value=""]').length == 0 ) {
				this_object.externalOptionChange();
			}
		
			if ( this_object.params.poip_product_option_ids.length ) {
				this_object.changeAvailableImages(this_object.params.poip_product_option_ids[0], ready_callback);
				//ready_callback();
			} else {
				this_object.setVisibleImages(this_object.getBasicVisibleImages(), ready_callback);
			}
			
		});
	}
};

// for better code transferring with the module version for opencart 3.x
poip_product_default.prototype.getElement = function(selector) {
	let this_object = this;
	if ( this_object.$product_container ) {
		return this_object.$product_container.is(selector) ? this_object.$product_container : this_object.$product_container.find(selector);
	} else {
		return $(selector);
	}
};

poip_product_default.prototype.getContainer = function() {
	let this_object = this;
	if ( this_object.$product_container ) {
		return this_object.$product_container;
	} else {
		return $(document);
	}
};

poip_product_default.prototype.getProductOptionIdByName = function(name) {
	let this_object = this;
	return name.substr(this_object.option_prefix_length+1, name.indexOf(']')-(this_object.option_prefix_length+1) );
};

// checkbox_variant : 1 - without checkbox, 2 - only checkbox
poip_product_default.prototype.getSelectedOptionValues = function(checkbox_variant, product_option_id) {
	let this_object = this;

	let values = [];
	
	let select_string = "";
	let name_filter = '[name^="'+this_object.option_prefix+'["]';
	if (!checkbox_variant || checkbox_variant==1) {
		select_string += 'select, :radio:checked';
	}
	if (!checkbox_variant || checkbox_variant==2) {
		select_string += (select_string=='' ? '' : ', ') + ':checkbox:checked';
	}
	
	this_object.getElement(select_string).filter(name_filter).each(function () {
		let current_product_option_id = this_object.getProductOptionIdByName($(this).attr('name'));
		if ( (!product_option_id && $.inArray(current_product_option_id, this_object.params.poip_product_option_ids) != -1) || (product_option_id && product_option_id == current_product_option_id) ) {
			if ($(this).val()) {
				values.push($(this).val());
			}
		}
	});
	return values;
};

poip_product_default.prototype.addToArrayIfNotExists = function(val, arr) { // object always by link
	if ( $.inArray(val, arr) == -1 ) {
		arr.push(val);
	}
};

poip_product_default.prototype.getBasicVisibleImages = function(all_pov_images, selected_values) {
	let this_object = this;
	
	// images which should be visible before options filter applying
	var global_visible_images = [];
	selected_values = selected_values || this_object.getSelectedOptionValues();
	this_object.each(this_object.params.images, function(poip_img){
	
		if ( poip_img.product_image_id || !poip_img.product_option_id || !poip_img.product_option_id.length ) { // std additional image
			this_object.addToArrayIfNotExists(poip_img.popup, global_visible_images);
		} else {
			this_object.each(poip_img.product_option_id, function(product_option_id){
				
				// check for "no value" (display the image if its option is not selected)
				if ( poip_img.product_option_value_id && poip_img.product_option_value_id.length && $.inArray(-product_option_id, poip_img.product_option_value_id) != -1 ) {
					this_object.addToArrayIfNotExists(poip_img.popup, global_visible_images);
				} else if (this_object.params.option_settings[product_option_id].img_use == 1 || all_pov_images) { // incl images of all values
					this_object.addToArrayIfNotExists(poip_img.popup, global_visible_images);
				} else if (this_object.params.option_settings[product_option_id].img_use == 2) { // incl images of the selected options only
					for (var j=0; j<selected_values.length; j++) {
						if ($.inArray(selected_values[j], poip_img.product_option_value_id)!=-1) {
							this_object.addToArrayIfNotExists(poip_img.popup, global_visible_images);
						}
					}
				}
			});
		}
	});
	
	if ( typeof(this_object.additional_addMainImageInitialHrefToArray) == 'function' ) {
		global_visible_images = this_object.additional_addMainImageInitialHrefToArray(global_visible_images);
	}
	
	return global_visible_images;
};

poip_product_default.prototype.getIntersectionOfArrays = function(arr1, arr2) {
	let this_object = this;
	
	var match = [];
	$.each(arr1, function (i, val1) {
		if ($.inArray(val1, arr2) != -1 && $.inArray(val1, match) == -1) {
			match.push(val1);
		}
	});
	
	return match;
};

poip_product_default.prototype.getConcatenationOfArraysUnique = function(arr1, arr2) {
	var arr = arr1.slice();
	for ( var i_arr2 in arr2 ) {
		var value = arr2[i_arr2];
		if ( $.inArray(value, arr) == -1 ) {
			arr.push(value);
		}
	}
	return arr;
};

poip_product_default.prototype.getDifferenceFromFirstArray = function(arr1, arr2) {
	let this_object = this;
	
	let arr = [];
	this_object.each(arr1, function(value1){
		if ( $.inArray(value1, arr2) == -1 ) {
			arr.push(value1);
		}
	});
	
	return arr;
};

// selected_options - not required, just for better performance
poip_product_default.prototype.getBasicImagesForMainImage = function(selected_options) {
	let this_object = this;
	
	var images_for_main_image = this_object.getBasicVisibleImages(true, selected_options);
	if ( this_object.std_href ) {
		images_for_main_image = this_object.getConcatenationOfArraysUnique([this_object.std_href], images_for_main_image);
		//if ( $.inArray(this_object.std_href, images_for_main_image) == -1 ) {
		//	images_for_main_image = [this_object.std_href].concat(images_for_main_image);
		//}
	}
	return images_for_main_image;
};

poip_product_default.prototype.getImagesForProductOptionValueIds = function(pov_ids) {
	let this_object = this;
	
	var images = [];
	for (var i_image in this_object.params.images) {
		var poip_img = this_object.params.images[i_image];
		if (poip_img.product_option_value_id && poip_img.product_option_value_id.length) {
			for (var i_pov_ids in pov_ids) {
				var product_option_value_id = pov_ids[i_pov_ids];
				if ($.inArray(product_option_value_id, poip_img.product_option_value_id) !== -1 && $.inArray(poip_img.popup, images) == -1 ) {
					images.push(poip_img.popup);
				}
			}
		}
	}
	return images;
};

poip_product_default.prototype.getImagesForNotSelectedProductOption = function(product_option_id) {
	let this_object = this;
	
	var images = [];
	for (var i_image in this_object.params.images) {
		var poip_img = this_object.params.images[i_image];
		if ( poip_img.product_option_value_id && poip_img.product_option_value_id.length ) {
			// -product_option_id is used for images checked to be shown when option is not selected
			if ( $.inArray(-product_option_id, poip_img.product_option_value_id) != -1 ) {
				images.push(poip_img.popup);
			}
		}
	}
	return images;
};

poip_product_default.prototype.getImagesNotLinkedToProductOption = function(product_option_id) {
	let this_object = this;
	
	var images = [];
	for (var i_image in this_object.params.images) {
		var poip_img = this_object.params.images[i_image];
		
		if ( !poip_img.product_option_id || $.inArray(product_option_id, poip_img.product_option_id) == -1 ) {
			if ( $.inArray(poip_img.popup, images) == -1 ) {
				images.push(poip_img.popup);
			}
		}
	}
	return images;
};

poip_product_default.prototype.getAdditionalImagesToDisplay = function(return_object_including_for_main_image) {
	let this_object = this;
	
	let selected_options = this_object.getSelectedOptionValues();
	
	var global_visible_images = this_object.getBasicVisibleImages(false, selected_options);
	var current_visible_images = global_visible_images.slice();
	
	var images_for_main_image = this_object.getBasicImagesForMainImage(selected_options);
	var all_images_of_selected_option_values = [];
	
	this_object.each(this_object.params.poip_product_option_ids, function(current_product_option_id){
		var current_product_option_selected_values = this_object.getSelectedOptionValues(0, current_product_option_id);
		
		var images_to_show = [];
		if ( current_product_option_selected_values.length ) {
			images_to_show = this_object.getImagesForProductOptionValueIds(current_product_option_selected_values);
		} else {
			images_to_show = this_object.getImagesForNotSelectedProductOption(current_product_option_id);
		}
		
		if ( images_to_show.length ) {
			if ( this_object.params.option_settings[current_product_option_id].img_use ) {
				if ( this_object.params.option_settings[current_product_option_id].img_limit == 1 ) {	 // intersection
					current_visible_images = this_object.getIntersectionOfArrays(current_visible_images, images_to_show);
				} else if ( this_object.params.option_settings[current_product_option_id].img_limit == 2 ) {	 // intersection with all images not linked to the option
					// add all images not linked with the selected options
					var images_to_show_with_other_images = this_object.getConcatenationOfArraysUnique(images_to_show, this_object.getImagesNotLinkedToProductOption(current_product_option_id) );
					current_visible_images = this_object.getIntersectionOfArrays(current_visible_images, images_to_show_with_other_images);
				} else { // addition
					current_visible_images = this_object.getConcatenationOfArraysUnique(current_visible_images, images_to_show);
				}
				all_images_of_selected_option_values = this_object.getConcatenationOfArraysUnique(all_images_of_selected_option_values, images_to_show);
			}
			if ( this_object.params.option_settings[current_product_option_id].img_change ) {
				images_for_main_image = this_object.getIntersectionOfArrays(images_for_main_image, images_to_show);
			}
		}
	});
	
	if (current_visible_images.length == 0) {
		// no images suitable for all selected option values at the same time
		// try to use just an amount of images suitable for every selected option value
		current_visible_images = this_object.getIntersectionOfArrays(global_visible_images, all_images_of_selected_option_values);
		if (current_visible_images.length == 0) {
			// still no images? use global
			current_visible_images = global_visible_images;
		}
	}
	if ( return_object_including_for_main_image ) {
		return {
			'images': current_visible_images,
			'main': images_for_main_image,
		};
	} else {
		return current_visible_images;
	}
	
};

poip_product_default.prototype.changeAvailableImages = function(product_option_id, callback, option) {
	let this_object = this;
	
	if ($.inArray(product_option_id, this_object.params.poip_product_option_ids)==-1) {
		return;
	}
	
	let current_visible_images_lists = this_object.getAdditionalImagesToDisplay(true);
	let images_for_main_image = current_visible_images_lists.main;
	if ( images_for_main_image.length == 0 ) { // if there is no image suitable for all selected options
		var selected_pov_ids = this_object.getSelectedOptionValues(0, product_option_id);
		if ( selected_pov_ids.length ) { // try to get images for the currently selected option only
			images_for_main_image = this_object.getImagesForProductOptionValueIds(selected_pov_ids);
		}
		if ( images_for_main_image.length == 0 ) { // still no image? get basic
			images_for_main_image = this_object.getBasicImagesForMainImage();
		}
		
		//images_for_main_image = this_object.getBasicVisibleImages(true);
	}
	
	this_object.setVisibleImages(current_visible_images_lists.images, function(){
		
		
		(function(images_to_show){
			
			let product_option_value_id = option ? option.value : 0;
			
			images_to_show = this_object.sortImagesBySelectedOptions(images_to_show);
			
			// update main image
			if ( this_object.params.option_settings[product_option_id] && this_object.params.option_settings[product_option_id].img_change ) {
				
				let main_img_urls = this_object.getImageUrlsToDisplayAsMain(product_option_value_id, images_to_show);
				if ( main_img_urls && main_img_urls.main && main_img_urls.popup ) {
					
					this_object.setMainImage(main_img_urls.main, main_img_urls.popup);
					this_object.updateZoomImage(main_img_urls.popup);
					if ( this_object.params.poip_update_url ) {
						let poip_img = this_object.getImageBySrc(main_img_urls.popup);
						if ( poip_img ) {
							this_object.setCurrentUrlByImage(poip_img.image);
						}
					}
				}
			}
		})(images_for_main_image);
		
		if ( callback ) {
			callback(images_for_main_image);
		}
	});
	
	return images_for_main_image;
};

poip_product_default.prototype.refreshPopupImages = function() {
	let this_object = this;
	
	if ( typeof(this_object.replace_refreshPopupImages) == 'function' ) {
		return this_object.replace_refreshPopupImages();
	}

	if ( typeof(this_object.if_refreshPopupImages) == 'function' ) {
		if ( this_object.if_refreshPopupImages() ) {
			return;
		}
	}
	
	if (!this_object.params.poip_settings.img_gal) {
		if ( this_object.getElement('li.image-additional').length ) { // OC 2.0 new-style default
			
			// exclude main image from gallery (main image should be present in additional images already)
			this_object.getElement('.thumbnails').magnificPopup({
				type:'image',
				delegate: '.image-additional a',
				gallery: {
					enabled:true
				}
			});
			this_object.getMainImage().off('click');
			this_object.getMainImage().on('click', function(event) {
				this_object.eventMainAImgClick(event, this);
			});
		}
		return;
	}
	
	
	if ( typeof(this_object.if_refreshPopupImagesBody) == 'function' && this_object.if_refreshPopupImagesBody() ) {
		// nothing
	} else if ( this_object.getElement('li.image-additional').length ) { // OC 2.0 new-style default
		// OC 2.0 DEFAULT instead of colorbox in OC 1.X
		
		if ( typeof($.magnificPopup) != 'undefined' ) {
			this_object.getElement('.thumbnails').magnificPopup({
				type:'image',
				delegate: '.image-additional a:visible',
				gallery: {
					enabled:true
				}
			});
		}
		
		this_object.getMainImage().off('click');
		this_object.getMainImage().on('click', function(event) {
			this_object.eventMainAImgClick(event, this);
		} );
		
	} else { // OC 1.X and OC 2.0 old-style themes
		this_object.refreshColorboxImages();
	}
};

poip_product_default.prototype.eventMainAImgClick = function(event, element) {
	let this_object = this;
	
	if ( typeof(this_object.if_eventMainAImgClick) == 'function' ) {
		var if_result = this_object.if_eventMainAImgClick(event, element);
		if ( if_result ) {
			return if_result;
		}
	}
	
	event.stopPropagation();
	event.preventDefault();
	
	var main_href = $(element).parent().attr('href');
	this_object.getAdditionalImagesBlock().find('a[href="'+main_href+'"]:first').click();
};

poip_product_default.prototype.getOwnProductImages = function() {
	let this_object = this;
	
	
	let poip_imgs = [];
	this_object.each(this_object.params.images, function(poip_img){
		if ( typeof(poip_img.product_image_id) != 'undefined' ) { // main or additional image
			poip_imgs.push(poip_img);
			//this_object.addToArrayIfNotExists(poip_img.popup, images);
		}
	});
	poip_imgs.sort( function(a,b){
		if ( typeof(a.sort_order_product_image) != 'undefined' && typeof(b.sort_order_product_image) != 'undefined' ) {
			if ( a.sort_order_product_image < b.sort_order_product_image ) return -1;
			if ( a.sort_order_product_image > b.sort_order_product_image ) return 1;
		}
		return 0;
	} );
	let images = [];
	this_object.each(poip_imgs, function(poip_img){
		this_object.addToArrayIfNotExists(poip_img.popup, images);
	});
	
	return images;
};

poip_product_default.prototype.sortImagesBySelectedOptions = function(p_images) {
	let this_object = this;
	
	let images = [];
	
	if ( this_object.params.poip_settings.options_images_edit == 1 ) { // use basic sort order (set on the Image tab)
		
		this_object.each(this_object.params.images, function(poip_img){
			if ( $.inArray(poip_img.popup, p_images) != -1 && $.inArray(poip_img.popup, images) == -1 ) {
				images.push(poip_img.popup);
			}
		});
		
	} else { // use option sort order (from the Option tab)
	
		let pov_ids = this_object.getSelectedOptionValues();
		let pov_images = this_object.getImagesByPOVIds(pov_ids, 'popup');
		let own_images_not_linked_with_selected_options = this_object.getDifferenceFromFirstArray(this_object.getOwnProductImages(), pov_images);
		images = this_object.getIntersectionOfArrays( own_images_not_linked_with_selected_options, p_images);
		
		if ( this_object.params.poip_settings.img_use == 1 ) { // all option images to additional product images
		
			this_object.each(this_object.params.poip_product_option_ids, function(product_option_id) {
				
				let product_option_images = this_object.getImagesForNotSelectedProductOption(product_option_id);
				let current_product_option_images = this_object.getIntersectionOfArrays(product_option_images, p_images);
				images = this_object.getConcatenationOfArraysUnique(images, current_product_option_images);
				
			});
		
		} else {
			
			if ( pov_ids.length ) {
				
				this_object.each(pov_ids, function(pov_id){
					
					if (this_object.params.images_by_options && this_object.params.images_by_options[pov_id] && this_object.params.images_by_options[pov_id].length) {
						
						this_object.each(this_object.params.images_by_options[pov_id], function(poip_image_by_option){
						
							if (poip_image_by_option.image) {
								let poip_img = this_object.getImageBySrc(poip_image_by_option.image,'image');
								if (poip_img && poip_img.popup && $.inArray(poip_img.popup, p_images) != -1) {
									this_object.addToArrayIfNotExists(poip_img.popup, images);
								}
							}	
						});
					}
				});
			}
		}
	}
	
	
	
	this_object.each(p_images, function(p_image){
	
		if ( $.inArray(p_image, images) == -1 ) {
			images.push(p_image);
		}
	});

	return images;
};

// fn_svi
poip_product_default.prototype.setVisibleImages = function(images_param, callback) {
	let this_object = this;
	
	var images = this_object.sortImagesBySelectedOptions(images_param);
	var result = '';
	
	if ( typeof(this_object.replace_setVisibleImages) == 'function' ) {
		let result = this_object.replace_setVisibleImages(images);
		if ( callback ) {
			callback();
		}
		return result;
	
	} else if ( typeof(this_object.replace_setVisibleImagesWithCallback) == 'function' ) {
		return this_object.replace_setVisibleImagesWithCallback(images, 0, callback);
		
	// << DEFAULT OC 2.0 STYLE	
	} else if ( this_object.getElement('li.image-additional').length ) { // OC 2.0 default
		let shown_img = [];
		this_object.getAdditionalImagesBlock().find('a').each( function(){
			let $anchor = $(this);
			let href = $anchor.attr('href');
			if ( !href ) {
				href = $anchor.attr('data-image');
			}
			
			let toggle_flag = $.inArray( href, images) != -1 && $.inArray( href, shown_img) == -1;
				
			$anchor.toggle(toggle_flag);
		});
	// >> DEFAULT OC 2.0 STYLE	
	
	
	// << originally theme 422 compatibility, currently common	
	} else if (this_object.getElement('div[class=image-additional]').find('ul[id=image-additional]').length) {
	
		// make inages list copy
		if ( !this_object.getElement('#image-additional-copy').length ) {
			this_object.getElement('div[class=image-additional]').after("<div id=\"image-additional-copy\" style=\"display: none;\">"+this_object.getElement('div[class=image-additional]').find('ul[id=image-additional]').html()+"</div>");
		}
		
		// check is image list update needed
		var new_html = '';
		var new_images = [];
		this_object.getElement('#image-additional-copy').find('a').each( function(){
			if ($.inArray( $(this).attr('data-image'), images) != -1 || $.inArray(decodeURIComponent($(this).attr('data-image')), images) != -1) {
				// anchors have parents = "li"
				new_html += "<li>"+$(this).parent().html()+"</li>";
				new_images.push($(this).attr('data-image'));
			}
		});
		
		// there may be double images, so make groupping
		var images_changed = this_object.getElement('#image-additional').find('a').length != new_images.length;
		var same_images_count = 0;
		if (!images_changed) {
			this_object.getElement('#image-additional').find('a').each( function(){
				if ($.inArray( $(this).attr('data-image'), images) != -1 || $.inArray(decodeURIComponent($(this).attr('data-image')), images) != -1) {
					same_images_count++;
				}
			});
			images_changed = same_images_count != new_images.length;
		}
		
		if (images_changed) {	
			
			this_object.getElement('div[class=image-additional]').html("<ul id=\"image-additional\">"+new_html+"</ul>");
			
			if (this_object.getElement('#image-additional').find('a').length) {
				setTimeout( function () {
					this_object.getElement('#image-additional').bxSlider({
						pager:false,
						controls:true,
						slideMargin:10,
						minSlides: 3,
						maxSlides: 3,
						slideWidth:70,
						infiniteLoop:false,
						moveSlides:1
					});
					
					this_object.getElement('#zoom_01').elevateZoom({gallery:'image-additional', cursor: 'pointer', galleryActiveClass: 'active', imageCrossfade: true}); 
					//pass the images to Fancybox
					this_object.getElement('#zoom_01').bind("click", function(e) {  
						var ez =   this_object.getElement('#zoom_01').data('elevateZoom');	
						$.fancybox(ez.getGalleryList());
						return false;
					});
					
				}, 0);
			}
		}
		// >> theme 422 compatibility
	
		// << originally lexus superstore compatibility, currently some themes	
	} else if (this_object.getElement('div.image-additional').find('div.item').find('a').length) {
		let shown_img = [];
		this_object.getElement('div.image-additional').find('div.item').find('a').each( function(){
		
			if (($.inArray( this.href, images) != -1 || $.inArray(decodeURIComponent(this.href), images) != -1) && $.inArray( this.href, shown_img) == -1) {
				$(this).show();
				shown_img.push(this.href);
			} else {
				$(this).hide();
				
			}
		});
		// >> lexus superstore compatibility
		
		// << DEFAULT OC 1.X STYLE
	} else {	
	
		let shown_img = [];
		this_object.getAdditionalImagesBlock().find('a').each( function(){
		
			var current_href = $(this).attr('href');
			if ( (!current_href || current_href == '#') ) {
				if ($(this).attr('data-zoom-image')) {
					current_href = $(this).attr('data-zoom-image');
				} else {
					current_href = false;
				}
				if (current_href) {
					if ( $.inArray( current_href, images) != -1 && $.inArray( current_href, shown_img) == -1 ) {
						$(this).show();
						shown_img.push(current_href);
					} else {
						$(this).hide();
					}
				}
			}
		});
	}
	// >> DEFAULT OC 1.X STYLE
	
	if ( callback ) {
		callback();
	}
	
};

poip_product_default.prototype.elevateZoomDirectChange = function(img_click, timeout, elem_img, update_src, update_lens) {
	let this_object = this;

	if ( elem_img && elem_img.is('img') ) {
		var poip_img = this_object.getImageBySrc(img_click, 'popup');
		if ( elem_img.attr('data-zoom-image') ) {
			elem_img.attr('data-zoom-image', poip_img.popup);
		}
		if ( elem_img.attr('data-image') ) {
			elem_img.attr('data-image', poip_img.main);
		}
		if ( update_src ) {
			elem_img.attr('src', poip_img[update_src]);
		}
	}
	
	if ( timeout ) {
		setTimeout(function(){
			this_object.elevateZoomDirectChange(img_click, 0, elem_img, update_src, update_lens);
			//this_object.getElement('.zoomContainer .zoomWindowContainer div').css({"background-image": 'url("'+img_click+'")'});
		}, timeout);
	} else {
		this_object.getElement('.zoomContainer').find('.zoomWindowContainer').find('div').css("background-image", 'url("'+img_click+'")');
		if ( update_lens ) {
			if ( this_object.getElement('.zoomContainer').find('.zoomLens').css("background-image") && this_object.getElement('.zoomContainer').find('.zoomLens').css("background-image") != 'none' ) {
				this_object.getElement('.zoomContainer').find('.zoomLens').css("background-image", 'url("'+img_click+'")');
			}
		}
	}
};

poip_product_default.prototype.elevateZoomClickImage = function(img_click, p_cnt) {
	let this_object = this;

	var have_elevate_zoom = false;
	
	this_object.getAdditionalImagesBlock().find('a').each( function () {
		if ($(this).attr('data-image') == img_click || $(this).attr('data-zoom-image') == img_click) {
			have_elevate_zoom = true;
		}
	});
	
	if (have_elevate_zoom) {
		this_object.elevateZoomClickImageDelayed(img_click);
	}
	return have_elevate_zoom;
};

poip_product_default.prototype.elevateZoomClickImageDelayed = function(img_click, p_cnt) {
	let this_object = this;
	
	var cnt = (typeof(p_cnt)=='undefined' ? 1 : p_cnt );
	if ( cnt <= 100 ) {
	
		if ( !this_object.getElement('.zoomContainer').length ) {
			setTimeout(function(){
				this_object.elevateZoomClickImageDelayed(img_click, cnt+1);
			}, 100);
			return;
		}
		// run
		setTimeout( function() {
			this_object.getAdditionalImagesBlock().find('a').each( function () {
				if ($(this).attr('data-image') == img_click || $(this).attr('data-zoom-image') == img_click) {
					//$(this).find('img').click();
					$(this).click();
					return false;
				}
			});
			
			if ( typeof(this_object.additional_afterElevateZoomClickImage) == 'function' ) {
				this_object.additional_afterElevateZoomClickImage(img_click);
			}
			
		}, 100);	
	}	
};


poip_product_default.prototype.cloudZoomClick = function(img_click, elem_check_param, additional_images_param) {
	let this_object = this;
		
	if ( typeof(elem_check_param) != 'undefined' && elem_check_param ) {
		elem = elem_check_param;
	} else {
		elem = this_object.getElement('#zoom1');
	}
	if ( typeof(additional_images_param) != 'undefined' && additional_images_param ) {
		additional_images = additional_images_param;
	} else {
		additional_images = this_object.getElement('.image-additional a[href]');
	}
	if ( elem.data('zoom') || elem.data('CloudZoom') ) {
		setTimeout(function(){
			additional_images.each(function(){
				var current_a = $(this);
				if ($(this).is('img') && $(this).parent().is('a')) {
					current_a = $(this).parent();
				}
				if ( current_a.is('img') ) {
					img_src = current_a.attr('src');
					poip_img = this_object.getImageBySrc(img_src, 'main');
					if (!poip_img) {
						poip_img = this_object.getImageBySrc(img_src, 'popup');
					}
					if (!poip_img) {
						poip_img = this_object.getImageBySrc(img_src, 'thumb');
					}
					if (poip_img) {
						href = poip_img.popup;
					} else {
						href = img_src;
					}
				} else {
					href = current_a.attr('href');
				}
				
				if ( img_click == href ) {
					$(this).click();
					return false;
				}
			});
		}, 200);
	}
};

// << theme lexus superstore & journal2
poip_product_default.prototype.autoZoomSwitch = function(img_click) {
	this_object.getElement('.image a #image').attr('data-zoom-image', img_click);
	this_object.getElement('.zoomWindowContainer').find('div').css({"background-image": 'url("'+img_click+'")'});
	if (this_object.getElement('.image a #image').data('zoom-image')) {
		this_object.getElement('.image a #image').data('zoom-image', img_click);
	}
};
// >> theme lexus superstore

poip_product_default.prototype.getDocumentReadyState = function() {
	let this_object = this;

	if ( typeof(this_object.replace_getDocumentReadyState) == 'function' ) {
		return this_object.replace_getDocumentReadyState();
	}

	return document.readyState == 'complete';
};

poip_product_default.prototype.updateZoomImage = function(img_click, call_cnt) {
	let this_object = this;
	
	if ( this_object.update_zoom_image_timer_id ) {
		clearTimeout(this_object.update_zoom_image_timer_id);
	}

	if ( !this_object.getDocumentReadyState() ) {
		if ( typeof(call_cnt) == 'undefined' ) {
			call_cnt = 1;
		}  
		if ( call_cnt <= 100 ) {
			this_object.update_zoom_image_timer_id = setTimeout(function(){
				this_object.updateZoomImage(img_click, call_cnt+1);
			}, 100);
		}
		return;
	}
	if ( typeof(this_object.replace_updateZoomImage) == 'function' ) {
		return this_object.replace_updateZoomImage(img_click);
	}
	
	if ( typeof(this_object.if_updateZoomImage) == 'function' ) {
		if ( this_object.if_updateZoomImage(img_click) ) {
			return;
		}
	}
	
	// << elevatezoom compatibility / some old style themes
	if ( this_object.elevateZoomClickImage(img_click) ) return;
	// >> elevatezoom compatibility  / some old style themes
	
	// << some cloud-zoom-gallery themes compatibility
	this_object.getElement('div.image-additional').find('a.cloud-zoom-gallery').each( function () {
		if ($(this).attr('href') == img_click) {
			$(this).find('img').click();
			return false;
		}
	});
	// >> some cloud-zoom-gallery themes compatibility
	
	// << originally came from lexus superstore & pav fashion, but works for many themes
	if (this_object.getElement('.image a #image').attr('data-zoom-image') && this_object.getElement('.zoomWindowContainer').length && this_object.getElement('.zoomWindowContainer').find('div').length) {
		this_object.autoZoomSwitch(img_click);
		return; 
	} else if (this_object.getElement('.image a #image').attr('data-zoom-image')) {
		setTimeout(function () { this_object.autoZoomSwitch(img_click); }, 100);
		return;
	}
	
	// >> originally came from lexus superstore & pav fashion, but works for many themes
	
	// << originally came from start theme, but maybe works for other themes
	this_object.getElement('#image-additional').find('a[data-zoom-image]').each( function () { 
		if ($(this).attr('href') == img_click) {
			$(this).click();
			return;
		}
	});
	// >> originally came from start theme, but maybe works for other themes
	
};

poip_product_default.prototype.setMainImage = function(main, popup) {
	let this_object = this;
	
	if ( typeof(this_object.replace_setMainImage) == 'function' ) {
		return this_object.replace_setMainImage(main, popup);
	} else if ( typeof(this_object.if_setMainImage) == 'function' && this_object.if_setMainImage(main, popup) ) {
		// nothing 	
	} else {
		this_object.getMainImage().attr('src', main);
		this_object.getMainImage().closest('a').attr('href', popup);
	}
};

poip_product_default.prototype.refreshOptionImagesContainer = function(option, product_option_id) {
	let this_object = this;

	if ( typeof(this_object.if_refreshOptionImagesContainer) == 'function' && this_object.if_refreshOptionImagesContainer(option, product_option_id) ) {
		return;
	}

	this_object.getElement('#option-images-'+product_option_id).remove();
	if (!this_object.getElement('#option-images-'+product_option_id).length) {
		if (this_object.getElement('#option-'+product_option_id).length) { // OC 1.X style
			this_object.getElement('#option-'+product_option_id).append('<div id="option-images-'+product_option_id+'"></div>');
		} else { // OC 2.0 style
			this_object.getElement(option).after('<div id="option-images-'+product_option_id+'" style="margin-top: 10px;"></div>');
		}
	}
};

poip_product_default.prototype.getImageUrlsToDisplayAsMain = function(product_option_value_id, images_to_show) {
	let this_object = this;
	
	let selected_values = this_object.getSelectedOptionValues();
	let image_main = '';
	let image_popup = '';
	
	if ( images_to_show.length==0 && value && $.inArray(value, selected_values)==-1 && this_object.std_src && this_object.std_href) {
		image_main = this_object.std_src;
		image_popup = this_object.std_href;
	} else {
	
		// if any option is selected then relevant image should be displayed (even if complete set of options caused visibility of all images)
		var images_to_check = [];
		if ( product_option_value_id && $.inArray(product_option_value_id, selected_values) != -1 ) {
			for ( var i_images_to_show in images_to_show ) {
				if ( !images_to_show.hasOwnProperty(i_images_to_show) ) continue;
				let image_to_show = images_to_show[i_images_to_show];
				let poip_img = this_object.getImageBySrc(image_to_show, 'popup');
				if ( poip_img && poip_img.product_option_value_id && $.inArray(product_option_value_id, poip_img.product_option_value_id) != -1 ) {
					images_to_check.push(image_to_show);
				}
			}
		}
		
		if ( !images_to_check.length ) {
			images_to_check = images_to_show;
		}
		
		var poip_img = this_object.getImageBySrc(images_to_check[0], 'popup');
		if ( poip_img ) {
			image_main = poip_img.main;
			image_popup = poip_img.popup;
		} else {
			image_main = this_object.std_src;
			image_popup = this_object.std_href;
		}
		
		return  {
			main: image_main,
			popup: image_popup,
		};
	}
};

poip_product_default.prototype.changeVisibleImages = function(option) {
	let this_object = this;
	
	//var product_option_id = option.name.substr(this_object.option_prefix_length+1, option.name.indexOf(']')-(this_object.option_prefix_length+1) );
	let product_option_id = this_object.getProductOptionIdByName(option.name);
	
	if ($.inArray(product_option_id, this_object.params.poip_product_option_ids)==-1) {
		return;
	}
	
	//var selected_values = this_object.getSelectedOptionValues();
	
	let callback = function(images_to_show){
		
		this_object.updateImagesBelowOption(option);
	
		if ( typeof(this_object.additional_afterChangeVisibleImages) == 'function' ) {
			this_object.additional_afterChangeVisibleImages();
		}	
	};
	
	images_to_show = this_object.changeAvailableImages(product_option_id, callback, option);

};

poip_product_default.prototype.afterChangeVisibleImages = function(option, images_to_show) {
	
};

poip_product_default.prototype.updateImagesBelowOption = function(option) {
	let this_object = this;
	
	let product_option_id = this_object.getProductOptionIdByName(option.name);
	let product_option_value_id = option.value;
	
	// display images below options
	if (this_object.params.option_settings[product_option_id] && this_object.params.option_settings[product_option_id].img_option ) {
		if (!this_object.getElement('product_option_images'+product_option_id).length) {

			// checkbox may have many values
			var values = [];
			if ($(option).prop('tagName')=='INPUT' && $(option).prop('type')=='checkbox' ) {
				
				this_object.getElement('input[type=checkbox][name^='+this_object.option_prefix+'\\['+product_option_id+'\\]]:checked').each( function() {
					values.push($(this).val());
				});
			} else {
				values = [product_option_value_id];
			}
			
			this_object.refreshOptionImagesContainer(option, product_option_id);
			
			//var new_style_img_opt = !this_object.getElement('#option-images-'+product_option_id).length && !this_object.getElement('#option-'+product_option_id).length;
			
			let images = [];
			this_object.getElement('#option-images-'+product_option_id).html('');
			this_object.each(this_object.params.images, function(poip_img){
			//for (var i=0; i<this_object.params.images.length; i++) {
				this_object.each(values, function(pov_id){
				//for (var j=0; j<values.length; j++) {
					if (poip_img.product_option_value_id && $.inArray(pov_id, poip_img.product_option_value_id) != -1) {
						images.push(poip_img.popup);
						//var html_image = '<a href="'+this_object.params.images[i].popup+'" class="image-additional" style="margin: 5px;"><img src="'+this_object.params.images[i].thumb+'" ></a>';
						//this_object.getElement('#option-images-'+product_option_id).append(html_image);
					}
				});
			});
			
			images = this_object.sortImagesBySelectedOptions(images);
			
			this_object.each(images, function(image){
				let poip_img = this_object.getImageBySrc(image);
				let html_image = '<a href="'+poip_img.popup+'" class="image-additional" style="margin: 5px;"><img src="'+poip_img.thumb+'" ></a>';
				this_object.getElement('#option-images-'+product_option_id).append(html_image);
			});
			
			
			// OC 2.0 new-style default
			if ( this_object.getElement('#option-images-'+product_option_id+' a').length ) {
			//if ( new_style_img_opt && this_object.getElement('#option-images-'+product_option_id+' a').length ) {
			
				if ( $.magnificPopup ) {
					this_object.getElement('#option-images-'+product_option_id).magnificPopup({
						type:'image',
						delegate: 'a',
						gallery: {
							enabled:true
						}
					});
				}
			}
		}
	}
};

poip_product_default.prototype.getProductOptionImages = function(product_option_id) {
	let this_object = this;
	
	var images = [];
	
	for (var product_option_value_id in this_object.params.images_by_options) {
		for (var i in this_object.params.images_by_options[product_option_value_id]) {
			if (this_object.params.images_by_options[product_option_value_id][i].product_option_id == product_option_id) {
				images.push(this_object.params.images_by_options[product_option_value_id][i].image);
			}
		}	
	}
	return images;
};

poip_product_default.prototype.getProductOptionValueImages = function(product_option_value_id) {
	let this_object = this;
	
	var images = [];
	for (var i in this_object.params.images_by_options[product_option_value_id]) {
		images.push(this_object.params.images_by_options[product_option_value_id][i].image);
	}	
	return images;
};

poip_product_default.prototype.getImageSrc = function(image, src) {
	let this_object = this;
	
	for (var i in this_object.params.images) {
		if (this_object.params.images[i].image == image) {
			return this_object.params.images[i][src];
		}
	}
	return '';
};

poip_product_default.prototype.getImageBySrc = function(image, src1, src2, src3, src4) {
	let this_object = this;
		
	if ( !src1 && !src2 && !src3 && !src4 ) {
		src1 = 'popup';
		src2 = 'main';
		src3 = 'thumb';
		src4 = 'option_thumb';
	}
	
	let poip_img_found = '';
	this_object.each(this_object.params.images, function(poip_img){
		if ( (src1 && poip_img[src1] == image) || (src2 && poip_img[src2] == image) || (src3 && poip_img[src3] == image) || (src4 && poip_img[src4] == image) ) {
			poip_img_found = poip_img;
			return false;
		}
	});
	return poip_img_found;
};

poip_product_default.prototype.getImagesBySrc = function(images, src1, src2, src3, src4) {
	let this_object = this;
	
	let poip_imgs = [];
	this_object.each(images, function(image){
		let poip_img = this_object.getImageBySrc(image, src1, src2, src3, src4);
		if (poip_img) {
		  poip_imgs.push(poip_img);
		}
	});
	return poip_imgs;
};

poip_product_default.prototype.getSrcImagesBySrc = function(src, images, src1, src2, src3, src4) {
	let this_object = this;
	
	let poip_imgs = this_object.getImagesBySrc(images, src1, src2, src3, src4);
	let src_images = [];
	this_object.each(poip_imgs, function(poip_img){
		src_images.push(poip_img[src]);
	});
	return src_images;
};

poip_product_default.prototype.getImagesByPOVIds = function(pov_ids, src) {
	let this_object = this;
	
	let poip_imgs = [];
	this_object.each(this_object.params.images, function(poip_img){
		if ( poip_img.product_option_value_id ) {
			let intersection = this_object.getIntersectionOfArrays(poip_img.product_option_value_id, pov_ids);
			if ( intersection.length ) {
				if ( src ) {
					poip_imgs.push(poip_img[src]);
				} else {	
					poip_imgs.push(poip_img);
				}
			}
		}
		
	});
	return poip_imgs;
};

poip_product_default.prototype.updateDependentThumbnails = function() {
	let this_object = this;
	
	for (var j in this_object.params.poip_product_option_ids) {
		
		var product_option_id = this_object.params.poip_product_option_ids[j];
		
		if (this_object.params.option_settings[product_option_id] && this_object.params.option_settings[product_option_id].dependent_thumbnails && this_object.params.option_settings[product_option_id].img_first == 1 ) {
			
			var option_images = this_object.getProductOptionImages(product_option_id);
			
			for (var i in this_object.params.poip_product_option_ids) {
				if ( !this_object.params.poip_product_option_ids.hasOwnProperty(i) ) continue;
				
				if (this_object.params.poip_product_option_ids[i] == product_option_id) continue;
				var current_product_option_id = this_object.params.poip_product_option_ids[i];
				
				var current_product_option_selected_values = this_object.getSelectedOptionValues(0, current_product_option_id);
				
				var current_option_images = [];
				for (var i_image in this_object.params.images) {
					if (this_object.params.images[i_image].product_option_value_id && this_object.params.images[i_image].product_option_value_id.length) {
						for (var copsv_i in current_product_option_selected_values) {
							if ($.inArray(current_product_option_selected_values[copsv_i], this_object.params.images[i_image].product_option_value_id) !== -1 && $.inArray(this_object.params.images[i_image].image, current_option_images) == -1 ) {
								current_option_images.push(this_object.params.images[i_image].image);
							}
						}
					}
				}
				option_images = this_object.getIntersectionOfArrays(option_images, current_option_images);
			}
			
			if (option_images.length == 0) {
				option_images = this_object.getProductOptionImages(product_option_id);
			}
			
			// change options icons
			this_object.getElement('#product').find('input[type=radio][name="'+this_object.option_prefix+'['+product_option_id+']"], input[type=checkbox][name="'+this_object.option_prefix+'['+product_option_id+']"]').each(function(){
				option_value_images = this_object.getProductOptionValueImages($(this).val());
				if (option_value_images.length) {
					current_option_value_images	= this_object.getIntersectionOfArrays(option_value_images, option_images);
					if (current_option_value_images.length) {
						$(this).next('img').attr('src', this_object.getImageSrc(current_option_value_images[0], 'option_thumb') );
					} else {
						$(this).next('img').attr('src', this_object.getImageSrc(option_value_images[0], 'option_thumb') );
					}
				}
			});
		}
	}
};

poip_product_default.prototype.eventOptionValueSelect = function (option) {
	let this_object = this;
	
	let product_option_id = this_object.getProductOptionIdByName(option.name);
	if ($.inArray(product_option_id, this_object.params.poip_product_option_ids)==-1) {
		return;
	}

	clearTimeout(this_object.function_event_option_value_select_timer_id);

	// not run twice parallel
	if ( this_object.function_event_option_value_select_is_still_working || this_object.set_visible_images_timer_id !== false) {
		this_object.function_event_option_value_select_timer_id = setTimeout(function(){
			this_object.eventOptionValueSelect(option);
		}, 100);
		return;
	}
	
	this_object.function_event_option_value_select_is_still_working = true;

	this_object.changeVisibleImages(option);
	
	this_object.refreshPopupImages();
	
	this_object.updateDependentThumbnails();
	
	this_object.function_event_option_value_select_is_still_working = false;
	
};

// return IMG element relevant to main image
poip_product_default.prototype.getMainImage = function() {
	let this_object = this;

	if ( typeof(this_object.replace_getMainImage) == 'function' ) {
		return this_object.replace_getMainImage();
	}
	if ( typeof(this_object.if_getMainImage) == 'function' ) {
		// function should return result of jQuery call ( $(...) ) or FALSE
		var if_result = this_object.if_getMainImage();
		if ( if_result ) {
			return if_result;
		}
	}
		
	var oc2_main_img = this_object.getElement('ul.thumbnails li').not('.image-additional').find('a img').first();
	if ( oc2_main_img.length ) { // OC 2.0 default
		return oc2_main_img;
	}

	if (!this_object.getElement('#image').length) {
		if (this_object.getElement('#main-image').length) {
			return this_object.getElement('#main-image'); // originally for theme start, actually common
		}
		if (this_object.getElement('div.product-info div.image a img').length) {
			return this_object.getElement('div.product-info div.image a img'); // originally for theme cosyone, actually common
		}
		if (this_object.getElement('div.row-product a img[itemprop="image"]').length) {
			return this_object.getElement('div.row-product a img[itemprop="image"]'); // originally for theme moneymaker, actually common
		}
	}
	return this_object.getElement('#image'); // by standard default
};

poip_product_default.prototype.getElementOuterHTML =  function(elem) {
	let this_object = this;
	let str = '';
	
	if ( elem.length ) {
		if ( typeof(elem[0].outerHtml) != 'undefined' ) {
			str = elem[0].outerHtml;
		} else {	
			// should use $ here
			str = $('<div>').append(elem.clone()).html();
			//str = $(document.createElement("div")).append(elem.clone()).html();
		}
	}
	return str;
};

poip_product_default.prototype.getOuterHTML =  function(elem) { // for better compatibility with scripts converted from 3.x module version
	let this_object = this;
	return this_object.getElementOuterHTML(elem);
};

// returns element/elements (div, ul, li etc, depend on theme) containing links to additional images (а)
poip_product_default.prototype.getAdditionalImagesBlock = function() {
	let this_object = this;
	
	if ( typeof(this_object.replace_getAdditionalImagesBlock) == 'function' ) {
		return this_object.replace_getAdditionalImagesBlock();
		//var additional_images_block = this_object.replace_getAdditionalImagesBlock();
		//if (additional_images_block) {
		//	return additional_images_block;
		//}
	}
	if ( typeof(this_object.if_getAdditionalImagesBlock) == 'function' ) {
		// returns result of jQuery call ( $(...) ) or FALSE
		var if_result = this_object.if_getAdditionalImagesBlock();
		if ( if_result ) {
			return if_result;
		}
	}
	
	
	
	if ( this_object.getElement('li.image-additional').length ) { // OC 2.0 default
		return this_object.getElement('li.image-additional');
	}

	if ( !this_object.getElement('div.image-additional').length ) {
		this_object.getElement('div.product-info div.image').after('<div class="image-additional"></div>');
	}

	return this_object.getElement('div.image-additional');
};

poip_product_default.prototype.getRefreshColorboxImagesVisible = function() {
	let this_object = this;
	
	if ( typeof(this_object.replace_getRefreshColorboxImagesVisible) == 'function' ) {
		return this_object.replace_getRefreshColorboxImagesVisible();
	}
	
	return this_object.getAdditionalImagesBlock().find('a:visible[href!="#"]');
};

poip_product_default.prototype.getColorboxSettings = function() {
	let this_object = this;
	
	if ( typeof(this_object.replace_getColorboxSettings) == 'function' ) {
		return this_object.replace_getColorboxSettings();
	}
	
	var colorbox_settings = false;
	try {
		var scripts = this_object.getElement('script:contains(".colorbox")');
		for (var i=0; i<scripts.length; i++) {
			var script_html  =$(scripts[i]).html();
			if (script_html.indexOf('$(\'.colorbox\').colorbox(') != -1 ) {
				var str_pos = script_html.indexOf('$(\'.colorbox\').colorbox(');
				var str = script_html.substr(str_pos+24);
				str_pos = str.indexOf('});');
				str = str.substr(0,str_pos+1);
				colorbox_settings = eval('('+str+')');
				break;
			}
		}
	} catch (e) {
		console.debug(e);
		colorbox_settings = false;
	}
	
	if (!colorbox_settings || (typeof colorbox_settings) != 'object') {
		//console.log('colorbox settings not found');
		colorbox_settings = {
			overlayClose: true,
			opacity: 0.5,
			rel: "colorbox"
		};
	}
	
};

poip_product_default.prototype.refreshColorboxImages = function() {
	let this_object = this;

	// OC 2.0 not uses colorbox in default theme
	if (!this_object.use_refresh_colorbox) return;
	
	if (this_object.params.poip_settings.img_gal) {
		
		if ( typeof(this_object.if_refreshColorboxImages) == 'function' && this_object.if_refreshColorboxImages() ) {
			return;
		}
	
		this_object.getElement('#poip_colorbox').remove();
		
		this_object.getAdditionalImagesBlock().after('<div style="display: none" id="poip_colorbox"></div>');
		
		var colorbox_images = [];

		var visible_images = this_object.getRefreshColorboxImagesVisible();
		
		visible_images.each(function(){
			var img_href = $(this).attr('href') ;
			if ($.inArray( img_href, colorbox_images) == -1) {
				this_object.getElement('#poip_colorbox').append( this_object.getElementOuterHTML($(this)).replace('colorbox', 'poip_colorbox') );
				colorbox_images.push(img_href);
			}
		});
		
		
		/* add main image to gallery, even if it's not included in additional images */
		if ($.inArray(this_object.getMainImage().parent().attr('href'), colorbox_images) == -1) {
			this_object.getElement('#poip_colorbox').append( this_object.getElementOuterHTML(this_object.getMainImage().parent()).replace('colorbox', 'poip_colorbox') );
			colorbox_images.push(this_object.getMainImage().parent().attr('href'));
		}
		
		// for ava store and, possible, other templates, poip_colorbox should be additionally filled
		this_object.getElement('#poip_colorbox a[href!="#"], #poip_colorbox a[href="#"][data-image]').each(function(){
			if ( !$(this).hasClass('poip_colorbox') ) {
				$(this).addClass('poip_colorbox');
			}
			if ($(this).attr('href') == '#' && $(this).attr('data-image')) {
				$(this).attr('href', $(this).attr('data-image'));
			}
		});
		
		if (typeof($.colorbox) !== 'undefined') {
			$.colorbox.remove();
		}
		
		if ( typeof(this_object.if_beforeColorboxReinit) == 'function' && this_object.if_beforeColorboxReinit() ) {
			return;
		}
		
		if ($.colorbox) {
		
			colorbox_settings = this_object.getColorboxSettings();
		
			if ( colorbox_settings ) {
				this_object.getElement('.poip_colorbox').colorbox(colorbox_settings);
				
				try {
					this_object.getElement('[id^=option-images-]').each( function() {
						
						colorbox_settings.rel = $(this).attr('id');
						// more compatible
						$(this).find('a').colorbox(colorbox_settings);
						
					});
				} catch(e) {
					console.debug(e);
					console.debug("colorbox under options gallery error");
				}
			}
		
		}
		
		if ( typeof(this_object.if_triggerAfterColorboxReinit) == 'function' && this_object.if_triggerAfterColorboxReinit() ) {
			// nothing
		} else {
			this_object.getElement('.colorbox').unbind('click');
			//this_object.getElement('.colorbox').unbind('click', this_object.eventColorboxClick);
			this_object.getElement('.colorbox').bind( 'click', function(event) {
				this_object.eventColorboxClick(event, this);
			});
		}
		
	}
};

poip_product_default.prototype.eventColorboxClick = function(event, element) {
	let this_object = this;

	if ( typeof(this_object.replace_eventColorboxClick) == 'function' ) {
		return this_object.replace_eventColorboxClick(event, element);
	}

	event.preventDefault();

	var this_data = $(element);
	var poip_colorbox = this_object.getElement('a.poip_colorbox[href!="#"]');
	
	for (var i=0; i<poip_colorbox.length; i++) {
		if (this_data.attr('href') == poip_colorbox[i].href || this_data.attr('href') == decodeURIComponent(poip_colorbox[i].href)) {
			$(poip_colorbox[i]).trigger('click');
			break;
		}
	}
};

poip_product_default.prototype.anchorIsVideo = function($a) {
	let this_object = this;
	
	if ( $a.attr('data-ipvitem') ) {
		try {
			let ipvitem = $.parseJSON($a.attr('data-ipvitem'));
			if ( ipvitem && ipvitem.ipv && ipvitem.ipv != 'false' ) {
				return true;
			}
		} catch(e) {
			// ignore
		}
	}
	return this_object.hrefIsVideo( $a.attr('href') );
};

poip_product_default.prototype.hrefIsVideo = function(href) {
	let this_object = this;
	
	if ( href ) {
		if ( href.indexOf('https://www.youtube.com')==0 || href.indexOf('http://www.youtube.com')==0
		|| href.indexOf('https://youtube.com')==0 || href.indexOf('http://youtube.com')==0
		|| href.indexOf('https://www.vimeo.com')==0 || href.indexOf('http://www.vimeo.com')==0
		|| href.indexOf('https://vimeo.com')==0 || href.indexOf('http://vimeo.com')==0
		|| href.indexOf('//www.youtube.com')==0
		|| href.indexOf('//youtube.com')==0
		|| href.indexOf('www.youtube.com')==0
		|| href.indexOf('youtube.com')==0
		|| href.indexOf('www.vimeo.com')==0
		|| href.indexOf('vimeo.com')==0 ) {
			return true;
		}
	}
	return false;
};

poip_product_default.prototype.getAdditionalImageMouseoverHref = function(image_a) {
	let this_object = this;
	
	if ( typeof(this_object.replace_getAdditionalImageMouseoverHref) == 'function' ) {
		return this_object.replace_getAdditionalImageMouseoverHref(image_a);
	}
	
	if ( typeof(this_object.if_getAdditionalImageMouseoverHref) == 'function' ) {
		var if_result = this_object.if_getAdditionalImageMouseoverHref(image_a);
		if ( if_result ) {
			return if_result;
		}
	}
	
	var href = '';
	if ($(image_a).is('img')) {
		href = $(image_a).attr('src');
	} else {
		href = ($(image_a).attr('href') && $(image_a).attr('href')!='#') ? $(image_a).attr('href') : $(image_a).attr('data-image') ;
	}
	
	return href;
};

poip_product_default.prototype.eventAdditionalImageMouseover = function(image_a) {
	let this_object = this;
	
	if ( typeof(this_object.if_eventAdditionalImageMouseover) == 'function' && this_object.if_eventAdditionalImageMouseover(image_a) ) {
		return;
	}
	
	if ( typeof(this_object.additional_startOfEventAdditionalImageMouseover) == 'function' ) {
		this_object.additional_startOfEventAdditionalImageMouseover(image_a);
	}

	var href = this_object.getAdditionalImageMouseoverHref(image_a);
	
	var data_image = $(image_a).attr('data-image');
	
	if ( this_object.anchorIsVideo( $(image_a) ) ) {
	//if ( this_object.hrefIsVideo(href) ) {
		return;
	}
	
	for (var i=0;i<this_object.params.images.length;i++) {
		
		let poip_img = this_object.getImageBySrc(href);
		if ( !poip_img ) {
			poip_img = this_object.getImageBySrc(data_image);
		}
		
		if ( poip_img ) {
			
			if ( this_object.useMainImageUpdatingOnMouseover() ) {
				this_object.setMainImage(poip_img.main, poip_img.popup);
			}
			this_object.updateZoomImage(poip_img.popup);
	
			break;
		}
	}
	
	if ( typeof(this_object.additional_endOfEventAdditionalImageMouseover) == 'function' ) {
		this_object.additional_endOfEventAdditionalImageMouseover(image_a);
	}
	
	this_object.refreshPopupImages();
};

poip_product_default.prototype.setDefaultOptionsByURL = function() {
	let this_object = this;
	
	if ( typeof(this_object.if_setDefaultOptionsByURL) == 'function' && this_object.if_setDefaultOptionsByURL() ) {
		return;
	}
	
	let pov_ids = this_object.getDefaultOptionValuesToSet();
	
	this_object.each(pov_ids, function(pov_id){
		this_object.setProductOptionValue(pov_id);
	});

};

poip_product_default.prototype.getDefaultOptionValuesToSet = function(){
	let this_object = this;
	
	let pov_ids = [];
	
	if ( this_object.params.poip_ov ) {
		pov_ids.push(this_object.params.poip_ov);
	}
	
	// for Yandex sync module by Toporchillo
	var hash = window.location.hash;
	if (hash) {
		var hashpart = hash.split('#');
		var hashvals = hashpart[1].split('-');
		for (i=0; i<hashvals.length; i++) {
			if ( !hashvals.hasOwnProperty(i) ) continue;
			
			if ( $.inArray(hashvals[i], pov_ids) == -1 ) {
			  pov_ids.push(hashvals[i]);
			}
		}
	}
	return pov_ids;
};
		

poip_product_default.prototype.setProductOptionValue = function(value) {
	let this_object = this;
	
	var $option_element = this_object.getElement('select[name^="'+this_object.option_prefix+'["] option, input:radio[name^="'+this_object.option_prefix+'["], input:checkbox[name^="'+this_object.option_prefix+'["]').filter('[value="'+value+'"]:not(:disabled)');
	if ( !$option_element.length ) {
		return;
	}
	
	// Journal2 compatibility new
	let $button = this_object.getElement('.option ul li[data-value='+value+'].hint--top');
	if ( $button.length ) {
		if ( $option_element.is('option') ) { // select
			$option_element.parent().val(value);
			$option_element.parent().trigger('change');
			$button.siblings('.hint--top').removeClass('selected');
			$button.addClass('selected');
			
		} else { // radio or checkbox
			$option_element.prop('checked', true);
			$option_element.trigger('change');
			
			if ( $option_element.is(':radio') ) {
				$button.siblings('.hint--top').removeClass('selected');
				$button.addClass('selected');
			} else { // checkbox
				$button.addClass('selected');
			}
			
		}
		return;
	}
	
	// Journal2 compatibility
	if (this_object.getElement('.option ul li[data-value='+value+']').length) {
		
		if ( $option_element.is('option') ) { // select
			$option_element.parent().val(value);
			$option_element.parent().trigger('change');
			
			return;
		} else { // radio or checkbox
			$option_element.prop('checked', true);
			$option_element.trigger('change');
			return;
		}
		
		this_object.getElement('.option ul li[data-value='+value+']').click();
		
		return;
	}

	// Product Block Option compatibility
	if ( this_object.getElement('a[option-value='+value+']').length ) {
		this_object.getElement('a[option-value='+value+']').click();
		return;
	}

	
	if ( typeof(this_object.if_setProductOptionValue) == 'function' && this_object.if_setProductOptionValue(value, $option_element) ) {
		return;
	}

	if ( $option_element.is('option') ) { // select
		$option_element.parent().val(value);
		$option_element.parent().trigger('change');
		
		return;
	} else { // radio or checkbox
		$option_element.prop('checked', true);
		$option_element.trigger('change');
		return;
	}

};


// << SEO
poip_product_default.prototype.getOptionSeoUrlByProductUrlAndKeywords = function(product_keyword, keyword, p_href) {
	var this_object = this;
	
	let href = p_href;
	if ( !href ) {
		href = this_object.getOriginalProductUrl();
	}
	
	let str_pos = -1;
	let new_href = href;
	if ( href.substr( -(1+product_keyword.length) ) == '/'+product_keyword ) {
		new_href = href.substr(0, href.length-product_keyword.length) + keyword;
	} else {
		new_href = new_href.replace('/'+product_keyword+'&', '/'+keyword+'&').replace('/'+product_keyword+'?', '/'+keyword+'?');
	}
	return new_href;
};

poip_product_default.prototype.setCurrentUrlByImage = function(image) {
	var this_object = this;
	
	let selected_values = this_object.getSelectedOptionValues();
	
	if ( !selected_values.length ) { // restore original url
		this_object.restoreOriginalProductUrl();
	} else { // set option specific url
		let current_poip_img = '';
		let current_pov_id = '';
		
		this_object.each(this_object.params.images, function(poip_img){
			if ( poip_img.image == image ) {
				let pov_ids = this_object.getIntersectionOfArrays(poip_img.product_option_value_id, selected_values);
				if ( pov_ids.length ) {
					current_poip_img = poip_img;
					current_pov_id = pov_ids[0];
					return false;
				}
			}
		});
		
		if ( !current_poip_img || !current_poip_img.product_keyword || !current_poip_img.keywords || !current_poip_img.keywords[current_pov_id] ) {
			this_object.restoreOriginalProductUrl();
		} else {
			let url = this_object.getOptionSeoUrlByProductUrlAndKeywords(current_poip_img.product_keyword, current_poip_img.keywords[current_pov_id]);
			
			this_object.setCurrentUrl(url);
			
		}
	}
	
};

poip_product_default.prototype.setCurrentUrl = function(url) {
	window.history.replaceState({}, '', url);
};

poip_product_default.prototype.restoreOriginalProductUrl = function() {
	var this_object = this;
	if ( this_object.getOriginalProductUrl() ) {
		this_object.setCurrentUrl(this_object.getOriginalProductUrl());
	}
};

poip_product_default.prototype.getOriginalProductUrl = function() {
	
	var this_object = this;
	if ( !this_object.original_product_href && this_object.params.images && this_object.params.images.length && this_object.params.images[0].product_keyword ) {
		
		let product_keyword = this_object.params.images[0].product_keyword;
		
		let default_product_url = '';
		let href = location.href;
		if ( href.substr( -(1+product_keyword.length) ) == '/'+product_keyword || href.indexOf('/'+product_keyword+'&') != -1 || href.indexOf('/'+product_keyword+'?') != -1 ) {
			default_product_url = href;
		} else { // try to find an option keyword and replace
			
			if ( typeof(this_object.params.poip_keywords) != 'undefined' && this_object.params.poip_keywords ) {
				this_object.each(this_object.params.poip_keywords, function(keyword){
					if ( href.includes(keyword) != -1 ) {
					//if ( href.indexOf(keyword) != -1 ) {
						let changed_url = this_object.getOptionSeoUrlByProductUrlAndKeywords(keyword, product_keyword, href);
						if ( changed_url != href ) {
							default_product_url = changed_url;
							return false;
						}
					}
				});
			}
		}
		if ( default_product_url ) {
			this_object.original_product_href = default_product_url;
		} else {
			this_object.original_product_href = href;
		}
		
	}
	
	if ( this_object.original_product_href ) {
		return this_object.original_product_href;
	}
};

// >> SEO

poip_product_default.prototype.externalOptionChange = function() {
	let this_object = this;
	
	if (this_object.params.images_by_options) {
		for (var i in this_object.params.images_by_options) {
			if (this_object.params.images_by_options[i] && this_object.params.images_by_options[i].length && this_object.params.images_by_options[i][0].product_option_id) {
				var product_option_id = this_object.params.images_by_options[i][0].product_option_id;
				this_object.getElement('select, input').filter('[name="'+this_object.option_prefix+'['+product_option_id+']"]').change();
				return;
			}
		}
	}
};

poip_product_default.prototype.checkEventsForSelects = function(first_time) {
	let this_object = this;

	this_object.getElement('select[name^="'+this_object.option_prefix+'["]').each(function () {
		var select_events = $(this).data('events') || $._data( this, "events" );
		var found_poip = false;
		
		if (select_events && select_events.change) {
			for (var i=0; i<select_events.change.length; i++) {
				if ( (''+select_events.change[i].handler).indexOf('this_object.eventOptionValueSelect') != -1 ) {
					found_poip = true;
					break;
				}
			}
		}
		
		if (!found_poip) {
			$(this).change( function(){this_object.eventOptionValueSelect(this);} );
			// event should be called, may be select value is reseted
			if (!first_time) {
				this_object.eventOptionValueSelect(this);
			}
		}
	});
};



// << MOST CHANGABLE FUNCTIONS

poip_product_default.prototype.useColorboxRefreshing = function() {
	let this_object = this;
	
	if ( typeof(this_object.replace_useColorboxRefreshing) == 'function' ) {
		return this_object.replace_useColorboxRefreshing();
	}
	
	return false;
};

poip_product_default.prototype.useMainImageUpdatingOnMouseover = function() {
	let this_object = this;
	
	if ( typeof(this_object.replace_useMainImageUpdatingOnMouseover) == 'function' ) {
		return this_object.replace_useMainImageUpdatingOnMouseover();
	}
	
	return true;
};

// >> MOST CHANGABLE FUNCTIONS

// << BASIC MODULE-TO_THEME ADAPDATION FUNCTIONS

// {$images: , attr_name: , parent_selector: , html_version: , command_prepare_element: };

poip_product_default.prototype.storeImageElementsToImageCollection = function(params) {
	let this_object = this;
	
	let html_version = params.html_version || 'html';
	if ( $.inArray(html_version, this_object.stored_image_elements_by_collections) == -1 ) {
		
		this_object.stored_image_elements_by_collections.push(html_version);
		params.$images.each(function(){
			let $image = $(this);
			if ( params.command_prepare_element && typeof(params.command_prepare_element) == 'function' ) {
				$image = params.command_prepare_element($image);
			}	
			
			let attr_name = params.attr_name || ( $image.is('img') ? 'src' : 'href' );
			let image = $image.attr(attr_name);
			let poip_img = this_object.getImageBySrc(image);
			if ( poip_img ) {
				let html = this_object.getOuterHTML( params.parent_selector ? $image.closest(params.parent_selector) : $image );
				
				poip_img[html_version] = html;
			}
		});
	}
};

poip_product_default.prototype.getStoredImagesContainer = function($put_before_element, $carousel_items, data_key) {
	let this_object = this;
	data_key = data_key || 'images';
	
	var selector = '[data-poip="'+data_key+'"]';
	if ( !this_object.getElement(selector).length ) {
		$put_before_element.before('<div data-poip="'+data_key+'" style="display:none;!important"></div>');
		$carousel_items.each(function(){
			this_object.getElement(selector).append( this_object.getElementOuterHTML($(this)) );
		});
	}
	return this_object.getElement(selector);
};

poip_product_default.prototype.updateShouldBeProcessed = function($carousel_items, href_attr_name, images_to_check, images, counter, carousel_is_ready, ignore_image_coincidence, callback) {
	let this_object = this;			
	
	if ( this_object.set_visible_images_first_call ) {
		if ( !carousel_is_ready ) {
			this_object.set_visible_images_timer_id = setTimeout(function(){
				if ( callback ) {
					this_object.replace_setVisibleImagesWithCallback(images, counter+1, callback);
				} else {
					this_object.replace_setVisibleImages(images, counter+1);
				}
			}, 100);
			return false;
		}
		this_object.set_visible_images_first_call = false;
	} else {
		if ( !ignore_image_coincidence ) {
			var current_imgs = [];
			$carousel_items.each( function(){
				current_imgs.push($(this).attr(href_attr_name));
			});
			
			if ( current_imgs.toString() == images_to_check.toString() ) {
				this_object.set_visible_images_timer_id = false;
				return false; // nothing to change
			}
		}
	}
	
	return true;

};

// >> BASIC MODULE-TO_THEME ADAPDATION FUNCTIONS