let ProyectosValidateController = {
	// Atributos Básicos
	users: null,
	mision: null,
	project: null,
	typeMision: null,
	idTypeMision: null,
	messages: null,
	user: null,
	survey: '',
	answerByUser: '',
	idGroup: '',
	loadIMG: '',
	startDate: '',
	endDate: '',
	language: '',
	questionsWithPictures: [],
	galleries: null,
	userPicturesArray: [],
	userPicturesRefuse: [],
	userAdmin: '',
	userPicturesArrayToCheck: [],
	usersForAcceptRejectArray: [],
	picturesArray: [],
	correctionOCR: [],
	markAll: false,
	objectEvidence: null,

	reset() {
		let self = this;

		self.users = null;
		self.mision = null;
		self.project = null;
		self.typeMision = null;
		self.idTypeMision = null;
		self.messages = null;
		self.user = null;
		self.survey = '';
		self.answerByUser = '';
		self.idGroup = '';
		self.loadIMG = '';
		self.startDate = '';
		self.endDate = '';
		self.language = pf.const.language_table;
		self.questionsWithPictures = [];
		self.galleries = null;
		self.userPicturesArray = [];
		self.userPicturesRefuse = [];
		self.userAdmin = '';
		self.userPicturesArrayToCheck = [];
		self.usersForAcceptRejectArray = [];
		self.picturesArray = [];
		self.correctionOCR = [];
		self.markAll = false;
		self.objectEvidence = null;
	},

	setEvents() {
		let self = this;
		self.reset();

		let JSONuser = sessionStorage['STCMBackEnd:user'];
		let user = JSON.parse(JSONuser);
		self.userAdmin= user.email;
		$('#languageOptions').val(user.location);

		let params = JSON.parse(atob(sessionStorage['STCMBackEnd:validate']));
		self.mision = params.mision;
		self.project = params.project;
		sessionStorage.setItem('idProject', self.project.id);

		// Reducción de Header
		headerSectionHeight(0);

		// Añadir titulo
		$('#page-title').text(pf.const.language.RSC351 + ' - ' + pf.const.language.RSC572);

		// Opciones de header
		let jsonsubopt = {
			back: 'back'
		};

		let nav = `
			<div></div>

			${createSubOptionBack(jsonsubopt.back)}
		`;

		// Acciones de página (flex-row-reverse)s
		$('#page-actions').html(nav);

		// Botones secundarios
		$('#back').addClass('secondary-button');

		$('#header1').html(self.mision.idmision);

		// Ocultación de botón para visualizar las imágenes de encuesta para validar
		$('#viewImages').hide();

		// Valores de configuración
		let config = JSON.parse(atob(sessionStorage.getItem('STCMBackEnd:config')));
		self.loadIMG = config.URLEncuestas;

		self.loadLang();
		self.applyEvents();
		self.getAllMisiones();
		
		self.getFilesRecordedByProject();

		// Collapse
		addEventArrowTableHeader();
	},

	loadLang() {
		pf.rsc.translateByTag('text');

		// TITLES
		$('.exportTitle').attr('title', pf.const.language.RSC47);
		$('#identifyDuplicatePhotos').attr('title', pf.const.language.RSC2122);
		$('#processImage').attr('title', pf.const.language.RSC2200);
		$('#processImageOCR').attr('title', pf.const.language.RSC2316);
		$('#markAll').attr('title', pf.const.language.RSC379);
		$('#uncheckAll').attr('title', pf.const.language.RSC378);
		$('#viewImages').attr('title', pf.const.language.RSC1992);
		$('#rejectSelected').attr('title', pf.const.language.RSC2117);
		$('#acceptSelected').attr('title', pf.const.language.RSC2116);
	},

	applyEvents() {
		let self = this;

		// Volver a Proyectos o misiones
		$('#back').on('click', function() {
			if(sessionStorage['validationSource'] == 'missions') {
				window.location.href = '#!misiones';
			} else {
				window.location.href = '#!proyectos_edit';
			}
		});

		$('#refuse').click(function() {
			$('#inputRefuse').removeClass('d-none');
			$('#buttons').addClass('d-none');
			$('#refuseReasons').val('');
		});

		$('#refuseCancel').click(function() {
			$('#inputRefuse').addClass('d-none');
			$('#buttons').removeClass('d-none');
		});

		// Validar pago
		$('#confirm').click(function() {
			self.confirm();
		});

		// Rechazar pago
		$('#refuseConfirm').click(function() {
			self.refuse();
		});

		// Visualización de imágenes de encuesta de validación
		$('#viewImages').off().on('click', function() {
			self.getSurveysFilesByQuestion();
		});

		// Rechazar pagos a través de imágenes
		$('#refusePictures').off().on('click', function() {
			self.showMotivoRechazoAlert(function() {
				let reasonRejection = $('#reasonRejection').val().trim();

				if(reasonRejection != '') {
					// Rechazo de misión por galería
					self.setMisionValidationMultiple(reasonRejection);
				} else {
					$('#reasonRejection').addClass('is-invalid');
					return false;
				}
			});
		});

		// Aceptación múltiple
		$('#acceptSelected').off().on('click', function() {
			self.validateMissionMultiple();
		});

		// Rechazo múltiple
		$('#rejectSelected').off().on('click', function() {
			if(self.usersForAcceptRejectArray.length > 0) {
				self.showMotivoRechazoAlert(function() {
					let reasonRejection = $('#reasonRejection').val().trim();

					if(reasonRejection != '') {
						// Rechazo de misión múltiple reutilizando el metodo para rechazo múltiple a través de galería
						self.userPicturesRefuse = self.usersForAcceptRejectArray;
						self.setMisionValidationMultiple(reasonRejection);
					} else {
						$('#reasonRejection').addClass('is-invalid');
						return false;
					}
				});
			}
		});

		// Identificar fotos duplicadas
		$('#identifyDuplicatePhotos').off().on('click', function() {
			let parameters = {
				survey: self.survey
			};
			ajaxComunCallWithCallback('getCompareFilesBySurveys', parameters, function(ajaxReturn) {
				if(ajaxReturn) {
					let duplicateArray = ajaxReturn.duplicatedFiles;

					// Collapse
					$('.arrowG').each(function() {
						let arrow = $(this).attr('data-arrow');
						let direction = '';
						if(arrow == 'right') {
							direction = stcmbackend.svg.chevronDown;
							$(this).attr('data-arrow', 'down');
							$(this).html(direction);
							$(this).parent().parent().find('.collapse').collapse('toggle');
						}
					});

					if(duplicateArray.length > 0) {
						$('.surveyImage').each(function() {
							let dataImage = $(this).data('image');

							if(duplicateArray.includes(dataImage)) {
								let user = $(this).data('user');
								let pictureFilter = $(this).find('img').css('filter');

								if(pictureFilter == 'none') {
									$(this).find('img').css('filter', 'grayscale(100%)');
									$(this).find('.btn-eye').show();

									if(self.userPicturesRefuse.indexOf(user) === -1) {
										self.userPicturesRefuse.push(user);

										// Anula todas las imágenes del mismo usuario
										$('.surveyImage').each(function() {
											let oUser = $(this).data('user');

											if(oUser == user) {
												$(this).find('img').css('filter', 'grayscale(100%)');
												$(this).find('.btn-eye').show();
											}
										});
									}
								}
							}
						});

						$('#refusePictures').prop('disabled', false);
					} else {
						let Title = pf.const.language.RSC1909;
						let Content = pf.const.language.RSC2138;
						pf.utils.showInfoDialog(Title, Content);
					}
				}
			});
		});

		// Analizar foto
		$('#processImage').off().on('click', function() {
			let parameters = {
				urlImage: JSON.stringify(self.picturesArray),
				lenguage: $('#languageOptions').val()
			};
			ajaxComunCallWithCallback('analizaFoto', parameters, function(ajaxReturn) {
				if(ajaxReturn) {
					// Recargar imágenes
					self.getSurveysFilesByQuestion();
				}
			});
		});

		// Analizar foto OCR
		$('#processImageOCR').off().on('click', function() {
			let parameters = {
				sid: self.mision.sid,
				lenguage: $('#languageOptions').val(),
				stampMision: self.mision.stampMision,
				idProject: self.project.id
			};
			ajaxComunCallWithCallback('procesaOCRFotosFolder', parameters, function(ajaxReturn) {
				if(ajaxReturn) {
					// Recargar imágenes
					self.getSurveysFilesByQuestion();
				}
			});
		});

		// Guardar corrección OCR
		$('#saveCorrection').off().on('click', function() {
			let fileName = $('#saveCorrection').data('img');
			let idCapture = $('#saveCorrection').data('capture');
			data = [];

			let size = self.correctionOCR.length;
			for(let i = 0; i < size; i++) {
				if(self.correctionOCR[i].changed) {
					let element = self.correctionOCR[i].text + '#:#' + self.correctionOCR[i].textSimilar;
					data.push(element);
				}
			}

			// Si no hay cambios no hace nada
			if(data.length < 1) {
				return false;
			}

			let parameters = {
				fileName: fileName,
				idCapture: idCapture,
				data: JSON.stringify(data)
			};
			ajaxComunCallWithCallback('setImageDataOCRSimilarities', parameters, function(ajaxReturn) {
				if(ajaxReturn) {
					// Ocultar modal individual
					$('#infoModal').modal('hide');

					// Mostrar modal de todas las imágenes
					$('#modalPictures').modal('hide');

					// Recargar imágenes
					self.getSurveysFilesByQuestion();
				}
			});
		});

		// JIRA: 3301
		// Pruebas en Social, misión: "RFQ - Nuevas validaciones"
		// Modal de evidencias
		$('#validateEvidence').off().on('click', function() {
			// Activación de spinner y creación de nuevo objeto para validar evidencias
			addLoader();
			// ¿Qué parámetros serán necesarios en la creación del objeto?
			self.objectEvidence = new EvidenceValidations(self.mision.idmision, self.mision.stampMision, self.project.id);
			// Petición de datos
			// ¿Qué parámetros serán necesarios para la petición de datos?
			self.objectEvidence.requestData();
		});
	},

	showMotivoRechazoAlert(callback) {
		let content = `
			<div class="form-group">
				<label for="reasonRejection" class="fw-500">${pf.const.language.RSC575}</label>
				<input id="reasonRejection" type="text" class="form-control" value="">
			</div>
		`;

		let objInfo = {
			accept: {
				text: pf.const.language.RSC377
			},
			cancel: {
				text: pf.const.language.RSC57
			}
		};

		let alertTitle = pf.const.language.RSC574;
		pf.utils.showInfoDialogCustomWidthAcceptCancelNewStyle(alertTitle, content, objInfo, '500px', function() {
			callback();
		}, function() {});
	},

	// Cambios para pedir misión por stampMision
	getAllMisiones() {
		let self = this;

		let parameters = {
			stampMision: self.mision.stampMision
		};
		ajaxComunCallWithCallback('getAllMisiones', parameters, function(ajaxReturn) {
			if(ajaxReturn) {
				let result = ajaxReturn.result;

				for(let i = 0; i < result.length; i++) {
					if(result[i].idmision == self.mision.idmision) {
						self.typeMision = result[i].tipomision;
						self.survey = result[i].sid;

						// Control de preguntas de misión de encuesta con validación
						if(result[i].isSurvey == '1') {
							self.getQuestionsSurvey();
						}

						break;
					}
				}

				self.getTypeMision();
			}
		});
	},

	getQuestionsSurvey() {
		let self = this;

		let parameters = {
			survey: self.survey
		};
		ajaxComunCallWithCallback('getQuestionsSurvey', parameters, function(ajaxReturn) {
			if(ajaxReturn) {
				self.questionsWithPictures = [];
				let size = ajaxReturn.result.length;
				for(let i = 0; i < size; i++) {
					if(ajaxReturn.result[i].type == '|' || ajaxReturn.result[i].type == '7' || ajaxReturn.result[i].type == 'J') {
						self.questionsWithPictures.push(ajaxReturn.result[i].columnName);
					}
				}

				if(self.questionsWithPictures.length > 0) {
					// Oculto por la implemetación del punto de JIRA: 3301
					$('#viewImages').show();
				}
			}
		});
	},

	getTypeMision() {
		let self = this;

		let parameters = {
			tipomision: self.typeMision
		};
		ajaxComunCallWithCallback('getAllTipoMisionObjetivos', parameters, function(ajaxReturn) {
			if(ajaxReturn) {
				self.idTypeMision = ajaxReturn.result[0].descripcion;

				self.requestProjectParticipants();
			}
		});
	},

	requestProjectParticipants() {
		let self = this;

		let sid = '0';
		if(self.mision.encuesta == '1') {
			sid = self.mision.sid;
		}

		if(self.mision.fechahorainicio.includes('#')) {
			let startDateArray = self.mision.fechahorainicio.split('/');
			let startYear = startDateArray[2].split('#');
			self.startDate = startYear[0] + '-' + startDateArray[1] + '-' + startDateArray[0] + ' ' + startYear[1] + ':' + startYear[2];
		} else {
			let startDateTimeArray = self.mision.fechahorainicio.split(' ');
			let startdateArray = startDateTimeArray[0].split('/');
			self.startDate = startdateArray[2] + '-' + startdateArray[1] + '-' + startdateArray[0] + ' ' + startDateTimeArray[1];
		}

		if(self.mision.fechahorafin.includes('#')) {
			let endDateArray = self.mision.fechahorafin.split('/');
			let endYear = endDateArray[2].split('#');
			self.endDate = endYear[0] + '-' + endDateArray[1] + '-' + endDateArray[0] + ' ' + endYear[1] + ':' + endYear[2];
		} else {
			let endDateTimeArray = self.mision.fechahorafin.split(' ');
			let endDateArray = endDateTimeArray[0].split('/');
			self.endDate = endDateArray[2] + '-' + endDateArray[1] + '-' + endDateArray[0] + ' ' + endDateTimeArray[1];
		}

		let parameters = {
			id: self.mision.idProject,
			sid: sid,
			mision: self.mision.stampMision,
			fechahorainicio: self.startDate,
			fechahorafin: self.endDate
		};
		ajaxComunCallWithCallback('getCMBPProjectsParticipantesValidacion', parameters, function(ajaxReturn) {
			if(ajaxReturn) {
				self.users = ajaxReturn.result;

				// De inicio todos desmarcados
				self.markAll = false;

				if(self.idTypeMision == '490'|| self.idTypeMision == '491') {
					self.isMisionValidatedLoadDatatables(self.users[0], 0);
				} else {
					// Tabla de participantes
					self.renderProjectParticipants();
				}
			}
		});
	},

	// Verifica que las misiones de video estén validadas y oculta 'Aceptar/Rechazar' en la tabla en caso de que así sea
	isMisionValidatedLoadDatatables(user, idButton) {
		let self = this;

		let parameters = {
			idmision: self.mision.idmision,
			users: user.idUser
		};
		ajaxComunCallWithCallback('isMisionValidated', parameters, function(ajaxReturn) {
			if(ajaxReturn) {
				if(ajaxReturn.result == 'false') {
					self.users[idButton]['validate'] = false;
				} else {
					self.users[idButton]['validate'] = true;
				}

				idButton++;
				if(idButton < self.users.length) {
					self.isMisionValidatedLoadDatatables(self.users[idButton], idButton);
				} else {
					self.renderProjectParticipants();
				}
			}
		});
	},

	renderProjectParticipants() {
		let self = this;

		if(self.markAll) {
			$('#markAll').addClass('d-none');
			$('#uncheckAll').removeClass('d-none');
		} else {
			$('#markAll').removeClass('d-none');
			$('#uncheckAll').addClass('d-none');
		}

		let table = `
			<table id="tableMissions" class="table table-hover tRegs">
				<thead>
					<tr>
						<th class="text-center" scope="col" title="">
							<div class="div-global-selection">
								<input type="checkbox" class="globalSelection">
							</div>
						</th>
						<th scope="col" title="${pf.const.language.RSC68}">${pf.const.language.RSC68}</th>
						<th scope="col" title="${pf.const.language.RSC564}">${pf.const.language.RSC564}</th>
						<th scope="col" title="${pf.const.language.RSC155}">${pf.const.language.RSC155}</th>
					</tr>
				</thead>

				<thead class="filtersResult">
					<tr>
						<td>selector</td>
						<td>user</td>
						<td>state</td>
						<td>see</td>
					</tr>
				</thead>

				<tbody>
		`;

		let size = self.users.length;
		for(let i = 0; i < size; i++) {
			let checkMission = false;
			let checkVideo = false;

			switch(self.idTypeMision) {
				case '480':
					// Chat unitario
					if(self.users[i].numMensajes != '0') {
						checkMission = true;
					}
					break;
				case '479':
					// Chat grupal
					if(self.users[i].numMensajes != '0') {
						checkMission = true;
					}
					break;
				case '485':
					// Foto Chat grupal
					if(self.users[i].numImages != '0') {
						checkMission = true;
					}
					break;
				case '486':
					// Foto Chat unitario
					if(self.users[i].numImages != '0') {
						checkMission = true;
					}
					break;
				case '490':
					// VideoCall grupal
					if(self.users[i].numVideoCall != '0') {
						checkMission = true;
						checkVideo = true;
					}
					break;
				case '491':
					// VideoCall unitaria
					if(self.users[i].numVideoCall != '0') {
						checkMission = true;
						checkVideo = true;
					}
					break;
				case '492':
					// VideoChat grupal
					if(self.users[i].numVideoCall != '0') {
						checkMission = true;
					}
					break;
				case '493':
					// VideoChat unitario
					if(self.users[i].numVideoCall != '0') {
						checkMission = true;
					}
					break;
				case '481':
					// Encuesta
					if(self.users[i].numSurveys != '0') {
						checkMission = true;
					}
					break;
				case '1041':
				case '1042':
				case '1234':
					// Pedido
					checkMission = true;
				default:
					break;
			}

			let eye = '';
			if(checkMission) {
				if(!checkVideo) {
					eye = `
						<button type="button" class="btn table-button main-color-text btn-see" data-id="${i}" data-toggle="modal" data-target="#modalMissions">
							${stcmbackend.svg.bigEyeWithoutColor}
						</button>
					`;
				} else {
					// Cambia el eye por 'Aceptar / Rechazar' directamente
					if(!self.users[i]['validate']) {
						eye = `
							<div id="${i}" class="buttons">
								<button type="button" class="btn btn-outline-secondary btn-confirm" data-id="${i}">${pf.const.language.RSC141}</button>
								<button type="button" class="btn btn-outline-secondary btn-refuse" data-id="${i}">${pf.const.language.RSC574}</button>
							</div>
						`;
					}
				}
			}

			// Control de rechazo o aceptación e input
			let iconControl = '';
			let spanControl = '';
			let inputMultiple = '';

			if(self.markAll) {
				inputMultiple = `
					<div class="div-single-selection">
						<input type="checkbox" class="selection" data-id="${self.users[i].idUser}" checked>
					</div>
				`;
			} else {
				inputMultiple = `
					<div class="div-single-selection">
						<input type="checkbox" class="selection" data-id="${self.users[i].idUser}">
					</div>
				`;
			}

			if(self.users[i].estado == '0') {
				// Rechazado
				iconControl = stcmbackend.svg.xLgRedWithoutColor;
				spanControl = 'Refuse';
				inputMultiple = '';
			} else if(self.users[i].estado == '1') {
				// Aceptado
				iconControl = stcmbackend.svg.checkLgGreenWithoutColor;
				spanControl = 'Accepted';
				inputMultiple = '';
			} else {
				// En espera
				iconControl = stcmbackend.svg.questionLgBlueWithoutColor;
				spanControl = 'Pending';
			}

			table += `
				<tr>
					<td class="text-center">
						${inputMultiple}
					</td>
					<td class="text-truncate c-pointer trSelect" title="${self.users[i].email}">${self.users[i].email}</td>
					<td class="text-center c-pointer trSelect" title="${spanControl}">
						<span class="d-none">${spanControl}</span>
						${iconControl}
					</td>
					<td class="text-center">
						<span class="d-none">-</span>
						${eye}
					</td>
				</tr>
			`;
		}

		table += `
				</tbody>
			</table>
		`;

		$('#tableMissionsContainer').html(table);

		// Setup - add a text input to each footer cell
		$('#tableMissions .filtersResult td').each(function() {
			let title = $(this).text();
			let value = `<input type="text" class="form-control form-control-sm">`;

			if(title === 'see' || title === 'validate' || title === 'refuse' || title === 'selector') {
				value = `<input type="text" class="form-control form-control-sm" disabled>`;
			} else if(title == 'state') {
				value = `
					<select class="form-control form-control-sm visualize">
						<option value="">${pf.const.language.RSC119}</option>
						<option value="Refuse">${pf.const.language.RSC1996}</option>
						<option value="Accepted">${pf.const.language.RSC1997}</option>
						<option value="Pending">${pf.const.language.RSC1998}</option>
					</select>
				`;
			}

			$(this).html(value);
		});

		let dataTable = $('#tableMissions').DataTable({
			retrieve: true,
			language: pf.const.language_table,
			pageLength: 25,
			autoWidth: false,
			columnDefs: [
				{width: '25px', orderable: false, targets: 0},
				{width: '80px', targets: 2},
				{width: '200px', orderable: false, 'targets': 3},
			],
			dom: 'Bfrtip',
			buttons: [{
				extend: 'excelHtml5',
				text: pf.const.language.RSC129,
				className: 'd-none',
				title: pf.const.language.RSC14,
				customize(xlsx) {
					dataTablesExcelCustomize(xlsx);
				}
			}],
			aaSorting: []
		});

		// Ocultar botones de tabla
		hideTableButtons('tableMissions');

		// Apply the search
		applyTheSearch(dataTable, 'filtersResult');

		// Exportar tabla
		$('#exportMissions').off().on('click', function() {
			$('#missionsTable .buttons-excel').trigger('click');
		});

		self.tableEvents();

		$('#tableMissions').on('draw.dt', function() {
			self.tableEvents();
		});
	},

	tableEvents() {
		let self = this;

		inputControl();

		$('.btn-see').off().on('click', function() {
			let id = $(this).data('id');
			let user = self.users[id];
			self.user = user;
			$('#inputRefuse').addClass('d-none');
			$('#buttons').removeClass('d-none');
			self.openModalValidate(user);
		});

		$('.btn-confirm').off().on('click', function() {
			let id = $(this).data('id');
			let parent = $(this).parent();
			let user = self.users[id];
			self.user = user;
			self.confirm();
			$(parent).addClass('d-none');
		});

		$('.btn-refuse').off().on('click', function() {
			let id = $(this).data('id');
			let parent = $(this).parent();
			let user = self.users[id];

			self.showMotivoRechazoAlert(function() {
				let reasonRejection = $('#reasonRejection').val().trim();

				if(reasonRejection != '') {
					// Rechazo de misión
					self.user = user;
					self.refuse(reasonRejection);
					$(parent).addClass('d-none');
				} else {
					$('#reasonRejection').addClass('is-invalid');
					return false;
				}
			});
		});

		// Seleccionar usuarios para aceptación/rechazo múltiple
		$('.selection').off().on('click', function() {
			let checkedComp = $(this).prop('checked');
			let idUser = $(this).data('id');

			if(checkedComp) {
				self.usersForAcceptRejectArray.push(idUser);
			} else {
				let index = self.usersForAcceptRejectArray.indexOf(idUser);
				self.usersForAcceptRejectArray.splice(index, 1);
			}

			inputControl();
		});

		// Seleccionar usuarios para aceptación/rechazo múltiple por <tr>
		$('.trSelect').off().on('click', function() {
			$(this).parent().find('.selection').trigger('click');
		});

		// Marcar desmarcar todo
		$('.globalSelection').off().on('change', function() {
			if($('.globalSelection').prop('checked')) {
				$('.selection').each(function() {
					if(!$(this).prop('checked')) {
						$(this).trigger('click');
					}
				});
			} else {
				$('.selection').each(function() {
					if($(this).prop('checked')) {
						$(this).trigger('click');
					}
				});
			}
		});

		// Seleccionar todos
		$('#markAll').off().on('click', function() {
			self.markAll = true;
			self.usersForAcceptRejectArray = [];

			let size = self.users.length;
			for(let i = 0; i < size; i++) {
				if(self.users[i].estado != '0' && self.users[i].estado != '1') {
					self.usersForAcceptRejectArray.push(self.users[i].idUser);
				}
			}

			self.renderProjectParticipants();
		});

		// Deseleccionar todos
		$('#uncheckAll').off().on('click', function() {
			self.markAll = false;
			self.usersForAcceptRejectArray = [];

			self.renderProjectParticipants();
		});

		function inputControl() {
			// Estado del input global con respecto a los inputs en página
			if($('.selection').length == $('.selection:checked').length && $('.selection').length > 0) {
				$('.globalSelection').prop('checked', true);
			} else {
				$('.globalSelection').prop('checked', false);
			}
		}
	},

	openModalValidate(user) {
		let self = this;

		switch(self.idTypeMision) {
			case '480':
				// Chat unitario
				self.modalChat(user, 'chat');
				break;
			case '479':
				// Chat grupal
				self.modalChat(user, 'group');
				break;
			case '485':
				// Foto Chat grupal
				self.modalChat(user, 'imageGroup');
				break;
			case '486':
				// Foto Chat unitario
				self.modalChat(user, 'image');
				break;
			case '490':
				// VideoCall grupal
				self.modalChat(user, 'videoGroup');
				break;
			case '491':
				// VideoCall unitaria
				self.modalChat(user, 'video');
				break;
			case '492':
				// VideoChat grupal
				self.modalChat(user, 'videoGroup');
				break;
			case '493':
				// VideoChat unitario
				self.modalChat(user, 'video');
				break;
			case '481':
				// Encuesta
				self.modalSurvey(user);
				break;
			case '1041':
			case '1042':
			case '1234':
			case '1861':
				// Pedido
				self.modalOrder(user);
			default:
				break;
		}
	},

	modalChat(user, type) {
		let self = this;

		let parameters = {
			fechaInicio: self.startDate,
			fechaFin: self.endDate,
			type: 'readValidate'
		};

		if(type == 'chat' || type == 'image') {
			parameters.jid = user.idUser;
			parameters.bid = self.project.LiderProyectoJID;
		} else if(type == 'group') {
			parameters.idgroup = self.project.ChatGrupalID;
		}

		ajaxComunCallWithCallback('getAnalyticsConversacion', parameters, function(ajaxReturn) {
			if(ajaxReturn) {
				self.messages = ajaxReturn.result;

				if(type == 'chat' || type == 'group') {
					self.printModalMessage(user.idUser);
				} else if(type == 'image' || type == 'imageGroup') {
					self.printModalMessage(user.idUser);
				} else if(type == 'video' || type == 'videoGroup') {
					self.printModalMessage(user.idUser);
				}

				self.isMisionValidated();
			}
		});
	},

	printModalMessage(idUser) {
		let self = this;

		let html = '';
		let size = self.messages.length;
		if(size > 0) {
			let table = `
				<table id="tableMessages" class="table table-hover tRegs">
					<thead>
						<tr>
							<th scope="col" title="${pf.const.language.RSC123}">${pf.const.language.RSC123}</th>
							<th scope="col" title="${pf.const.language.RSC164}">${pf.const.language.RSC164}</th>
							<th scope="col" title="${pf.const.language.RSC165}">${pf.const.language.RSC165}</th>
							<th scope="col" title="${pf.const.language.RSC166}">${pf.const.language.RSC166}</th>
							<th scope="col" title="${pf.const.language.RSC167}">${pf.const.language.RSC167}</th>
							<th scope="col" title="${pf.const.language.RSC168}">${pf.const.language.RSC168}</th>
							<th scope="col" title="${pf.const.language.RSC169}">${pf.const.language.RSC169}</th>
						</tr>
					</thead>

					<tbody>
			`;

			let eye = `
				<button type="button" class="btn table-button main-color-text loadFile viewFile">
					${stcmbackend.svg.bigEyeWithoutColor}
				</button>
			`;

			for(let i = 0; i < size; i++) {
				if(idUser == self.messages[i].jid) {
					let name = self.messages[i].nameUser + ' ' + self.messages[i].userApellidos + ' ' + self.messages[i].userApellidos2;

					let dateTime = self.messages[i].stampServer.split(' ');
					let date = dateTime[0];
					let time = dateTime[1];

					let attachment = false;
					if(self.messages[i].attachmentName != '' && self.messages[i].attachmentName.indexOf('.') != -1) {
						attachment = true;
					}

					table += `
						<tr id="s-${self.messages[i].stamp}">
							<td title="${name}">${name}</td>
							<td title="${(self.messages[i].msg != null ? self.messages[i].msg : '')}">${(self.messages[i].msg != null ? self.messages[i].msg : '')}</td>
							<td title="${date}">${date}</td>
							<td title="${time}">${time}</td>
							<td class="file" title="${(attachment ? self.messages[i].attachmentName : '')}">${(attachment ? self.messages[i].attachmentName : '')}</td>
							<td class="type" title="${self.messages[i].attachmentType}">${self.messages[i].attachmentType}</td>
							<td class="text-center">
								<span class="d-none">${(attachment ? pf.const.language.RSC120 : pf.const.language.RSC121)}</span>
								${(attachment ? eye : '')}
							</td>
						</tr>
					`;
				}
			}

			table += `
					</tbody>
				</table>
			`;

			$('#messages').html(table);

			let dataTable = $('#tableMessages').DataTable({
				retrieve: true,
				language: pf.const.language_table,
				paging: false,
				searching: false,
				autoWidth: false,
				columnDefs: [
					{width: '70px', targets: 2},
					{width: '50px', targets: 3},
					{width: '80px', targets: 6}
				],
				info: false,
				order: [[2, 'asc'], [3, 'asc']]
			});

			// Ocultar botones de tabla
			hideTableButtons('tableMessages');

			$('.viewFile').off().on('click', function() {
				$('#closeMissions').trigger('click');
				let file = $(this).parent().parent().find('.file').text();
				let type = $(this).parent().parent().find('.type').text();
				let stamp = $(this).parent().parent().attr('id').replace('s-', '');
				self.fileShow(file, type, stamp);
			});
		} else {
			html += pf.const.language.RSC573;
			$('#messages').html(html);
		}
	},

	fileShow(file, type, stamp) {
		let self = this;

		$('#attachmentViewer').show();
		$('#downloadAttachment').show();
		$('.attachmentContainer').html('');

		file = file.replace(/\"/g, '');

		let row = '';
		let size = self.messages.length;
		for(let i = 0; i < size; i++) {
			if(self.messages[i].stamp === stamp) {
				row = self.messages[i];
			}
		}

		let year = row.stampServer.substr(0, 4);
		let month = row.stampServer.substr(5, 2);
		let day = row.stampServer.substr(8, 2);
		let issuingUser = '';
		if(row.jid != '') {
			let issuing = row.jid.split('@');
			issuingUser = issuing[0];
		}
		let receivingUser = '';
		if(row.bid != '') {
			let receiving = row.bid.split('@');
			receivingUser = receiving[0];
		}

		if(self.idGroup !== '') {
			issuingUser = receivingUser;
		}

		let formatExt = type.split('/');
		let format = formatExt[0];

		let src = stcm.const.conversationFiles;

		let content = '';
		switch(format) {
			case 'image':
				src += 'imagenes/' + year + '/' + month + '/' + day + '/' + issuingUser + '/' + stamp + receivingUser + file;
				content = `<img src="${src}">`;
				break;
			case 'video':
				if(type === 'video/quicktime') {
					let fileLastDot = file.lastIndexOf('.');
					file = file.substr(0, fileLastDot);
					file += '.mp4';
					type = 'video/mp4';
				}
				src += 'video/' + year + '/' + month + '/' + day + '/' + issuingUser + '/' + stamp + receivingUser + file;
				content = `
					<video controls>
						<source src="${src}" type="${type}">
					</video>
				`;
				break;
			case 'audio':
				src += 'audio/' + year + '/' + month + '/' + day + '/' + issuingUser + '/' + stamp + receivingUser + file;
				content = `
					<audio controls>
						<source src="${src}" type="${type}">
					</audio>
				`;
				break;
			case 'application':
				src += 'docs/' + year + '/' + month + '/' + day + '/' + issuingUser + '/' + stamp + receivingUser + file;
				content = `
					<object data="${src}" type="${type}" width="100%" height="100%">
						<p>${pf.const.language.RSC173}</p>
						<p>${pf.const.language.RSC174}</p>
					</object>
				`;
				break;
			default:
				content = '';
		}

		$('.attachmentContainer').html(content);

		$('#downloadAttachment').off().on('click', function(e) {
			e.preventDefault();
			self.createFileServer(src, file);
		});

		$('#closeAttachment').off().on('click', function() {
			$('#attachmentViewer').hide();
			//recargar tabla modal
			$('#modalMissions').modal('show');
		});
	},

	createFileServer(url, file) {
		let self = this;

		let client = JSON.parse(sessionStorage['STCMBackEnd:user']);
		let mail = client.email.split('@');
		let user = mail[0].replace('.', '_');

		let parameters = {
			url: url,
			file: file,
			user: user
		};
		ajaxComunCallWithCallbackOne('getAttachedConversation', parameters, function(ajaxReturn) {
			if(ajaxReturn) {
				let resp = JSON.parse(ajaxReturn.resData.response);
				let src = stcm.const.downloads + resp.file
				let link = document.createElement('a');
				link.href = src;
				link.download = file;
				document.body.appendChild(link);
				link.click();
				document.body.removeChild(link);
				self.deleteFile(resp.file);
			}
		});
	},

	// Borrado de archivo
	deleteFile(file) {
		let parameters = {
			filename: file
		};
		ajaxComunCallWithCallbackVoid('deleteFile', parameters);
	},

	modalSurvey(user) {
		let self = this;

		let parameters = {
			survey: self.survey,
			numPreguntasPerfilacionEnAnalyticMostreo: 3,
			userToken: user.email,
			continuingMission: self.mision.continuingMission
		};
		ajaxComunCallWithCallback('getSurveyByUser', parameters, function(ajaxReturn) {
			if(ajaxReturn) {
				self.answerByUser = ajaxReturn.result;

				self.printSurveyByUser();
				self.isMisionValidated();
			}
		});
	},

	printSurveyByUser() {
		let self = this;

		let html = '';
		$('#expCollAll').show();

		let size = self.answerByUser.length;
		for(let i = 0; i < size; i++) {
			let eyeHead = '';
			if(self.answerByUser[i].type == '|' || self.answerByUser[i].type == '7' || self.answerByUser[i].type == 'J') {
				eyeHead = `<th scope="col" title="${pf.const.language.RSC169}">${pf.const.language.RSC169}</th>`;
			}

			// Columna para fecha de envío en caso de misiones continuas
			let submitDateHead = '';
			if(self.mision.continuingMission == '1') {
				submitDateHead = `
					<th scope="col" title="${pf.const.language.RSC2344}">${pf.const.language.RSC2344}</th>
				`;
			}

			let table = `
				<thead>
					<tr>
						<th scope="col" title="${pf.const.language.RSC2411}">${pf.const.language.RSC2411}</th>
						${submitDateHead}
						<th scope="col" title="${pf.const.language.RSC127}">${pf.const.language.RSC127}</th>
						<th scope="col" title="${pf.const.language.RSC128}">${pf.const.language.RSC128}</th>
						${eyeHead}
					</tr>
				</thead>

				<tbody>
			`;

			let sizeAnswers = self.answerByUser[i].answer.length;
			for(let j = 0; j < sizeAnswers; j++) {
				let eyeBody = '';
				if((self.answerByUser[i].type == '|' || self.answerByUser[i].type == '7' || self.answerByUser[i].type == 'J') && self.answerByUser[i].answer[j].answerothers != '') {
					eyeBody = `
						<td class="text-center" data-file="${self.answerByUser[i].answer[j].answerothers}">
							<span class="d-none">Si</span>
							<button type="button" class="btn table-button main-color-text loadFile viewFile">
								${stcmbackend.svg.bigEyeWithoutColor}
							</button>
						</td>
					`;
				} else if(self.answerByUser[i].type == '|' || self.answerByUser[i].type == '7' || self.answerByUser[i].type == 'J') {
					eyeBody = `
						<td class="text-center">
							<span class="d-none">No</span>
						</td>
					`;
				}

				// Columna para fecha de envío en caso de misiones continuas
				let submitDateBody = '';
				if(self.mision.continuingMission == '1') {
					submitDateBody = `
						<td class="text-truncate" title="${self.answerByUser[i].answer[j].submitDate}">${self.answerByUser[i].answer[j].submitDate}</td>
					`;
				}

				table += `
				<tr>
					<td class="text-truncate" title="${self.answerByUser[i].answer[j].userEmail}">${self.answerByUser[i].answer[j].userEmail}</td>
					${submitDateBody}
					<td class="text-truncate" title="${(self.answerByUser[i].answer[j].answer == 'Others' ? '' : self.answerByUser[i].answer[j].answer)}">${(self.answerByUser[i].answer[j].answer == 'Others' ? '-' : self.answerByUser[i].answer[j].answer)}</td>
					<td class="text-truncate" title="${self.answerByUser[i].answer[j].answerothers}">${(self.answerByUser[i].answer[j].answerothers == '' ? '-' : self.answerByUser[i].answer[j].answerothers)}</td>
					${eyeBody}
				</tr>
			`;
			}

			table += `
				</tbody>
			`;

			html += `
				<div class="modal-content glass-efect-validation ma-bo-20">
					<div class="modal-header d-flex align-items-center justify-content-between c-pointer">
						<div class="d-flex align-items-center">
							<div class="circle-count">
								<span>${i + 1}</span>
							</div>
							<!-- Título de sección -->
							<span class="section-title title-secondary">${self.answerByUser[i].question}</span>
						</div>

						<!-- Botón Collapse -->
						<button type="button" class="btn btn-link text-body text-decoration-none arrow" data-toggle="collapse" data-target="#collap${i}" data-arrow="left" data-sub="1">
							${stcmbackend.svg.chevronRight}
						</button>
					</div>

					<div id="collap${i}" class="modal-body collapse collapseConf">
						<table id="table${i}" class="table table-hover tRegs">
							${table}
						</table>
					</div>
				</div>
			`;
		}

		$('#messages').html(html);

		for(let t = 0; t < size; t++) {
			let columnDefs = [];

			// Columna otros
			if(self.mision.continuingMission == '1') {
				columnDefs.push({width: '180px', targets: 1});
				columnDefs.push({width: '150px', targets: 3});
			} else {
				columnDefs.push({width: '150px', targets: 2});
			}

			// Visualizar imágenes
			if(self.answerByUser[t].type == '|' || self.answerByUser[t].type == '7' || self.answerByUser[t].type == 'J') {
				if(self.mision.continuingMission == '1') {
					columnDefs.push({width: '80px', targets: 4});
				} else {
					columnDefs.push({width: '80px', targets: 3});
				}
			}

			let table = $('#table' + t).DataTable({
				language: pf.const.language_table,
				retrieve: true,
				autoWidth: false,
				paging: false,
				searching: false,
				ordering: false,
				info: false,
				columnDefs: columnDefs,
				aaSorting: []
			});

			// Ocultar botones de tabla
			hideTableButtons('table' + t);
		}

		$('.viewFile').off().on('click', function() {
			$('#closeMissions').trigger('click');
			let file = $(this).parent().data('file');
			self.fileShowSurvey(file, true);
		});

		// Collapse general en inicio
		directionOrigin = stcmbackend.svg.chevronRight + `<span class="ma-le-3">${pf.const.language.RSC988}</span>`;
		$('#expCollAll').html(directionOrigin);
		$('#expCollAll').data('arrow', 'left');

		// Collapse
		addEventArrowTableHeader();

		// Collapse all
		$('#expCollAll').off().on('click', function() {
			let arrow = $(this).data('arrow');
			let direction = '';
			if(arrow == 'left') {
				direction = stcmbackend.svg.chevronDown + `<span class="ma-le-3">${pf.const.language.RSC989}</span>`;
				let directionAll = stcmbackend.svg.chevronDown;
				$(this).data('arrow', 'down');
				$('.collapseConf').data('arrow', 'down');
				$('.collapseConf').collapse('show');
				$('.arrow').html(directionAll);
				$('.arrow').data('arrow', 'down');
			} else {
				direction = stcmbackend.svg.chevronRight + `<span class="ma-le-3">${pf.const.language.RSC988}</span>`;
				let directionAll = stcmbackend.svg.chevronRight;
				$(this).data('arrow', 'left');
				$('.collapseConf').data('arrow', 'left');
				$('.collapseConf').collapse('hide');
				$('.arrow').html(directionAll);
				$('.arrow').data('arrow', 'left');
			}
			$(this).html(direction);
		});

		// Si todos los collapse están a la izquierda o a abajo, cambio del collapse general
		$('.arrow').on('click', function() {
			let direction = '';
			if($('.arrow').length == $('.arrow[data-arrow="left"]').length) {
				direction = stcmbackend.svg.chevronRight + `<span class="ma-le-3">${pf.const.language.RSC988}</span>`;
				$('#expCollAll').html(direction);
				$('#expCollAll').attr('data-arrow', 'left');
			} else if($('.arrow').length == $('.arrow[data-arrow="down"]').length) {
				direction = stcmbackend.svg.chevronDown + `<span class="ma-le-3">${pf.const.language.RSC989}</span>`;
				$('#expCollAll').html(direction);
				$('#expCollAll').attr('data-arrow', 'down');
			}
		});
	},

	fileShowSurvey(file, table) {
		let self = this;

		$('#attachmentViewer').show();
		$('.attachmentContainer').html('');

		let url = self.loadIMG + `/upload/surveys/${self.survey}/files/`;
		let dot = file.lastIndexOf('.');

		let imgName = file.substring(0, dot);
		let ext = file.substring(dot + 1).toLowerCase();

		if(dot === -1) {
			imgName = file;
			ext = '';
		}

		let content = '';
		if(ext == 'mp4' || ext == 'mp3' || ext == 'avi' || ext == 'mov') {
			content = `<video id="videoRep" src="${url + imgName}" type="video/${ext}" controls></video>`;
		} else if(ext == 'pdf') {
			let src = url + imgName;

			content = `<embed src="${src}" type="application/pdf" width="100%" height="100%">`;
		} else {
			content = `<img src="${url + imgName}"></img>`;
		}

		$('.attachmentContainer').html(content);
		$('#downloadAttachment').hide();

		if(table) {
			$('#closeAttachment').off().on('click', function() {
				if(ext == 'mp4' || ext == 'mp3' || ext == 'avi' || ext == 'mov') {
					let vid = document.getElementById('videoRep');
					vid.pause();
				}
				$('#attachmentViewer').hide();
				// Volver a mostrar el modal
				$('#modalMissions').modal('show');
			});
		} else {
			$('#modalPictures').modal('hide');

			$('#closeAttachment').off().on('click', function() {
				$('#attachmentViewer').hide();
				// Volver a mostrar el modal
				$('#modalPictures').modal('show');
			});
		}
	},

	modalOrder(user) {
		let self = this;

		let startDateArray = self.startDate.split(' ');
		let startDate = startDateArray[0];

		let endDateArray = self.endDate.split(' ');
		let endDate = endDateArray[0];

		let usernameArray = user.idUser.split('@');
		let username = usernameArray[0];

		let parameters = {
			startDate: startDate,
			endDate: endDate,
			username: username
		};
		ajaxComunCallWithCallback('getOrdersByUser', parameters, function(ajaxReturn) {
			if(ajaxReturn) {
				self.answerByUser = ajaxReturn.result;

				self.printOrderByUser();
				self.isMisionValidated();
			}
		});
	},

	printOrderByUser() {
		let self = this;

		let html = '';
		$('#expCollAll').hide();
		let size = self.answerByUser.length;
		if(size > 0) {
			let table = `
				<table id="tableMessagesVal" class="table table-hover tRegs h-100">
					<thead>
						<tr>
							<th scope="col" title="${pf.const.language.RSC1673}">${pf.const.language.RSC1673}</th>
							<th scope="col" title="${pf.const.language.RSC178}">${pf.const.language.RSC178}</th>
							<th scope="col" title="${pf.const.language.RSC1674}">${pf.const.language.RSC1674}</th>
							<th scope="col" title="${pf.const.language.RSC1675}">${pf.const.language.RSC1675}</th>
							<th scope="col" title="${pf.const.language.RSC1676}">${pf.const.language.RSC1676}</th>
						</tr>
					</thead>

					<tbody>
			`;

			for(let i = 0; i < size; i++) {
				let sizePro = self.answerByUser[i].products.length;

				for(let j = 0; j < sizePro; j++) {
					table += `
						<tr>
							<td title="${self.answerByUser[i].products[j].code}">${self.answerByUser[i].products[j].code}</td>
							<td title="${self.answerByUser[i].products[j].description}">${self.answerByUser[i].products[j].description}</td>
							<td title="${self.answerByUser[i].products[j].idcodebar}">${self.answerByUser[i].products[j].idcodebar}</td>
							<td title="${self.answerByUser[i].products[j].price}">${self.answerByUser[i].products[j].price}</td>
							<td title="${self.answerByUser[i].products[j].quantity}">${self.answerByUser[i].products[j].quantity}</td>
						</tr>
					`;
				}
			}

			table += `
					</tbody>
				</table>
			`;

			$('#messages').html(table);

			let dataTable = $('#tableMessagesVal').DataTable({
				retrieve: true,
				autoWidth: false,
				columnDefs: [
					{width: '160px', targets: 0},
					{width: '135px', targets: 2},
					{width: '75px', targets: 3},
					{width: '80px', targets: 4}
				],
				paging: false,
				searching: false,
				language: pf.const.language_table,
				info: false,
			});

			// Ocultar botones de tabla
			hideTableButtons('tableMessagesVal');
		} else {
			html += pf.const.language.RSC573;
			$('#messages').html(html);
		}
	},

	isMisionValidated() {
		let self = this;

		let parameters = {
			idmision: self.mision.idmision,
			users: self.user.idUser
		};
		ajaxComunCallWithCallback('isMisionValidated', parameters, function(ajaxReturn) {
			if(ajaxReturn) {
				if(ajaxReturn.result == 'false') {
					$('#buttons').show();
				} else {
					$('#buttons').hide();
				}
			}
		});
	},

	getFilesRecordedByProject() {
		let self = this;

		let idProject = sessionStorage['idProject'];

		let parameters = {
			idProject: idProject
		};
		ajaxComunCallWithCallback('getFilesRecordedByProject', parameters, function(ajaxReturn) {
			if(ajaxReturn) {
				self.filesRecorded = ajaxReturn.result;

				// Tabla de video llamadas
				self.renderFilesRecorded();
			}
		});
	},

	renderFilesRecorded() {
		let self = this;

		let table = `
			<thead>
				<tr>
					<th scope="col" title="${pf.const.language.RSC165}">${pf.const.language.RSC165}</th>
					<th scope="col" title="${pf.const.language.RSC1311}">${pf.const.language.RSC1311}</th>
					<th scope="col" title="${pf.const.language.RSC1312}">${pf.const.language.RSC1312}</th>
					<th scope="col" title="${pf.const.language.RSC1313}">${pf.const.language.RSC1313}</th>
				</tr>
			</thead>

			<thead class="filtersRecorded">
				<tr>
					<td>fecha</td>
					<td>grabacion</td>
					<td>duracion</td>
					<td>tamaño</td>
				</tr>
			</thead>

			<tbody>
		`;

		let size = self.filesRecorded.length;
		for(let i = 0; i < size; i++) {
			let url = self.filesRecorded[i].recordedFilePath + '/' + self.filesRecorded[i].recordedFileName;
			let size = self.filesRecorded[i].recordedFileTotalSize + ' ' + self.filesRecorded[i].recordedFileTotalSizeUnit;

			let camara = `<span class="d-none">${pf.const.language.RSC121}</span>`;
			if(self.filesRecorded[i].recorded == '1') {
				camara = `
					<span class="d-none">${pf.const.language.RSC120}</span>
					<span class="c-pointer viewVideo" data-url="${url}" data-file="${self.filesRecorded[i].recordedFileName}">
						${stcmbackend.svg.cameraVideoFillRedWithoutColor}
					</span>
				`;
			}

			table += `
				<tr>
					<td class="text-truncate" title="${self.filesRecorded[i].stampServer}">${self.filesRecorded[i].stampServer}</td>
					<td class="text-truncate text-center">
						${camara}
					</td>
					<td class="text-truncate" title="${self.filesRecorded[i].recordedFilePartDuration}">${self.filesRecorded[i].recordedFilePartDuration}</td>
					<td class="text-truncate" title="${size}">${size}</td> 
				</tr>
			`;
		}

		table += `
			</tbody>
		`;

		$('#tableVideoLlamadas').html(table);

		// Setup - add a text input to each footer cell
		$('#tableVideoLlamadas .filtersRecorded td').each(function() {
			let title = $(this).text();
			let value = `<input type="text" class="form-control form-control-sm">`;

			if(title === 'grabacion') {
				value = optionsSelectAllYesNo();
			}

			$(this).html(value);
		});

		let recordedTable = $('#tableVideoLlamadas').DataTable({
			retrieve: true,
			language: self.language,
			pageLength: 5,
			autoWidth: false,
			columnDefs: [
				{width: '80px', targets: 1}
			],
			dom: 'Bfrtip',
			buttons: [{
				extend: 'excelHtml5',
				text: pf.const.language.RSC194,
				className: 'd-none',
				title: pf.const.language.RSC194,
				customize(xlsx) {
					dataTablesExcelCustomize(xlsx);
				}
			}],
			aaSorting: []
		});

		// Ocultar botones de tabla
		hideTableButtons('tableVideoLlamadas');

		// Apply the search
		applyTheSearch(recordedTable, 'filtersRecorded');

		// Exportar tabla
		$('#exportVideoLlamadas').off().on('click', function() {
			$('#videoLlamadasTable .buttons-excel').trigger('click');
		});

		self.tableVideoLlamadasEvents();

		$('#tableVideoLlamadas').on('draw.dt', function() {
			self.tableVideoLlamadasEvents();
		});
	},

	tableVideoLlamadasEvents() {
		let self = this;

		$('.viewVideo').off().on('click', function() {
			let url = $(this).data('url');
			let file = $(this).data('file');

			$('#attachmentViewer').show();
			$('.attachmentContainer').html('');

			content = `
				<video controls>
					<source src="${url}">
				</video>
			`;

			$('.attachmentContainer').html(content);

			$('#downloadAttachment').off().on('click', function(e) {
				e.preventDefault();
				self.createFileServer(url, file);
			});

			$('#closeAttachment').off().on('click', function() {
				$('#attachmentViewer').hide();
			});
		});
	},

	getSurveysFilesByQuestion() {
		let self = this;

		let qid = self.questionsWithPictures.join();

		let parameters = {
			qid: qid,
			mision: self.mision.idmision
		};
		ajaxComunCallWithCallback('getSurveysFilesByQuestion', parameters, function(ajaxReturn) {
			if(ajaxReturn) {
				self.galleries = ajaxReturn.result;

				// Modal de galería
				self.renderGallery();
			}
		});
	},

	renderGallery() {
		let self = this;

		self.userPicturesArray = [];
		self.userPicturesRefuse = [];
		self.picturesArray = [];

		// Control por si las imágenes ya han sido procesadas con OCR
		let processedImagesOCR = false;

		let thereArePictures = false;
		let gallery = '';
		let index = 0;
		for(let question in self.galleries) {
			let size = self.galleries[question].users.length;
			if(size == 0) {
				continue;
			}

			let galleryElements = `<div class="d-flex flex-row flex-wrap">`;

			for(let i = 0; i < size; i++) {
				// Si no hay imagen que pase a la siguiente
				if(self.galleries[question].users[i].file == '') {
					continue;
				}

				// Controlar si hay imágenes
				if(!thereArePictures && self.galleries[question].users[i].fileType == 'image') {
					thereArePictures = true;
				}

				// Array de usuarios
				if(self.userPicturesArray.indexOf(self.galleries[question].users[i].jid) === -1) {
					self.userPicturesArray.push(self.galleries[question].users[i].jid);
				}

				let file = self.loadIMG + `/upload/surveys/${self.survey}/files/` + self.galleries[question].users[i].file;

				let dNone = 'd-none';
				if(self.galleries[question].users[i].procesedImageRecognition == '1') {
					dNone = '';
				} else if(self.galleries[question].users[i].fileType == 'image') {
					// Se guardan solo las imágenes que no se han procesado
					self.picturesArray.push(file);
				}

				let dNoneOCR = 'd-none';
				if(self.galleries[question].users[i].procesedImageOCR == '1') {
					dNoneOCR = '';
					processedImagesOCR = true;
				}

				// Dependiendo del tipo, imagen subida o imagen guardada
				let src = '';
				if(self.galleries[question].users[i].fileType == 'image') {
					src = self.loadIMG + `/upload/surveys/${self.survey}/files/thumb/${self.galleries[question].users[i].file}_thumb`;
				} else if(self.galleries[question].users[i].fileType == 'video') {
					src = stcm.const.downloads + 'icons/VID_160pxH.jpg';
				} else if(self.galleries[question].users[i].fileType == 'pdf') {
					src = stcm.const.downloads + 'icons/PDF_160pxH2.jpg';
				}

				galleryElements += `
					<div class="p-1 wi-20per">
						<div id="element${i}" class="surveyImage c-pointer position-relative" data-user="${self.galleries[question].users[i].jid}" data-image="${self.galleries[question].users[i].file}" data-menuid="contextMenu${i}">
							<img src="${src}" class="w-100 surveyImageImg he-160 ob-fit-cove">

							<div class="btn-eye" style="position: absolute; display: none; bottom: 10px; right: 10px; border-radius: 50%;">
								${stcmbackend.svg.checkBigCircleWithoutColor}
							</div>

							<div class="text-center pb-1 viewData ${dNone}" data-image="${file}" style="position: absolute; top: 10px; left: 10px; border-radius: 50%; background-color: #fff; width: 28px;">
								${stcmbackend.svg.robot}
							</div>

							<div class="text-center pb-1 viewDataOCR ${dNoneOCR}" data-image="${self.galleries[question].users[i].file}" style="position: absolute; top: 10px; left: 40px; border-radius: 50%; background-color: #fff; width: 28px;">
								<i class="fa-solid fa-text pt-2 fs-13"></i>
							</div>

							<div id="dropdownMenuButton${i}" class="product_menu_c border text-center c-pointer" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
								${stcmbackend.svg.threeDotsVerticalBig}
							</div>

							<div class="dropdown-menu dropdown-menu-right shadow" aria-labelledby="dropdownMenuButton${i}">
								<p class="dropdown-item userMail c-default text-center font-weight-bold mb-1">
									${stcmbackend.svg.envelope}
									<span>${self.galleries[question].users[i].token}</span>
								</p>
								<a href="#" class="dropdown-item copyEmail">
									${stcmbackend.svg.clipboard}
									<span>${pf.const.language.RSC2121}</span>
								</a>
								<a href="#" class="dropdown-item viewImage" data-element="${self.galleries[question].users[i].file}" data-ext="${self.galleries[question].users[i].fileExtension}">
									${stcmbackend.svg.image}
									<span>${pf.const.language.RSC2437}</span>
								</a>
								<a href="#" class="dropdown-item viewData ${dNone}" data-image="${file}">
									${stcmbackend.svg.robot}
									<span>${pf.const.language.RSC2201}</span>
								</a>
								<a href="#" class="dropdown-item viewDataOCR ${dNoneOCR}" data-image="${self.galleries[question].users[i].file}">
									<i class="fa-solid fa-text"></i>
									<span>${pf.const.language.RSC2317}</span>
								</a>
							</div>
						</div>
					</div>
				`;
			}

			galleryElements += `
				</div>
			`;

			gallery += `
				<div class="card glass-efect-validation mb-2">
					<div class="card-header d-flex align-items-center justify-content-between c-pointer bo-bo-no">
						<!-- Título de sección -->
						<span class="section-titleG title-secondary">${self.galleries[question].title}</span>

						<!-- Botón Collapse -->
						<button type="button" class="btn btn-link text-body text-decoration-none arrowG ml-auto mb-auto" data-toggle="collapse" data-target="#collapG${index}" data-arrow="right">
							${stcmbackend.svg.chevronRight}
						</button>
					</div>

					<div id="collapG${index}" class="card-body collapse collapseConf">
						${galleryElements}
					</div>
				</div>
			`;

			index++;
		}

		$('#bodyPictures').html(gallery);

		if(thereArePictures) {
			$('#identifyDuplicatePhotos').removeClass('disabled');
		} else {
			$('#identifyDuplicatePhotos').addClass('disabled');
		}

		if(self.picturesArray.length > 0) {
			$('#processImage').removeClass('disabled');
		} else {
			$('#processImage').addClass('disabled');
		}

		if(processedImagesOCR) {
			$('#processImageOCR').addClass('disabled');
		} else {
			$('#processImageOCR').removeClass('disabled');
		}

		// Collapse
		// Para abarcar todo el título
		$('.section-titleG').parent().off().on('click', function() {
			$(this).find('.arrowG').trigger('click');
		});

		$('.arrowG').on('click', function(event) {
			// Evitar la propagación
			event.stopPropagation();
			
			let arrow = $(this).data('arrow');
			let direction = '';
			if(arrow == 'right') {
				direction = stcmbackend.svg.chevronDown;
				$(this).data('arrow', 'down');
			} else {
				direction = stcmbackend.svg.chevronRight;
				$(this).data('arrow', 'right');
			}
			$(this).html(direction);
			$(this).parent().parent().find('.collapse').collapse('toggle');
		});

		$('#refuseCount').hide();
		$('#refuseCount').text('0 / ' + self.userPicturesArray.length);

		// Control de imágenes a rechazar
		$('.surveyImageImg').off().on('click', function() {
			let user = $(this).parent().data('user');

			let pictureFilter = $(this).parent().find('img').css('filter');

			if(pictureFilter == 'none') {
				$(this).parent().find('img').css('filter', 'grayscale(100%)');
				$(this).parent().find('.btn-eye').show();
				if(self.userPicturesRefuse.indexOf(user) === -1) {
					self.userPicturesRefuse.push(user);

					$('.surveyImage').each(function() {
						let oUser = $(this).data('user');

						if(oUser == user) {
							$(this).parent().find('img').css('filter', 'grayscale(100%)');
							$(this).parent().find('.btn-eye').show();
						}
					});
				}
			} else {
				$(this).parent().find('img').css('filter', 'none');
				$(this).parent().find('.btn-eye').hide();
				let index = self.userPicturesRefuse.indexOf(user);
				self.userPicturesRefuse.splice(index, 1);

				$('.surveyImage').each(function() {
					let oUser = $(this).data('user');

					if(oUser == user) {
						$(this).parent().find('img').css('filter', 'none');
						$(this).parent().find('.btn-eye').hide();
					}
				});
			}

			if(self.userPicturesRefuse.length > 0) {
				$('#refusePictures').prop('disabled', false);
				$('#refuseCount').text(self.userPicturesRefuse.length + ' / ' + self.userPicturesArray.length);
			} else {
				$('#refusePictures').prop('disabled', true);
				$('#refuseCount').hide();
			}
		});

		// Copiar correo en portapapeles
		$('.copyEmail').on('click', function(e) {
			e.preventDefault();
			let mail = $(this).parent().find('.userMail').text();

			navigator.clipboard.writeText(mail).then(() => {
				console.log('Text copied to clipboard...');
			}).catch(err => {
				console.log('Something went wrong', err);
			});
		});

		// Ver imagen
		$('.viewImage').on('click', function(e) {
			e.preventDefault();

			let element = $(this).data('element');
			let ext = $(this).data('ext');
			let file = element + '.' + ext;

			self.fileShowSurvey(file, false);
		});

		// Ver información de la imagen
		$('.viewData').on('click', function(e) {
			e.preventDefault();

			let file = $(this).data('image');

			let parameters = {
				urlImage: file
			};
			ajaxComunCallWithCallback('getFotoAnalizedData', parameters, function(ajaxReturn) {
				if(ajaxReturn) {
					$('#infoModal').modal('show');

					// Ocultar modal de validación de imágenes
					$('#modalPictures').modal('hide');

					// Modal de información de imagen
					self.renderImageInfo(ajaxReturn.result[0]);
				}
			});
		});

		// Ver información de la imagen OCR
		$('.viewDataOCR').on('click', function(e) {
			e.preventDefault();

			let file = $(this).data('image');

			let parameters = {
				fileName: file
			};
			ajaxComunCallWithCallback('getImageDataOCRProcessed', parameters, function(ajaxReturn) {
				if(ajaxReturn) {
					$('#infoModal').modal('show');

					// Ocultar modal de validación de imágenes
					$('#modalPictures').modal('hide');

					// Guardar valores de imagen
					$('#saveCorrection').data('img', file);
					$('#saveCorrection').data('capture', ajaxReturn.result[0].idCapture);

					// Modal de información de imagen
					self.renderImageInfoOCR(ajaxReturn.result, ajaxReturn.file);
				}
			});
		});

		// Quitar dropdown menú por movimiento de scroll
		$('#bodyPictures').scroll(function() {
			$('.dropdown-menu').dropdown('hide');
		});
	},

	confirm() {
		let self = this;

		// Se ha validado la mision
		let textMision = pf.const.language.RSC576 + ' ' + self.mision.idmision;

		let parameters = {
			mision: self.mision.idmision,
			idUser: self.user.idUser,
			importe: self.mision.importe,
			textMision: textMision,
			from: self.project.LiderProyectoJID,
			survey: self.survey,
			stampMission: self.mision.stampMision,
			currency: self.mision.currency,
			project: self.project.id
		};
		ajaxComunCallWithCallback('validateMission', parameters, function(ajaxReturn) {
			if(ajaxReturn) {
				let infoTitle = pf.const.language.RSC177;
				let infoContent = pf.const.language.RSC576;
				pf.utils.showInfoDialog(infoTitle, infoContent);
				$('#closeMissions').trigger('click');

				setTimeout(function() {
					loadHTML('inc/proyectos/proyectos_validate.html', 'wrapper', self);
				}, 400);
			}
		});
	},

	refuse(reasonRejec = null) {
		let self = this;

		// Se ha rechazado la mision
		let textMision = pf.const.language.RSC577 + ' ' + self.mision.idmision;

		let reasonRejection = '';
		if(reasonRejec === null) {
			reasonRejection = $('#refuseReasons').val().trim();

			if(reasonRejection == '') {
				$('#refuseReasons').addClass('is-invalid');
				return;
			} else {
				$('#refuseReasons').removeClass('is-invalid');
			}
		} else {
			reasonRejection = reasonRejec;
		}

		let parameters = {
			mision: self.mision.idmision,
			idUser: self.user.idUser,
			textMision: textMision,
			from: self.project.LiderProyectoJID,
			motivos: reasonRejection,
			userAdmin: self.userAdmin,
			project: self.project.id
		};
		ajaxComunCallWithCallback('refuseMission', parameters, function(ajaxReturn) {
			if(ajaxReturn) {
				let errorTitle = pf.const.language.RSC14;
				let errorContent = pf.const.language.RSC577;
				pf.utils.showInfoDialog(errorTitle, errorContent);
				$('#closeMissions').trigger('click');

				setTimeout(function() {
					loadHTML('inc/proyectos/proyectos_validate.html', 'wrapper', self);
				}, 400);
			}
		});
	},

	// Rechazo de asesores a través de galería de imágenes
	setMisionValidationMultiple(reason) {
		let self = this;

		let textMision = pf.const.language.RSC577 + ' ' + self.mision.idmision;
		let reasonRejection = reason;

		let parameters = {
			mision: self.mision.idmision,
			idUser: JSON.stringify(self.userPicturesRefuse),
			textMision: textMision,
			from: self.project.LiderProyectoJID,
			motivos: reasonRejection,
			userAdmin: self.userAdmin,
			project: self.project.id
		};
		ajaxComunCallWithCallback('setMisionValidationMultiple', parameters, function(ajaxReturn) {
			if(ajaxReturn) {
				let errorTitle = pf.const.language.RSC14;
				let errorContent = pf.const.language.RSC577;
				pf.utils.showInfoDialog(errorTitle, errorContent);

				$('#closePictures').trigger('click');
				removeLoader();
				setTimeout(function() {
					loadHTML('inc/proyectos/proyectos_validate.html', 'wrapper', self);
				}, 400);
			}
		});
	},

	// Validación múltiple
	validateMissionMultiple() {
		let self = this;

		// Se ha validado la mision
		let textMision = pf.const.language.RSC576 + ' ' + self.mision.idmision;

		let parameters = {
			mision: self.mision.idmision,
			idUser: JSON.stringify(self.usersForAcceptRejectArray),
			importe: self.mision.importe,
			textMision: textMision,
			from: self.project.LiderProyectoJID,
			survey: self.survey,
			stampMission: self.mision.stampMision,
			currency: self.mision.currency,
			project: self.project.id
		};
		ajaxComunCallWithCallback('validateMissionMultiple', parameters, function(ajaxReturn) {
			if(ajaxReturn) {
				let infoTitle = pf.const.language.RSC177;
				let infoContent = pf.const.language.RSC576;
				pf.utils.showInfoDialog(infoTitle, infoContent);

				setTimeout(function() {
					loadHTML('inc/proyectos/proyectos_validate.html', 'wrapper', self);
				}, 400);
			}
		});
	},

	printMessages(idUser) {
		let self = this;

		let html = '';
		let size = self.messages.length;
		if(size > 0) {
			let table = `
				<table id="tableMessagesVal" class="table table-hover tRegs h-100">
					<thead>
						<tr>
							<th scope="col" title="${pf.const.language.RSC123}">${pf.const.language.RSC123}</th>
							<th scope="col" title="${pf.const.language.RSC164}">${pf.const.language.RSC164}</th>
							<th scope="col" title="${pf.const.language.RSC165}">${pf.const.language.RSC165}</th>
							<th scope="col" title="${pf.const.language.RSC166}">${pf.const.language.RSC166}</th>
						</tr>
					</thead>

					<tbody>
			`;

			for(let i = 0; i < self.messages.length; i++) {
				if(idUser == self.messages[i].jid) {
					let dateTime = self.messages[i].stampServer.split(' ');
					let date = dateTime[0];
					let time = dateTime[1];

					let name = self.messages[i].nameUser + ' ' + self.messages[i].userApellidos + ' ' + self.messages[i].userApellidos2;

					table += `
						<tr>
							<td title="${name}">${name}</td>
							<td title="${self.messages[i].msg}">${self.messages[i].msg}</td>
							<td title="${date}">${date}</td>
							<td title="${time}">${time}</td>
						</tr>
					`;
				}
			}

			table += `
					</tbody>
				</table>
			`;

			$('#messages').html(table);

			let dataTable = $('#tableMessagesVal').DataTable({
				retrieve: true,
				autoWidth: false,
				columnDefs: [
					{width: '300px', targets: 0},
					{width: '80px', targets: 2},
					{width: '70px', targets: 3}
				],
				paging: false,
				searching: false,
				language: pf.const.language_table,
				info: false,
				order: [[2, 'asc'], [3, 'asc']]
			});

			// Ocultar botones de tabla
			hideTableButtons('tableMessagesVal');
		} else {
			html += pf.const.language.RSC573;
			$('#messages').html(html);
		}
	},

	getCumplimentMision() {
		let self = this;

		return new Promise((resolve, reject) => {
			let parameters = {
				project: self.mision.idProject,
				mision: self.mision.idmision
			};
			ajaxComunCallWithCallback('getAnalyticsMisiones', parameters, function(ajaxReturn) {
				if(ajaxReturn) {
					resolve(ajaxReturn.result);
				}
			});
		});
	},

	renderImageInfo(imageInfo) {
		let self = this;

		// Ocultar botón de guardado de corrección de OCR y contenedor
		$('#saveCorrection').hide();
		$('#infoBodyOCR').html('');
		$('#infoBodyOCR').hide();
		$('#infoBody').show();

		let table = `
			<table id="tableImageInfo" class="table table-hover">
				<thead>
					<tr>
						<th scope="col" title="${pf.const.language.RSC2132}">${pf.const.language.RSC2132}</th>
						<th scope="col" title="${pf.const.language.RSC127}">${pf.const.language.RSC127}</th>
					</tr>
				</thead>

				<thead class="filtersParams">
					<tr>
						<td>param</td>
						<td>response</td>
					</tr>
				</thead>

				<tbody>
		`;

		for(let param in imageInfo) {
			table += `
				<tr>
					<td class="text-truncate" title="${param}"><strong>${param}</strong></td>
					<td class="text-truncate" title="${imageInfo[param]}">${imageInfo[param]}</td>
				</tr>
			`;
		}

		table += `
				</tbody>
			</table>
		`;

		$('#infoBody').html(table);

		// Setup - add a text input to each footer cell
		$('#tableImageInfo .filtersParams td').each(function() {
			let value = `<input type="text" class="form-control form-control-sm">`;

			$(this).html(value);
		});

		let dataTable = $('#tableImageInfo').DataTable({
			retrieve: true,
			language: self.language,
			pageLength: 25,
			autoWidth: false,
			aaSorting: [],
			dom: 'Bfrtip',
			buttons: [{
				extend: 'excelHtml5',
				text: pf.const.language.RSC2202,
				className: 'd-none',
				title: pf.const.language.RSC2202,
				customize(xlsx) {
					dataTablesExcelCustomize(xlsx);
				}
			}]
		});

		// Ocultar botones de tabla
		hideTableButtons('tableImageInfo');

		// Exportar tabla
		$('#exportImageInfo').off().on('click', function() {
			$('#infoBody .buttons-excel').trigger('click');
		});

		// Apply the search
		applyTheSearch(dataTable, 'filtersParams');

		// Evento para cuando se cierre el modal de información de la imágen
		$('#infoModal').on('hidden.bs.modal', function() {
			// Mostrar modal de validación de imágenes
			$('#modalPictures').modal('show');
		});
	},

	renderImageInfoOCR(imageInfoOCR, picture) {
		let self = this;

		// Mostrar botón de guardado de corrección de OCR y contenedor
		$('#saveCorrection').show();
		$('#infoBody').html('');
		$('#infoBody').hide();
		$('#infoBodyOCR').show();

		// Limipar array de corrección OCR
		self.correctionOCR = [];

		let table = `
			<div class="d-flex">
				<div class="mt-4 mr-4 wi-40per">
					<img src="${picture}" class="img-fluid">
				</div>

				<div class="wi-60per">
					<table id="tableImageInfoOCR" class="table table-hover w-100">
						<thead>
							<tr>
								<th scope="col" title="${pf.const.language.RSC1210}">${pf.const.language.RSC1210}</th>
								<th scope="col" title="${pf.const.language.RSC2319}">${pf.const.language.RSC2319}</th>
							</tr>
						</thead>

						<thead class="filtersParams">
							<tr>
								<td>texto</td>
								<td>correccion</td>
							</tr>
						</thead>

						<tbody>
		`;

		let size = imageInfoOCR.length;
		for(let i = 0; i < size; i++) {
			table += `
				<tr>
					<td class="text-truncate p-1" title="${imageInfoOCR[i].text}"><strong>${imageInfoOCR[i].text}</strong></td>
					<td class="text-truncate p-1">
						<span class="d-none">${imageInfoOCR[i].textSimilar}</span>
						<input type="text" class="form-control OCRCorrection" value="${imageInfoOCR[i].textSimilar}" data-index="${i}">
					</td>
				</tr>
			`;

			// Crear array de textos / correcciones
			let obj = {
				changed: false,
				text: imageInfoOCR[i].text,
				textSimilar: imageInfoOCR[i].textSimilar
			}
			self.correctionOCR.push(obj);
		}

		table += `
						</tbody>
					</table>
				</div>
			</div>
		`;

		$('#infoBodyOCR').html(table);

		// Setup - add a text input to each footer cell
		$('#tableImageInfoOCR .filtersParams td').each(function() {
			let value = `<input type="text" class="form-control form-control-sm">`;

			$(this).html(value);
		});

		let dataTable = $('#tableImageInfoOCR').DataTable({
			retrieve: true,
			language: self.language,
			pageLength: 25,
			autoWidth: false,
			aaSorting: [],
			dom: 'Bfrtip',
			buttons: [{
				extend: 'excelHtml5',
				text: pf.const.language.RSC2202,
				className: 'd-none',
				title: pf.const.language.RSC2202,
				customize(xlsx) {
					dataTablesExcelCustomize(xlsx);
				}
			}]
		});

		// Ocultar botones de tabla
		hideTableButtons('tableImageInfoOCR');

		// Exportar tabla
		$('#exportImageInfo').off().on('click', function() {
			$('#infoBodyOCR .buttons-excel').trigger('click');
		});

		// Apply the search
		applyTheSearch(dataTable, 'filtersParams');

		// Evento para cuando se cierre el modal de información de la imágen
		$('#infoModal').on('hidden.bs.modal', function() {
			// Mostrar modal de validación de imágenes
			$('#modalPictures').modal('show');
		});

		self.tableInfoOCREvents();

		// Eventos con cambio de página de tabla
		$('#tableImageInfoOCR').on('draw.dt', function() {
			self.tableInfoOCREvents();
		});
	},

	tableInfoOCREvents() {
		let self = this;

		// Evento de corrección
		$('.OCRCorrection').off().on('blur', function() {
			let index = $(this).data('index');
			let value = $(this).val().trim();
			$(this).val(value);
			$(this).parent().find('span').text(value);
			self.correctionOCR[index].changed = true;
			self.correctionOCR[index].textSimilar = value;
		});
	}
};