<?php

use SimpleCaptcha\Builder;

/**
 * The functionality of the module.
 *
 * @package    TS Forms
 * @author     Max Sternitzke <max.sternitzke@th-luebeck.de>
 */
class Trainingssystem_Plugin_Module_TS_Forms {

	private static $types = ["input", "textarea", "select", "radio", "checkbox", "slider", "text", "scale", "matrix", "upload", "captcha"];

	private static $captchaUserMetaKey = "tspv2_captcha_phrase";

	/**
	 * Initialize the class and set its properties.
	 *
	 * @since    1.0.0
	 */
	public function __construct() {

    }
	
	/**
	 * BACKEND
	 * Restructure Columns for Formulare List Table (Coulmn Post_type is removed via CSS)
	 */
	function tsforms_manage_columns($columns) {
		$columns = array(
			'cb' => $columns['cb'],
			'formulare_id' => 'ID',
			'title' => __('Title'),
			'date' => __('Date'),
		);
		return $columns;
	}

	/**
	 * BACKEND
	 * Add Content to ID column
	 */
	function tsforms_manage_custom_columns($column, $post_id) {
		if ( 'formulare_id' === $column ) {
			echo '<a href="' . get_edit_post_link($post_id) . '">' . $post_id . '</a>';
		}
	}

	/**
	 * BACKEND
	 * Make ID column sortable
	 */
	function tsforms_manage_sortable_columns($columns) {
		$columns['formulare_id'] = 'formulare_id';
  		return $columns;
	}

	/**
	 * BACKEND 
	 * If search for Formulare and search string is numeric, call additional filter
	 */
	function tsforms_custom_search( $query ) {
		if(get_query_var("post_type") == "formulare") {
			// Bail if we are not in the admin area
			if ( ! is_admin() ) {
				return;
			}
		
			// Bail if this is not the search query.
			if ( ! $query->is_main_query() && ! $query->is_search() ) {
				return;
			}

			if(!isset($_GET['orderby'])) {
				$query->set('orderby', 'ID');
				$query->set('order', 'DESC');
			}
		
			// Get the value that is being searched.
			$search_string = get_query_var( 's' );
		
			// Bail if the search string is not an integer.
			if ( ! filter_var( $search_string, FILTER_VALIDATE_INT ) ) {
				return;
			}
		
			add_filter('posts_where', array($this, 'tsforms_custom_search_where'));
			$query->set( 'ID', $search_string );
		}
	}

	/**
	 * BACKEND
	 * Adds the additional Where Parameter to search for ID and PostType Formulare as well
	 */
	function tsforms_custom_search_where($where = '') {
		$search_string = intval(get_query_var( 's' ));

		$where .= " OR `ID` = '" . $search_string . "' AND `post_type` = 'formulare'";

		return $where;
	}
	
	/**
	 * BACKEND
	 * Adding the meta boxes to the edit page
	 */
    public function add_formular_meta_box() {
		if(isset($_GET['post'])) {
			add_meta_box("ts-formular-option-meta-box", "Formular-Optionen", array($this, "custom_ts_formular_options_meta_box_markup"), "formulare", "normal", "high", null);
			add_meta_box("ts-formular-meta-box", "Formular zusammenstellen", array($this, "custom_ts_formular_meta_box_markup"), "formulare", "normal", "high", null);
			add_meta_box("ts-formular-pages-meta-box", "Formular wird verwendet in:", array($this, "custom_ts_formular_pages_meta_box_markup"), "formulare", "normal", "high", null);
			add_meta_box("ts-formular-export-meta-box", "&nbsp;", array($this, "custom_ts_formular_export_meta_box_markup"), "formulare", "side", "high", null);
		} else {
			add_meta_box("ts-formular-titlefirst-meta-box", "Bitte einen Titel vergeben", array($this, "custom_ts_formular_titlefirst_meta_box_markup"), "formulare", "normal", "high", null);
		}
	}

	/**
	 * BACKEND
	 * Add the warning box if a newly created form has not yet been saved
	 */
	public function custom_ts_formular_titlefirst_meta_box_markup() {
		$twig = Trainingssystem_Plugin_Twig::getInstance()->twig;

		echo $twig->render('forms/backend-form-titlefirst.html');
	}
	
	/**
	 * BACKEND
	 * Add the form options box
	 */
	public function custom_ts_formular_options_meta_box_markup() {
		global $post;
		$id = $post->ID;
		$is_multiform = $post->isMultiform == "1";
		$multiform_ordering = $post->multiformOrdering == "1";
		$submit_manually = $post->submitmanually == "1";
		$submitmanuallylink = $post->submitmanuallylink;
		$send_by_mail = $post->sendbymail == "1";
		$send_to_mail = $post->sendtomail;
		$send_receipt = $post->sendreceipt == "1";
		$send_receipt_subject = $post->send_receipt_subject;
		$send_receipt_text = $post->send_receipt_text;
		$keep_data = $post->keepdata == "1";
		$saveonce = $post->saveonce == "1";
		$nosave = $post->nosave == "1";
		$form_css = $post->formCss;
		$multiform_orientation = $post->multiformOrientation;

		$multiform_help_img = plugin_dir_url(dirname(__FILE__)) . '../../assets/img/multiform-help.jpg';

		$twig = Trainingssystem_Plugin_Twig::getInstance()->twig;

		echo $twig->render('forms/backend-form-options.html', ["id" => $id, 
																"is_multiform" => $is_multiform, 
																"multiform_ordering" => $multiform_ordering,
																"form_css" => $form_css, 
																"multiform_orientation" => $multiform_orientation,
																"multiform_help_img" => $multiform_help_img,
																"submit_manually" => $submit_manually,
																"submitmanuallylink" => $submitmanuallylink,
																"send_by_mail" => $send_by_mail,
																"send_to_mail" => $send_to_mail,
																"send_receipt" => $send_receipt,
																"send_receipt_subject" => $send_receipt_subject,
																"send_receipt_text" => $send_receipt_text,
																"keep_data" => $keep_data,
																"saveonce" => $saveonce,
																"nosave" => $nosave,
																"allowed_html" => "&lt;" . implode("&gt;, &lt;", array_keys(wp_kses_allowed_html())) . "&gt;",
																"dataexport_url" => get_permalink(get_option(TRAININGSSYSTEM_PLUGIN_SETTINGS)['dataexport']),
															]);
	}

	/**
	 * BACKEND
	 * Add the form fields box with button for preview and creating new fields
	 */
	public function custom_ts_formular_meta_box_markup() {
		global $post;
        $id = $post->ID;

		$twig = Trainingssystem_Plugin_Twig::getInstance()->twig;

		$allfields = Trainingssystem_Plugin_Database::getInstance()->Formfield->getFormfieldsByForm($id);
		$form_fields_html = $twig->render('forms/backend-form-fields.html', ["fields" => $allfields, "id" => $id]);

		echo $twig->render('forms/backend-form-assemble.html', ['id' => $id, 'form_fields_html' => $form_fields_html, "allowed_html" => "&lt;" . implode("&gt;, &lt;", array_keys(wp_kses_allowed_html())) . "&gt;"]);
	}

	/**
	 * BACKEND
	 * Add the box that displays on which pages the form is being used when requested
	 */
	public function custom_ts_formular_pages_meta_box_markup() {
		global $post;

		$id = $post->ID;

		$twig = Trainingssystem_Plugin_Twig::getInstance()->twig;

		echo $twig->render('forms/backend-form-pages.html', ["id" => $id]);
	}

	/**
	 * BACKEND
	 * Add the box in the sidebar with export/duplicate buttons
	 */
	public function custom_ts_formular_export_meta_box_markup() {

		global $post;

		echo '<div class="wrapper-admin-backend"><button type="button" class="btn btn-secondary backend-export-ts-form" data-formid="' . $post->ID . '"><i class="fas fa-file-export"></i>&nbsp;Formular exportieren</button></div>';
		echo '<div class="wrapper-admin-backend"><button type="button" class="btn btn-secondary backend-duplicate-ts-form mt-3" data-formid="' . $post->ID . '"><i class="fas fa-clone"></i>&nbsp;Formular duplizieren</button></div>';
	}

	/**
	 * BACKEND
	 * Returns a list with pages the form is used in
	 */
	public function getPagesWithForm() {
		global $wpdb;

		$twig = Trainingssystem_Plugin_Twig::getInstance()->twig;

		if(isset($_POST['formid']) && is_numeric($_POST['formid'])) {

			$id = sanitize_text_field($_POST['formid']);

			$sql = "SELECT `ID`, `post_title`, `post_type`, `post_content` FROM $wpdb->posts WHERE `post_content` REGEXP '[ts_forms id=[\']?" . $id . "[\']?]' AND `post_status` = 'publish' ORDER BY `post_title` ASC";
			$result = $wpdb->get_results($sql);
			
			$pages = array();
			$sc_multi = false;
			$i = 0;
			if($result) {
				foreach($result as $row) {
					$pages[$i]['id'] = $row->ID;
					$pages[$i]['title'] = $row->post_title;
					$pages[$i]['type'] = ucfirst($row->post_type);
					$pages[$i]['url'] = get_permalink($row->ID);
					$pages[$i]['edit_url'] = get_edit_post_link($row->ID);

					preg_match_all("[ts_forms id=[\']?" . $id . "[\']?]", $row->post_content, $matches);
					$pages[$i]['count_sc'] = isset($matches[0]) ? count($matches[0]) : 0;

					if($pages[$i]['count_sc'] > 1) {
						$sc_multi = true;
					}

					$i++;
				}
			}
	
			echo $twig->render('forms/backend-form-pages-list.html', ["pages" => $pages, "sc_multi" => $sc_multi]);

		}
		wp_die();
	}

	/**
	 * BACKEND
	 * Funtion to save the Options for a form
	 */
	public function saveOptions()  {

		if(isset($_POST['formid']) && is_numeric($_POST['formid']) &&
			isset($_POST['multiform']) && ($_POST['multiform'] == "false" || $_POST['multiform'] == "true") &&
			isset($_POST['multiformordering']) && ($_POST['multiformordering'] == "false" || $_POST['multiformordering'] == "true") &&
			isset($_POST['classes']) &&
			isset($_POST['multiformorientation']) && ($_POST['multiformorientation'] == "next" || $_POST['multiformorientation'] == "above") &&
			isset($_POST['submitmanually']) && ($_POST['submitmanually'] == "false" || $_POST['submitmanually'] == "true") &&
			isset($_POST['submitmanuallylink']) &&
			isset($_POST['sendbymail']) && ($_POST['sendbymail'] == "false" || $_POST['sendbymail'] == "true") &&
			isset($_POST['sendtomail']) &&
			isset($_POST['sendreceipt']) && ($_POST['sendreceipt'] == "false" || $_POST['sendreceipt'] == "true") &&
			isset($_POST['sendreceipt_subject']) &&
			isset($_POST['sendreceipt_text']) &&
			isset($_POST['normaldata']) && ($_POST['normaldata'] == "false" || $_POST['normaldata'] == "true") &&
			isset($_POST['keep_data']) && ($_POST['keep_data'] == "false" || $_POST['keep_data'] == "true") &&
			isset($_POST['saveonce']) && ($_POST['saveonce'] == "false" || $_POST['saveonce'] == "true") &&
			isset($_POST['nosave']) && ($_POST['nosave'] == "false" || $_POST['nosave'] == "true")) {

				$formid = sanitize_text_field($_POST['formid']);
				$post = get_post($formid, ARRAY_A);

				if(isset($post['post_title'])) {

					$multiform = $_POST['multiform'] == "false" ? false : true;
					$classes = sanitize_text_field($_POST['classes']);
					$multiform_ordering = $_POST['multiformordering'] == "false" ? false : true;
					$multiform_orientation = sanitize_text_field($_POST['multiformorientation']);
					$submitmanually = $_POST['submitmanually'] == "false" ? false : true;
					$submitmanuallylink = sanitize_text_field($_POST['submitmanuallylink']);
					$sendbymail = $_POST['sendbymail'] == "false" ? false : true;
					$sendtomail = sanitize_text_field($_POST['sendtomail']);
					$sendreceipt = $_POST['sendreceipt'] == "false" ? false : true;
					$sendreceipt_subject = sanitize_text_field($_POST['sendreceipt_subject']);
					$sendreceipt_text = wp_kses($_POST['sendreceipt_text'], wp_kses_allowed_html());
					$normaldata = $_POST['normaldata'] == "false" ? false : true;
					$keep_data = $_POST['keep_data'] == "false" ? false : true;
					$saveonce = $_POST['saveonce'] == "false" ? false : true;
					$nosave = $_POST['nosave'] == "false" ? false : true;

					update_post_meta($formid, 'isMultiform', $multiform);
					update_post_meta($formid, 'multiformOrdering', $multiform_ordering);
					update_post_meta($formid, 'formCss', $classes);
					update_post_meta($formid, 'multiformOrientation', $multiform_orientation);
					update_post_meta($formid, 'submitmanually', $submitmanually);
					update_post_meta($formid, 'submitmanuallylink', $submitmanuallylink);
					update_post_meta($formid, 'sendbymail', $sendbymail);

					delete_post_meta($formid, "keepdata");
					delete_post_meta($formid, "nosave");
					delete_post_meta($formid, "saveonce");

					if(!$normaldata) {
						if($keep_data) {
							update_post_meta($formid, 'keepdata', $keep_data);
						}
						if($nosave) {
							update_post_meta($formid, 'nosave', $nosave);
						}
						if($saveonce) {
							update_post_meta($formid, 'saveonce', $saveonce);
						}
					}
					$email_adresses = array();
					if(strlen(trim($sendtomail)) > 0) {
						$tmp = explode(";", $sendtomail);
						foreach($tmp as $tmp_mail) {
							if(filter_var($tmp_mail, FILTER_VALIDATE_EMAIL)) {
								$email_adresses[] = $tmp_mail;
							} else {
								echo "invalidmail";
								wp_die();
							}
						}
					}
					update_post_meta($formid, 'sendtomail', implode(';', $email_adresses));

					update_post_meta($formid, 'sendreceipt', $sendreceipt);
					update_post_meta($formid, 'send_receipt_subject', $sendreceipt_subject);
					update_post_meta($formid, 'send_receipt_text', $sendreceipt_text);
					echo "success";

				} else {
					echo "no post found";
				}

		} else {
			echo "invalid data";
		}
		wp_die();
	}

	/**
	 * BACKEND
	 * Funtion to get a list of form fields
	 */
	public function getFormFields() {

		if(isset($_POST['formid']) && is_numeric($_POST['formid']) && is_string(get_post_status($_POST['formid']))) {
			$twig = Trainingssystem_Plugin_Twig::getInstance()->twig;

			$allfields = Trainingssystem_Plugin_Database::getInstance()->Formfield->getFormfieldsByForm($_POST['formid']);
			echo $twig->render("forms/backend-form-fields.html", ["fields" => $allfields, "id" => $_POST['formid']]);
		}
		wp_die();
	}

	/**
	 * BACKEND
	 * Funtion to get a clean new form field assemble modal
	 */
	public function getAssembleModal() {
		$twig = Trainingssystem_Plugin_Twig::getInstance()->twig;

		echo $twig->render("forms/backend-form-assemble-modal.html", ["allowed_html" => "&lt;" . implode("&gt;, &lt;", array_keys(wp_kses_allowed_html())) . "&gt;",]);
		wp_die();
	}

	/**
	 * BACKEND
	 * Saves a new form field
	 */
	public function newField() {
		
		if(isset($_POST['formid']) && is_numeric($_POST['formid']) &&
			isset($_POST['type']) && in_array($_POST['type'], self::$types) &&
			isset($_POST['data']) && strlen(trim($_POST['data'])) > 1) {

				$formid = $_POST['formid'];
				$type = $_POST['type'];
				$datastr = $_POST['data'];

				$data = json_decode(stripslashes($datastr), true);
				
				if(is_string(get_post_status($formid)) && json_last_error() === JSON_ERROR_NONE) {

					$idata = $this->getInsertData($type, $data);
					$sortIndex = Trainingssystem_Plugin_Database::getInstance()->Formfield->getFormfieldsCount($formid);

					if($this->validateInput($type, $idata)) {

						if(Trainingssystem_Plugin_Database::getInstance()->Formfield->addFormfield($formid, $type, json_encode($idata), $sortIndex)) {
							echo "success";
						} else {
							echo "0-" . $type;
						}

					} else {
						echo "invaliddata";
					}

				} else {
					echo "invalid data structure";
				}

		} else {
			echo "not all data";
		}
		wp_die();
	}

	/**
	 * BACKEND
	 * Gets the pre-filled formfield edit form
	 */
	public function editField() {
		
		if(isset($_POST['fieldid']) && is_numeric($_POST['fieldid'])) {
			
			$twig = Trainingssystem_Plugin_Twig::getInstance()->twig;

			$fieldid = sanitize_text_field($_POST['fieldid']);
			$formfield = Trainingssystem_Plugin_Database::getInstance()->Formfield->getFormfield($fieldid);

			echo $twig->render("forms/backend-form-field-edit.html", ["formfield" => $formfield, "allowed_html" => "&lt;" . implode("&gt;, &lt;", array_keys(wp_kses_allowed_html())) . "&gt;",]);
		}
		wp_die();
	}

	/**
	 * BACKEND
	 * Duplicates a Form
	 */
	public function duplicateField() {
		
		if(isset($_POST['fieldid']) && is_numeric($_POST['fieldid'])) {
			
			$twig = Trainingssystem_Plugin_Twig::getInstance()->twig;

			$fieldid = sanitize_text_field($_POST['fieldid']);
			$formfield = Trainingssystem_Plugin_Database::getInstance()->Formfield->getFormfield($fieldid);
			$index = Trainingssystem_Plugin_Database::getInstance()->Formfield->getFormfieldsCount($formfield->getFormId());
			
			if(Trainingssystem_Plugin_Database::getInstance()->Formfield->addFormfield($formfield->getFormId(), $formfield->getType(), $formfield->getAttributes(), $index)) {
				echo "1";
			} else {
				echo "0";
			}
		}
		wp_die();
	}

	/**
	 * BACKEND
	 * Updates the formfield from the edit form
	 */
	public function updateField() {
		if(isset($_POST['fieldid']) && is_numeric($_POST['fieldid']) &&
			isset($_POST['type']) && in_array($_POST['type'], self::$types) &&
			isset($_POST['data']) && strlen(trim($_POST['data'])) > 1) {

			$fieldid = $_POST['fieldid'];
			$type = $_POST['type'];
			$datastr = $_POST['data'];

			$data = json_decode(stripslashes($datastr), true);
			
			if(json_last_error() === JSON_ERROR_NONE) {

				$insertData = $this->getInsertData($type, $data);

				if($this->validateInput($type, $insertData)) {
					if(Trainingssystem_Plugin_Database::getInstance()->Formfield->updateFormfield($fieldid, $type, json_encode($insertData))) {
						echo "success";
					} else {
						echo "error inserting";
					}
				} else {
					echo "invaliddata";
				}
			} else {
				echo "invalid data structure";
			}
		} else {
			echo "not all data";
		}
		wp_die();
	}

	/**
	 * BACKEND
	 * Saves the order of the form fields
	 */
	public function saveOrder() {
		
		if(isset($_POST['formid']) && is_numeric($_POST['formid']) && is_string(get_post_status($_POST['formid'])) &&
			isset($_POST['data']) && strlen(trim($_POST['data'])) > 1) {
		
			$formid = $_POST['formid'];
			$datastr = $_POST['data'];

			$data = json_decode($datastr, true);

			if(json_last_error() === JSON_ERROR_NONE) {

				foreach($data as $i => $fieldid) {
					if(!Trainingssystem_Plugin_Database::getInstance()->Formfield->setFormfieldOrder($formid, $fieldid, $i)) {
						echo "error";
						return;
					}
				}
				echo "success";

			} else {
				echo "json not valid";
			}
		} else {
			echo "invalid data";
		}
		
		wp_die();
	}

	/**
	 * BACKEND
	 * 
	 * Delete all data for a form and all of its fields or only a speicific field
	 */
	public function backendDeleteData() {
		if(isset($_POST['formid']) && is_numeric($_POST['formid']) && strtolower(get_post_type($_POST['formid'])) == "formulare" &&
			isset($_POST['fieldid']) && (is_numeric($_POST['fieldid']) || $_POST['fieldid'] == "all")) {

			$formid = $_POST['formid'];
			$fieldid = $_POST['fieldid'];

			if($fieldid == "all") {
				if(Trainingssystem_Plugin_Database::getInstance()->Formdata->deleteFormdataByFormId($formid)) {
					echo "1";
				} else {
					echo "0";
				}
			} else {
				if(Trainingssystem_Plugin_Database::getInstance()->Formdata->deleteFormdataByFieldId($fieldid)) {
					echo "1";
				} else {
					echo "0";
				}
			}
		}
		wp_die();
	}

	/**
	 * BACKEND
	 * Deletes a form field
	 */
	public function deleteField() {

		if(isset($_POST['formid']) && is_numeric($_POST['formid']) && is_string(get_post_status($_POST['formid'])) &&
			isset($_POST['fieldid']) && is_numeric($_POST['fieldid'])) {

			$formid = $_POST['formid'];
			$fieldid = $_POST['fieldid'];

			if(Trainingssystem_Plugin_Database::getInstance()->Formfield->removeFormfield($formid, $fieldid) && 
				Trainingssystem_Plugin_Database::getInstance()->Formdata->deleteFormdataByFieldId($fieldid)) {
				echo "success";
			} else {
				echo "0";
			}

		}
		wp_die();
	}

	/**
	 * BACKEND
	 * Returns the preview of the currently viewed form
	 */
	public function getFormPreview() {
		if(isset($_POST['formid']) && is_numeric($_POST['formid']) && is_string(get_post_status($_POST['formid']))) {

			echo $this->getFormPreviewById($_POST['formid']);

		}
		wp_die();
	}

	/**
	 * HELPER
	 * Returns the preview of a form with the formid passed as a parameter
	 */
	public function getFormPreviewById($formid) {
		$groups[] = Trainingssystem_Plugin_Database::getInstance()->Formfield->getFormfieldsByForm($formid);

		return $this->renderForm($formid, $groups, true, false);
	}

	/**
	 * BACKEND/ADMIN
	 * Fires if a post is deleted from trash and deletes related data from the database if post was a form
	 */
	public function backendDeleteForm($postid) {

		if(strtolower(get_post_type($postid)) === "formulare") {
			Trainingssystem_Plugin_Database::getInstance()->Formdata->deleteFormdataByFormId($postid);
			Trainingssystem_Plugin_Database::getInstance()->Formfield->deleteFormfieldsByFormId($postid);
		}
	}

	/**
	 * BACKEND/ADMIN
	 * Adds an export and duplicate button to each form row action list
	 */
	public function backendAddExportAction($actions, $post) {
		
		if(strtolower($post->post_type) === "formulare") {
			$actions['export_link'] = '<div class="wrapper-admin-backend" style="display:inline"><button type="button" class="btn btn-secondary btn-sm backend-export-ts-form" data-formid="' . $post->ID . '">Export</button></div>';
			$actions['duplicate_link'] = '<div class="wrapper-admin-backend" style="display:inline"><button type="button" class="btn btn-secondary btn-sm backend-duplicate-ts-form" data-formid="' . $post->ID . '">Duplizieren</button></div>';
		}

		return $actions;
	}

	/**
	 * BACKEND/ADMIN
	 * Adds a new entry for exporting forms to the bulk dropdown
	 */
	public function backendAddBulkExportAction($bulk_actions) {

		$bulk_actions['export_forms'] = "Formulare exportieren";

		return $bulk_actions;
	}

	/**
	 * BACKEND/ADMIN
	 * Exports a form as a json file and returns this content to the browser
	 */
	public function backendExportForm() {

		if(isset($_POST['formid']) && is_numeric($_POST['formid']) && strtolower(get_post_type($_POST['formid'])) === "formulare") {
			$filename = "Formularexport-" . current_time("d-m-Y-H-i-s") . ".json";

			header('Content-type: application/json; charset=utf-8');
			header('Content-disposition: attachment; filename="' . $filename . '"');

			echo $this->exportForm($_POST['formid']);
		} else {
			echo "0";
		}
		wp_die();
	}

	/**
	 * BACKEND/ADMIN
	 * Exports multiple forms as a json file and returns the content of a json (one valid export form) or zip archive (multiple valid forms) to the browser
	 */
	public function backendExportBulk() {

		if(isset($_POST['ids']) && trim($_POST['ids']) != "" ) {

			$data = json_decode(wp_unslash($_POST['ids']), true);

			if(json_last_error() == JSON_ERROR_NONE) {

				$ids = array();

				foreach($data as $possible_id) {
					if(strtolower(get_post_type($possible_id)) === "formulare") {
						$ids[] = $possible_id;
					}
				}

				if(sizeof($ids) > 1) {

					$zip = new ZipArchive;
					$filename = "Formularexport_" . current_time("d-m-Y-H-i-s") . ".zip";
                    $tmp_dir = trailingslashit((wp_get_upload_dir()['basedir'])) . "trainings-ex-import/";

					$zipfile = $tmp_dir . $filename;
	
					if (is_dir($tmp_dir) && $zip->open($zipfile, ZipArchive::CREATE) === true) {
						foreach ($ids as $id) {
							$zip->addFromString(uniqid("Formularexport_") . ".json", $this->exportForm($id));
						}
						if($zip->close()) {
	
							header('Content-Type: application/zip; charset=utf-8');
							header('Content-disposition: attachment; filename="' . $filename . '"');
							header('Content-Length: ' . filesize($zipfile));
							$handle = fopen($zipfile, 'rb');
							$buffer = '';
							while (!feof($handle)) {
								$buffer = fread($handle, 4096);
								echo $buffer;
								ob_flush();
								flush();
							}
							fclose($handle);
						}
						unlink($zipfile);
					} else {
						echo "0";
					}

				} else if(sizeof($ids) == 1 && isset($ids[0])) {

					$filename = "Formularexport-" . current_time("d-m-Y-H-i-s") . ".json";

					header('Content-type: application/json; charset=utf-8');
					header('Content-disposition: attachment; filename="' . $filename . '"');

					echo $this->exportForm($ids[0]);
				} else {
					echo "0";
				}

			} else {
				echo "0";
			}

		} else {
			echo "0";
		}
		wp_die();
	}

	/**
	 * BACKEND/ADMIN
	 * Duplicates a form with the helper ex-/import funtions and returns a link to the edit page of the new form
	 */
	public function backendDuplicateForm() {
		if(isset($_POST['formid']) && is_numeric($_POST['formid']) && strtolower(get_post_type($_POST['formid'])) === "formulare") {
			
			$export = $this->exportForm($_POST['formid']);

			$importdata = json_decode($export, true);

			if(isset($importdata['title'])) {
				$importdata['title'] .= " Kopie";
			}

			$import = $this->importForm($importdata);
			if($import != null && is_numeric($import)) {
				echo get_edit_post_link($import, "");
			}
		}
		wp_die();
	}

	/**
	 * BACKEND/ADMIN
	 * Adds an import button to the subsubsub menu of the forms-table
	 */
	public function backendAddImportAction($views) {
		
		$twig = Trainingssystem_Plugin_Twig::getInstance()->twig;

		$views['export_forms'] = '<div class="wrapper-admin-backend" style="display:inline"><button type="button" class="btn btn-secondary btn-sm" id="backend-ts-forms-export-bulk">Formular(e) exportieren</button></div>';
		$views['import_forms'] = $twig->render("forms/backend-form-import.html") . '<style>#the-list td.column-post_type, .table-view-list th.column-post_type { display: none; } </style>';

		return $views;
	}

	/**
	 * BACKEND/ADMIN
	 * Imports a form of a json file and returns the edit link to the newly created form
	 */
	public function backendImportForm() {
		$countfiles = sizeof($_FILES['file']['name']);
		
		for($i = 0; $i < $countfiles; $i++) {
			if(!isset($_FILES['file']['name'][$i]) ||
					$_FILES['file']['error'][$i] != UPLOAD_ERR_OK ||
					!is_uploaded_file($_FILES['file']['tmp_name'][$i]))
					{
						wp_die();
					}
		}
		
		for($i = 0; $i < $countfiles; $i++) {
			$filecontent = file_get_contents($_FILES['file']['tmp_name'][$i]);

			$import = $this->importForm($filecontent);

			if($import != null && is_numeric($import)) {
				$editlink = get_edit_post_link($import, "");
			} else {
				wp_die();
			}
		}

		if($countfiles > 1) {
			echo "edit.php?post_type=formulare";
		} else {
			echo $editlink;
		}
		wp_die();
	}

	/**
	 * FRONTEND
	 * Gets a fresh copy of a form to append it on the user's side when multiform is requested
	 */
	public function getMultiformAppend() {
		if(isset($_POST['formid']) && is_numeric($_POST['formid']) && is_string(get_post_status($_POST['formid'])) &&
			isset($_POST['index']) && is_numeric($_POST['index']) && $_POST['index'] > 0) {

			$formid = $_POST['formid'];
			$index = $_POST['index'];

			$allfields = Trainingssystem_Plugin_Database::getInstance()->Formfield->getFormfieldsByForm($formid);
			$form_css = get_post_meta($formid, 'formCss', true);
			$is_multiform = get_post_meta($formid, 'isMultiform', true) == "1";
			$multiform_ordering = get_post_meta($formid, 'multiformOrdering', true) == "1";
			$multiform_orientation = get_post_meta($formid, 'multiformOrientation', true);
			$submitmanually = get_post_meta($formid, 'submitmanually', true) == "1";
			$submitmanuallylink = get_post_meta($formid, 'submitmanuallylink', true);
			$usermodus = false;
			$selectui = '' . get_user_meta(wp_get_current_user()->ID, 'coach_select_user', true);
			if ($selectui != '') {
				$usermodus = true;
			}
			$keep_data = get_post_meta($formid, 'keepdata', true) == "1";

			$twig = Trainingssystem_Plugin_Twig::getInstance()->twig;
			echo $twig->render("forms/form-fields.html", ["formid" => $formid,
															"form_css" => $form_css, 
															"formfields" => $allfields,
															"is_multiform" => $is_multiform,
															"multiform_ordering" => $multiform_ordering,
															"multiform_orientation" => $multiform_orientation,
															"submitmanually" => $submitmanually,
															"submitmanuallylink" => $submitmanuallylink,
															"usermodus" => $usermodus,
															"index" => $index,
															"keepdata" => $keep_data]);
		}
		wp_die();
	}

	/**
	 * FRONTEND
	 * Displays a form for the user in the frontend
	 */
	public function frontendDisplayForm($atts) {
		$twig = Trainingssystem_Plugin_Twig::getInstance()->twig;

		if(isset($atts['id']) && strtolower(get_post_type($atts['id'])) === "formulare") {

			$formid = $atts['id'];

			$usermodus = false;
			$uid = get_current_user_id();
			$selectui = '' . get_user_meta(wp_get_current_user()->ID, 'coach_select_user', true);
			if ($selectui != '') {
				$uid = $selectui;
				$usermodus = true;
			}

			$formgroups = Trainingssystem_Plugin_Database::getInstance()->Formfield->getUserFormfieldsByForm($formid, $uid);

			// Kalender-Prefill: Prefill strikt über calendar_entries + ts_forms_data (unabhängig von keepdata)
			$overrideKeepdataForCalendar = false;
			$calendarIdParam = isset($_GET['calendar_id']) ? intval($_GET['calendar_id']) : 0;
			$calendarDateParam = isset($_GET['date']) ? sanitize_text_field($_GET['date']) : '';
			
			// Prüfe Meta-Tag für calendar_id im HTML DOM
			if(!$calendarIdParam) {
				$calendar_meta = get_post_meta(get_the_ID(), 'calendar_id', true);
				if($calendar_meta) {
					$calendarIdParam = intval($calendar_meta);
					// NEUE LEKTIONS-SEITEN: Verwende aktuelles Datum (Meta-Tag-basiert)
					$calendarDateParam = date('Y-m-d');
				}
			}
			
			if($calendarIdParam && $calendarDateParam) {
				global $wpdb;
				$calendar_entries_table = $wpdb->prefix . Trainingssystem_Plugin_Database_Calendar_Entry_Daoimple::$dbprefix;
				$hasCalendarEntries = (int) $wpdb->get_var(
					$wpdb->prepare(
						"SELECT COUNT(*) FROM {$calendar_entries_table} WHERE user_id = %d AND calendar_id = %d AND entry_date = %s AND form_id = %d",
						$uid, $calendarIdParam, $calendarDateParam, $formid
					)
				);

				if($hasCalendarEntries > 0) {
					$formgroups = $this->injectCalendarPrefill($formid, $uid, $calendarIdParam, $calendarDateParam, $formgroups);
					$overrideKeepdataForCalendar = true;
					if(is_array($formgroups) && !empty($formgroups)) {
						$formgroups = array(0 => (isset($formgroups[0]) ? $formgroups[0] : reset($formgroups)));
					}
				} else {
					// Kalender-Parameter vorhanden, aber KEINE Einträge: ALLE Felder leeren und nur Gruppe 0 anzeigen
					foreach($formgroups as $groupIndex => &$groupFields) {
						foreach($groupFields as $formfield) {
							$formfield->setFormdata(null);
						}
					}
					unset($groupFields);
					$overrideKeepdataForCalendar = true;
					if(is_array($formgroups) && !empty($formgroups)) {
						$formgroups = array(0 => (isset($formgroups[0]) ? $formgroups[0] : reset($formgroups)));
					}
				}
			}

			$post = get_post($formid);
			// WICHTIG: Wenn Kalender-Prefill aktiv ist, KEIN Merge, damit keine normalen Formdata zurückkommen
			if(!$overrideKeepdataForCalendar && $post->keepdata == "1" && $this->hasSelectUserAddField($formgroups)) {
				$formgroups = $this->mergeFormgroupData($formgroups);
			}

			if($this->hasCaptchaField($formgroups)) {
				$formgroups = $this->injectCaptchaData($uid, $formgroups);
			}

			return $this->renderForm($formid, $formgroups, false, $usermodus, $overrideKeepdataForCalendar);

		} else {
			return $twig->render("forms/form-error.html");
		}
	}

	/**
	 * FRONTEND
	 * Shows manual submit button with optional href link
	 */
	public function submitButtonManually($atts) {
		$text = "Absenden";
		if(isset($atts['text']) && trim($atts['text']) != "") {
			$text = $atts['text'];
		}

		$link = "";
		if(isset($atts['link']) && trim($atts['link']) != "") {
			$link = $atts['link'];
		}

		$css = "";
		if(isset($atts['css']) && trim($atts['css']) != "") {
			$css = $atts['css'];
		}

		$extendedFeedback = false;
		if(isset($atts['extendedfeedback']) && trim($atts['extendedfeedback']) == "true") {
			$extendedFeedback = true;
		}

		$extendedFeedbackText = "Ihre Eingaben wurden erfolgreich gespeichert.";
		if(isset($atts['extendedfeedbacktext']) && trim($atts['extendedfeedbacktext']) != "") {
			$extendedFeedbackText = $atts['extendedfeedbacktext'];
		}

		$extendedFeedbackTextFail = "Ihre Eingaben konnten nicht gespeichert werden.<br>Bitte versuchen Sie es erneut.";
		if(isset($atts['extendedfeedbacktext_fail']) && trim($atts['extendedfeedbacktext_fail']) != "") {
			$extendedFeedbackTextFail = $atts['extendedfeedbacktext_fail'];
		}

		$twig = Trainingssystem_Plugin_Twig::getInstance()->twig;

		return $twig->render('forms/submit-button.html', ["text" => $text, 
															"link" => $link, 
															"css" => $css, 
															"extendedfeedback" => $extendedFeedback, 
															"extendedfeedbacktext" => $extendedFeedbackText,
															"extendedfeedbacktext_fail" => $extendedFeedbackTextFail,
															"rand" => bin2hex(random_bytes(32)),
														]);
	}

	/**
	 * FRONTEND
	 * 
	 * Regenerates the captcha and return the image
	 */
	public function reloadCaptcha() {
		if(isset($_POST['fieldid']) && trim($_POST['fieldid']) != "" && is_numeric($_POST['fieldid'])) {
			$formfield = Trainingssystem_Plugin_Database::getInstance()->Formfield->getFormfield($_POST['fieldid']);
			$converted_to_array = array(array($formfield));

			$uid = get_current_user_id();
			$selectui = '' . get_user_meta(wp_get_current_user()->ID, 'coach_select_user', true);
			if ($selectui != '') {
				$uid = $selectui;
			}

			$injected = $this->injectCaptchaData($uid, $converted_to_array);
			if(isset($injected[0][0])) {
				echo $injected[0][0]->getCaptchaData();
			}
		}
		wp_die();
	}

	/**
	 * FRONTEND
	 * 
	 * Gets the data from a form and outputs it as a json string.
	 */
	public function getData() {
		if(isset($_POST['formid']) && is_numeric($_POST['formid']) && is_string(get_post_status($_POST['formid']))) {

			$formid = $_POST['formid'];

			$uid = get_current_user_id();
			$selectui = '' . get_user_meta(wp_get_current_user()->ID, 'coach_select_user', true);
			if ($selectui != '') {
				$uid = $selectui;
			}
			$form_data = Trainingssystem_Plugin_Database::getInstance()->Formfield->getUserFormfieldsByForm($formid, $uid);
			
			// Loop through the form data and extract field data
			$formdata_values = [];
			foreach ($form_data as $form_field_array) {
				foreach ($form_field_array as $form_field) {
					$formdata = $form_field->getFormData();
					if (!$formdata) {
						continue;
					}
					$form_field_data = $form_field->getFormData()->getData();
					$formdata_values[$form_field->getFieldId()] = $form_field_data;
				}
			}
			
			// Encode the form data values as a JSON string and output it
			echo json_encode($formdata_values);
			wp_die();
		}
		wp_die();
	}

	/**
	 * FRONTEND - KALENDER VERSION
	 * Saves the data for all forms of a training page (Kalender-spezifische Version)
	 * KOMPLETT UNABHÄNGIG von saveData() - KEIN FALLBACK!
	 */
	public function saveDataCalendar() {
		$canSave = get_user_meta(wp_get_current_user()->ID, 'can_save', true);

		if($canSave == null || $canSave == "" || $canSave == 1) { // Only when user is allowed to store data in database
			
			if(isset($_POST['datastr']) && strlen(trim($_POST['datastr'])) > 1) {
				
				$data = json_decode(stripslashes($_POST['datastr']), true);

				if(json_last_error() == JSON_ERROR_NONE) {

					$usermodus = false;
					$uid = get_current_user_id();
					$selectui = '' . get_user_meta(wp_get_current_user()->ID, 'coach_select_user', true);
					if ($selectui != '') {
						$uid = $selectui;
						$usermodus = true;
					}

					$mailerror = false;
					$mailsend = false;
					$captchaerror = $this->validateCaptcha($uid, $usermodus, $data);

					if(!$captchaerror && !$usermodus) {
						
						// Kalender-spezifische Parameter aus POST holen (AJAX-Request)
						$calendar_id = isset($_POST['calendar_id']) ? sanitize_text_field($_POST['calendar_id']) : '';
						$date = isset($_POST['date']) ? sanitize_text_field($_POST['date']) : '';
						
						// Nur fortfahren wenn Kalender-Parameter vorhanden sind
						if($calendar_id && $date) {
							
							foreach($data as $formid => $formdata) {
								
								// Delete all Data for Form by current User if the form has the keep data attribute disabled
								$post = get_post($formid);
								
								$alreadysaved = false; // default false
								if($post->saveonce) {
									$prev_data = Trainingssystem_Plugin_Database::getInstance()->Formfield->getUserFormfieldsByForm($formid, $uid);
									foreach($prev_data as $p_d) {
										foreach($p_d as $fg_pd) {
											if(!is_null($fg_pd->getFormdata())) {
												$alreadysaved = true;
												break;
											}
										}
									}
								}

								if(!$alreadysaved) {
									// Für Kalender-Formulare: KEINE Löschung der Formdata, da Update-Logik verwendet wird
									// Die Update-Logik in den Zeilen darunter kümmert sich um bestehende Einträge

									        if(!$post->nosave && get_current_user_id() !== 0) {
            $fieldIds = array();
            $fieldValues = array();
										
										foreach($formdata as $formgroup => $formgroupdata) {
											foreach($formgroupdata as $fieldid => $value) {
												// If multiple select options selected, encode selection as json to save in DB
												if(is_array($value)) {
													$value = json_encode($value);
												}

												if(strcasecmp("__FILE__", $value) === 0 && isset($_FILES['tsform-field-'.$fieldid.'-'.$formgroup])) {
													$user = get_user_by( 'ID', $uid );
													$file_parts = pathinfo($_FILES['tsform-field-'.$fieldid.'-'.$formgroup]['name']);
													$new_filename = date("Y-m-d-H-i-s") . "-" . $user->user_login . "." . $file_parts['extension'];
													$wp_uploaded_file = wp_upload_bits($new_filename, null, file_get_contents($_FILES['tsform-field-'.$fieldid.'-'.$formgroup]['tmp_name']));
													if(!$wp_uploaded_file['error']) {
														$attachment = array(
															'post_parent' => $formid,
															'post_title' => preg_replace('/\.[^.]+$/', '', $new_filename),
															'post_content' => '',
															'post_status' => 'inherit'
														);
														$attachment_id = wp_insert_attachment( $attachment, $wp_uploaded_file['file'], $formid );
														$value = $attachment_id;
													} else {
														echo "error uploading";
														$value = null;
													}
												} else if (strcasecmp("__FILE__", $value) === 0) {
													$value = null;
												}

												if($value != null) {
													$fieldIds[] = $fieldid;
													$fieldValues[$fieldid] = $value;
												}
											}
										}
										
										            if(!empty($fieldIds)) {
                global $wpdb;

                // Alle existierenden Kalender-Einträge für diese Felder in einem Query laden
											$placeholders = implode(',', array_fill(0, count($fieldIds), '%d'));
											$existing_entries = $wpdb->get_results($wpdb->prepare(
												"SELECT form_field_id, form_data_id FROM {$wpdb->prefix}md_trainingsmgr_calendar_entries 
												WHERE user_id = %d AND calendar_id = %d AND entry_date = %s AND form_field_id IN ($placeholders)",
												array_merge([$uid, $calendar_id, $date], $fieldIds)
											));
											
											                $existing_entries_map = array();
                foreach($existing_entries as $entry) {
                    $existing_entries_map[$entry->form_field_id] = $entry->form_data_id;
                }

                // Jetzt alle Felder verarbeiten
											foreach($fieldIds as $fieldid) {
												$value = $fieldValues[$fieldid];
												
												                    if(isset($existing_entries_map[$fieldid])) {
                        $wpdb->update(
														$wpdb->prefix . 'md_trainingsmgr_ts_forms_data',
														array(
															'data' => $value,
															'save_date' => current_time('mysql')
														),
														array(
															'ID' => $existing_entries_map[$fieldid]
														),
														array('%s', '%s'),
														array('%d')
													);
												                    } else {
                        $insert_success = Trainingssystem_Plugin_Database::getInstance()->Formdata->insertFormDataForUser($fieldid, $uid, $value, 0, current_time('mysql'));
													
													if($insert_success) {
														// Hole die ID des gerade eingefügten Eintrags
														$form_data_id = $wpdb->insert_id;
														
														if($form_data_id) {
															// Erstelle neuen Eintrag in wp_md_trainingsmgr_calendar_entries
															$wpdb->insert(
																$wpdb->prefix . 'md_trainingsmgr_calendar_entries',
																array(
																	'user_id' => $uid,
																	'calendar_id' => $calendar_id,
																	'entry_date' => $date,
																	'form_id' => $formid,
																	'form_field_id' => $fieldid,
																	'form_data_id' => $form_data_id,
																	'created_at' => current_time('mysql'),
																	'updated_at' => current_time('mysql')
																),
																array('%d', '%d', '%s', '%d', '%d', '%d', '%s', '%s')
															);
														}
													}
												}
											}
										}
									}

									$sendbymail = get_post_meta($formid, 'sendbymail', true);
									$sendtomail = get_post_meta($formid, 'sendtomail', true);

									if($sendbymail == "1" && trim($sendtomail) != "") {

										$mailsend = true;
										
										$twig = Trainingssystem_Plugin_Twig::getInstance()->twig;

										$blogname = get_bloginfo('name');
										$formtitle = get_the_title($formid);

										$formfields_tmp = Trainingssystem_Plugin_Database::getInstance()->Formfield->getFormfieldsByForm($formid);
										$formfields = array();
										foreach($formfields_tmp as $tmp) {
											$formfields[$tmp->getFieldId()] = $tmp;
										}

										$mail_to  = $sendtomail;
										$mail_subject = 'Eingabe in das Formular ' . $formtitle . ' auf ' . $blogname;
										$mail_content = $twig->render('forms/form-mail.html', ["blogname" => $blogname, "formtitle" => $formtitle, "formdata" => $formdata, "formfields" => $formfields]);
										$headers = array('Content-Type: text/html; charset=UTF-8');
										
										$email_adresses = explode(";", $sendtomail);

										foreach($email_adresses as $email_adress) {
											if(!wp_mail($email_adress, $mail_subject, $mail_content, $headers )) {
												$mailerror = true;
											}
										}
									}

									$send_receipt = get_post_meta($formid, 'sendreceipt', true);

									if($send_receipt == "1") {
										$mailsend = true;

										$receipt_subject = get_post_meta($formid, 'send_receipt_subject', true);
										$receipt_text = get_post_meta($formid, 'send_receipt_text', true);

										if(trim($receipt_subject) != "" && trim($receipt_text) != "") {

											$mail_to = null;
											if(0 == get_current_user_id()) {

												$formfields_tmp = Trainingssystem_Plugin_Database::getInstance()->Formfield->getFormfieldsByForm($formid);
												$formfields = array();
												foreach($formfields_tmp as $tmp) {
													if($tmp->getType() == "input" && isset($tmp->getAttributesJsonDecoded()['type']) && $tmp->getAttributesJsonDecoded()['type'] == "email") {
														if(isset($formdata[0][$tmp->getFieldId()]) && trim($formdata[0][$tmp->getFieldId()]) != "") {
															if(filter_var($formdata[0][$tmp->getFieldId()], FILTER_VALIDATE_EMAIL)) {
																$mail_to = $formdata[0][$tmp->getFieldId()];
															}
															break;
														}
													}
												}
													
											} else {
												$curr_user = wp_get_current_user();
												$mail_to = $curr_user->user_email;
											}
										}
										if($mail_to != null) {

											$headers = array('Content-Type: text/html; charset=UTF-8');
											if(!wp_mail($mail_to, $receipt_subject, $receipt_text, $headers)) {
												$mailerror = true;
											}
										}
									}
								}
							}
						} else {
							// Kalender-Parameter fehlen - KEIN FALLBACK!
							error_log("KALENDER DEBUG: Kalender-Parameter fehlen - calendar_id: '" . $calendar_id . "', date: '" . $date . "'");
							error_log("KALENDER DEBUG: KEIN FALLBACK - Kalender-spezifische Funktion wird beendet");
							echo "calendar_parameters_missing";
							wp_die();
						}
					}
					if($mailerror) {
						echo "mailerror";
					} elseif($mailsend) {
						echo "mailsuccess";
					} elseif($captchaerror) {
						echo "captchaerror";
					} else {
						echo "success";
					}

				} else {
					echo "invalid json";
				}

			} else {
				echo "no data";
			}
		} else {
			echo "no permission";
		}
		wp_die();
	}

	/**
	 * FRONTEND
	 * Saves the data for all forms of a training page  
	 */
	public function saveData() {
		$canSave = get_user_meta(wp_get_current_user()->ID, 'can_save', true);

		if($canSave == null || $canSave == "" || $canSave == 1) { // Only when user is allowed to store data in database
			
			if(isset($_POST['datastr']) && strlen(trim($_POST['datastr'])) > 1) {
				
				$data = json_decode(stripslashes($_POST['datastr']), true);

				if(json_last_error() == JSON_ERROR_NONE) {

					$usermodus = false;
					$uid = get_current_user_id();
					$selectui = '' . get_user_meta(wp_get_current_user()->ID, 'coach_select_user', true);
					if ($selectui != '') {
						$uid = $selectui;
						$usermodus = true;
					}

					$mailerror = false;
					$mailsend = false;
					$captchaerror = $this->validateCaptcha($uid, $usermodus, $data);

					if(!$captchaerror && !$usermodus) {
						foreach($data as $formid => $formdata) {
							
							// Delete all Data for Form by current User if the form has the keep data attribute disabled
							$post = get_post($formid);
							
							$alreadysaved = false; // default false
							if($post->saveonce) {
								$prev_data = Trainingssystem_Plugin_Database::getInstance()->Formfield->getUserFormfieldsByForm($formid, $uid);
								foreach($prev_data as $p_d) {
									foreach($p_d as $fg_pd) {
										if(!is_null($fg_pd->getFormdata())) {
											$alreadysaved = true;
											break;
										}
									}
								}
							}

							if(!$alreadysaved) {
								if(!$post->keepdata && get_current_user_id() !== 0) {
									if(!Trainingssystem_Plugin_Database::getInstance()->Formdata->deleteFormDataForUser($formid, $uid)) {
										echo "error deleting the previous data";
										wp_die();
									}
								}

								if(!$post->nosave && get_current_user_id() !== 0) {
									foreach($formdata as $formgroup => $formgroupdata) {
										foreach($formgroupdata as $fieldid => $value) {

											// If multiple select options selected, encode selection as json to save in DB
											if(is_array($value)) {
												$value = json_encode($value);
											}

											if(strcasecmp("__FILE__", $value) === 0 && isset($_FILES['tsform-field-'.$fieldid.'-'.$formgroup])) {
												$user = get_user_by( 'ID', $uid );
												$file_parts = pathinfo($_FILES['tsform-field-'.$fieldid.'-'.$formgroup]['name']);
												$new_filename = date("Y-m-d-H-i-s") . "-" . $user->user_login . "." . $file_parts['extension'];
												$wp_uploaded_file = wp_upload_bits($new_filename, null, file_get_contents($_FILES['tsform-field-'.$fieldid.'-'.$formgroup]['tmp_name']));
												if(!$wp_uploaded_file['error']) {
													$attachment = array(
														'post_parent' => $formid,
														'post_title' => preg_replace('/\.[^.]+$/', '', $new_filename),
														'post_content' => '',
														'post_status' => 'inherit'
													);
													$attachment_id = wp_insert_attachment( $attachment, $wp_uploaded_file['file'], $formid );
													$value = $attachment_id;
												} else {
													echo "error uploading";
													$value = null;
												}
											} else if (strcasecmp("__FILE__", $value) === 0) {
												$value = null;
											}

											if($value != null) {
												// Save each field data into the DB
												if(!Trainingssystem_Plugin_Database::getInstance()->Formdata->insertFormDataForUser($fieldid, $uid, $value, $formgroup)) {
													echo "error inserting new formdata";
													wp_die();
												}
											}
										}
									}
								}

								$sendbymail = get_post_meta($formid, 'sendbymail', true);
								$sendtomail = get_post_meta($formid, 'sendtomail', true);

								if($sendbymail == "1" && trim($sendtomail) != "") {

									$mailsend = true;
									
									$twig = Trainingssystem_Plugin_Twig::getInstance()->twig;

									$blogname = get_bloginfo('name');
									$formtitle = get_the_title($formid);

									$formfields_tmp = Trainingssystem_Plugin_Database::getInstance()->Formfield->getFormfieldsByForm($formid);
									$formfields = array();
									foreach($formfields_tmp as $tmp) {
										$formfields[$tmp->getFieldId()] = $tmp;
									}

									$mail_to  = $sendtomail;
									$mail_subject = 'Eingabe in das Formular ' . $formtitle . ' auf ' . $blogname;
									$mail_content = $twig->render('forms/form-mail.html', ["blogname" => $blogname, "formtitle" => $formtitle, "formdata" => $formdata, "formfields" => $formfields]);
									$headers = array('Content-Type: text/html; charset=UTF-8');
									
									$email_adresses = explode(";", $sendtomail);

									foreach($email_adresses as $email_adress) {
										if(!wp_mail($email_adress, $mail_subject, $mail_content, $headers )) {
											$mailerror = true;
										}
									}
								}

								$send_receipt = get_post_meta($formid, 'sendreceipt', true);

								if($send_receipt == "1") {
									$mailsend = true;

									$receipt_subject = get_post_meta($formid, 'send_receipt_subject', true);
									$receipt_text = get_post_meta($formid, 'send_receipt_text', true);

									if(trim($receipt_subject) != "" && trim($receipt_text) != "") {

										$mail_to = null;
										if(0 == get_current_user_id()) {

											$formfields_tmp = Trainingssystem_Plugin_Database::getInstance()->Formfield->getFormfieldsByForm($formid);
											$formfields = array();
											foreach($formfields_tmp as $tmp) {
												if($tmp->getType() == "input" && isset($tmp->getAttributesJsonDecoded()['type']) && $tmp->getAttributesJsonDecoded()['type'] == "email") {
													if(isset($formdata[0][$tmp->getFieldId()]) && trim($formdata[0][$tmp->getFieldId()]) != "") {
														if(filter_var($formdata[0][$tmp->getFieldId()], FILTER_VALIDATE_EMAIL)) {
															$mail_to = $formdata[0][$tmp->getFieldId()];
														}
														break;
													}
												}
											}
												
										} else {
											$curr_user = wp_get_current_user();
											$mail_to = $curr_user->user_email;
										}
									}
									if($mail_to != null) {

										$headers = array('Content-Type: text/html; charset=UTF-8');
										if(!wp_mail($mail_to, $receipt_subject, $receipt_text, $headers)) {
											$mailerror = true;
										}
									}
								}
							}
						}
					}
					if($mailerror) {
						echo "mailerror";
					} elseif($mailsend) {
						echo "mailsuccess";
					} elseif($captchaerror) {
						echo "captchaerror";
					} else {
						echo "success";
					}

				} else {
					echo "invalid json";
				}

			} else {
				echo "invalid data";
			}
		} else { // if user is not allowed to store data, just return a success
			echo "success";
		}
		wp_die();
	}

	/**
	 * FRONTEND
	 * Displays content of the shortcode if input of a form equals a specific value
	 */
	public function tsFormsConditional($atts, $content = "") {
		
		$twig = Trainingssystem_Plugin_Twig::getInstance()->twig;

		if(isset($atts['tsformid']) && strtolower(get_post_type($atts['tsformid'])) === "formulare" && 
				(
					isset($atts['value']) || 
					(
						isset($atts['range_min']) && trim($atts['range_min']) != "" && is_numeric($atts['range_min']) 
						&&
						isset($atts['range_max']) && trim($atts['range_max']) != "" && is_numeric($atts['range_max'])
					)
				) && 
			trim($content) != "") {

			$range = false;
			$value = (isset($atts['value'])) ? $atts['value'] : "";
			$range_min = isset($atts['range_min']) ? $atts['range_min'] : 0;
			$range_max = isset($atts['range_max']) ? $atts['range_max'] : 0;
			$row = (isset($atts['row']) && is_numeric($atts['row'])) ? $atts['row'] : null;
			if(isset($atts['range_min']) && isset($atts['range_max'])) {
				$range = true;
			}
			
			$samepage = true;
			if(isset($atts['samepage']) && trim($atts['samepage']) == "false") {
				$samepage = false;
			}

			$formid = $atts['tsformid'];

			$uid = get_current_user_id();
			$selectui = '' . get_user_meta(wp_get_current_user()->ID, 'coach_select_user', true);
			if ($selectui != '') {
				$uid = $selectui;
			}

			$formgroups = Trainingssystem_Plugin_Database::getInstance()->Formfield->getUserFormfieldsByForm($formid, $uid);

			$formgroupindex = count($formgroups)-1;
			if(isset($atts['formgroup']) && isset($formgroups[$atts['formgroup']])) {
				$formgroupindex = $atts['formgroup'];
			}
			$formgroup = isset($formgroups[$formgroupindex]) ? $formgroups[$formgroupindex] : null;

			if($formgroup != null) {

				$fieldindex = 0;

				if(isset($atts['fieldid']) && trim($atts['fieldid']) != "" && is_numeric($atts['fieldid'])) {
					foreach($formgroup as $key => $formfield) {
						if($formfield->getFieldId() == $atts['fieldid']) {
							$fieldindex = $key;
							break;
						}
					}
				}

				if(isset($formgroup[$fieldindex])) {

					if(($range && $formgroup[$fieldindex]->getType() != "slider") || (is_null($row) && $formgroup[$fieldindex]->getType() == "scale" && $formgroup[$fieldindex]->getType() != "matrix") || (is_null($row) && $formgroup[$fieldindex]->getType() != "scale" && $formgroup[$fieldindex]->getType() == "matrix")) {
						return $twig->render("forms/ts-forms-conditional-error.html");
					}

					$formdata = $formgroup[$fieldindex]->getFormdata();

					$htmlcontent = do_shortcode($content);
					$show = false;

					if($formdata != null) {

						if($formdata->dataIsArray()) {
							$dataArray = $formdata->getDataJsonDecoded();

							if($formgroup[$fieldindex]->getType() != "scale" || $formgroup[$fieldindex]->getType() != "matrix") {

								if(isset($dataArray[($row-1)]) && $dataArray[($row-1)] == $value) {
									$show = true;
								}

							} else {
							
								foreach($dataArray as $key => $dataOption) {
									if($dataOption == $value) {
										$show = true;
									}
								}
							}
						
						} else {
							if($range) {
								if($formdata->getData() >= $range_min && $formdata->getData() <= $range_max) {
									$show = true;
								}
							} else {
								if($formdata->getData() == $value) {
									$show = true;
								}
							}
						}
					} elseif($formdata == null && $value == "" && !$range) {
						$show = true;
					} else if(isset($atts['show_on_default']) && $atts['show_on_default'] == "true") {

						if($formgroup[$fieldindex]->getType() == "select" || $formgroup[$fieldindex]->getType() == "radio") {

							foreach($formgroup[$fieldindex]->getAttributesJsonDecoded()['elements'] as $element) {
								if($element['selected'] == "true" && $element['value'] == $value) {
									$show = true;
								}
							}

						} elseif($formgroup[$fieldindex]->getType() == "input" || $formgroup[$fieldindex]->getType() == "textarea" || $formgroup[$fieldindex]->getType() == "checkbox" || $formgroup[$fieldindex]->getType() == "slider") {

							$def_val = $formgroup[$fieldindex]->getAttributesJsonDecoded()['value'];

							if($range) {
								if($def_val >= $range_min && $def_val <= $range_max) {
									$show = true;
								}
							} else {
								if($def_val == $value) {
									$show = true;
								}
							}
						}
					}

					return $twig->render("forms/ts-forms-conditional.html", [
																			"samepage" => $samepage,
																			"htmlcontent" => $htmlcontent,
																			"formid" => $formid,
																			"formgroupindex" => $formgroupindex,
																			"fieldindex" => $fieldindex,
																			"fieldid" => $formgroup[$fieldindex]->getFieldId(),
																			"type" => $formgroup[$fieldindex]->getType(),
																			"value" => $value,
																			"range_min" => $range_min,
																			"range_max" => $range_max,
																			"show" => $show,
																			"range" => $range,
																			"row" => $row,
																			"randid" => bin2hex(random_bytes(32)),
																			]);
				}
			}			
		} else {
			return $twig->render("forms/ts-forms-conditional-error.html");
		}
	}

	/**
	 * HELPER
	 * Exports a Form to migrate within multiple platforms, either as JSON or as PHP Array
	 * 
	 * @param int form ID
	 * @param boolean return JSON encoded, default true
	 * @param String or null TS Form Title Append. Ignored if null
	 * 
	 * @return String Form with all fields as JSON or PHP Array
	 */
	public function exportForm($formid, $jsonencoded = true, $tsformAppend = null) {
		$ret = array();

		if(strtolower(get_post_type($formid)) === "formulare") {

			$ret['title'] = get_the_title($formid);
			if(!is_null($tsformAppend)) {
				$ret['title'] .= $tsformAppend;
			}
			$ret['multiform'] = get_post_meta($formid, 'isMultiform', true) == "1";
			$ret['multiformOrdering'] = get_post_meta($formid, 'multiformOrdering', true) == "1";
			$ret['multiformOrientation'] = get_post_meta($formid, 'multiformOrientation', true);
			$ret['submitmanually'] = get_post_meta($formid, 'submitmanually', true) == "1";
			$ret['submitmanuallylink'] = get_post_meta($formid, 'submitmanuallylink', true);
			$ret['sendbymail'] = get_post_meta($formid, 'sendbymail', true) == "1";
			$ret['sendtomail'] = get_post_meta($formid, 'sendtomail', true);
			$ret['keepdata'] = get_post_meta($formid, 'keepdata', true) == "1";
			$ret['saveonce'] = get_post_meta($formid, 'saveonce', true) == "1";
			$ret['nosave'] = get_post_meta($formid, 'nosave', true) == "1";
			$ret['css'] = get_post_meta($formid, 'formCss', true);

			$ret['fields'] = array();
			$groups = Trainingssystem_Plugin_Database::getInstance()->Formfield->getFormfieldsByForm($formid);

			foreach($groups as $field) {
				$ret['fields'][$field->getIndex()] = array();
				$ret['fields'][$field->getIndex()]['type'] = $field->getType();
				$ret['fields'][$field->getIndex()]['attributes'] = $field->getAttributes();
				$ret['fields'][$field->getIndex()]['sort_index'] = $field->getIndex();
			}
		}

		if($jsonencoded) {
			return json_encode($ret);
		} else {
			return $ret;
		}
	}

	/**
	 * HELPER
	 * Imports a form and creates all its fields
	 * 
	 * @param Array|String data: if data is not an array, we try to json_deocde it, otherwise this function won't do anything
	 * 
	 * @return null|int Returns the int of the newly created form on success or null if anything went wrong
	 */
	public function importForm($data) {

		if(!is_array($data)) {
			$jsondata = json_decode($data, true);
			if(json_last_error() == JSON_ERROR_NONE) {
				$data = $jsondata;
			}
		}

		if(is_array($data) && isset($data['title']) && isset($data['multiform']) && isset($data['multiformOrdering']) && isset($data['multiformOrientation']) && 
			isset($data['submitmanually']) && isset($data['submitmanuallylink']) &&
			isset($data['sendbymail']) && isset($data['sendtomail']) &&
			isset($data['keepdata']) && isset($data['nosave']) &&
			isset($data['css']) &&  isset($data['fields']) && is_array($data['fields'])) {

			$insert_title = $data['title'];
			while(count(get_posts(array("post_type" => "formulare", "title" => $insert_title))) > 0) {
				$insert_title .= " Kopie";
			}

			$wp_form = array(
				"post_title" => $insert_title,
				"post_status" => "publish",
				"post_type" => "formulare",
			);

			$wp_form_id = wp_insert_post($wp_form);

			if(!is_wp_error($wp_form_id)) {

				update_post_meta($wp_form_id, "isMultiform", $data['multiform']);
				update_post_meta($wp_form_id, "multiformOrdering", $data['multiformOrdering']);
				update_post_meta($wp_form_id, "multiformOrientation", $data['multiformOrientation']);
				update_post_meta($wp_form_id, "submitmanually", $data['submitmanually']);
				update_post_meta($wp_form_id, "submitmanuallylink", $data['submitmanuallylink']);
				update_post_meta($wp_form_id, "sendbymail", $data['sendbymail']);
				update_post_meta($wp_form_id, "sendtomail", $data['sendtomail']);
				update_post_meta($wp_form_id, "keepdata", $data['keepdata']);
				update_post_meta($wp_form_id, "saveonce", $data['saveonce']);
				update_post_meta($wp_form_id, "nosave", $data['nosave']);
				update_post_meta($wp_form_id, "formCss", $data['css']);

				if(Trainingssystem_Plugin_Database::getInstance()->Formfield->importFormfields($wp_form_id, $data['fields'])) {
					return $wp_form_id;
				} else {
					delete_post_meta($wp_form_id, "isMultiform");
					delete_post_meta($wp_form_id, "multiformOrdering");
					delete_post_meta($wp_form_id, "multiformOrientation");
					delete_post_meta($wp_form_id, "submitmanually");
					delete_post_meta($wp_form_id, "submitmanuallylink");
					delete_post_meta($wp_form_id, "sendbymail");
					delete_post_meta($wp_form_id, "sendtomail");
					delete_post_meta($wp_form_id, "keepdata");
					delete_post_meta($wp_form_id, "saveonce");
					delete_post_meta($wp_form_id, "nosave");
					delete_post_meta($wp_form_id, "formCss");

					wp_delete_post($wp_form_id, true);

					return null;
				}

			} else {
				return null;
			}

		} else {
			return null;
		}
	}

	/**
	 * HELPER
	 * Renders an Array of Formgroups and returns the html content
	 * 
	 * @param int form ID
	 * @param Array form groups
	 * @param boolean preview default false
	 * 
	 * @return String rendered HTML Content
	 */
	private function renderForm($formid, Array $formgroups, $preview = false, $usermodus = false, $overrideKeepdataForCalendar = false) {

		$is_multiform = get_post_meta($formid, 'isMultiform', true) == "1";
		$multiform_ordering = get_post_meta($formid, 'multiformOrdering', true) == "1";
		$submitmanually = get_post_meta($formid, 'submitmanually', true) == "1";
		$submitmanuallylink = get_post_meta($formid, 'submitmanuallylink', true);
		$form_css = get_post_meta($formid, 'formCss', true);
		$multiform_orientation = get_post_meta($formid, 'multiformOrientation', true);
		$keep_data_meta = get_post_meta($formid, 'keepdata', true) == "1";
		$keep_data = $overrideKeepdataForCalendar ? false : $keep_data_meta;
		$saveonce = get_post_meta($formid, 'saveonce', true) == "1";

		$saveOnceDisable = false;
		$saveOnceDate = "";
		if($saveonce) {
			foreach($formgroups as $formgroup) {
				foreach($formgroup as $formfield) {
					if(!is_null($formfield->getFormdata())) {
						$saveOnceDisable = true;
						$saveOnceDate = $formfield->getFormdata()->getSaveDate();
					}
				}
			}
		}

		/* implement possibility for custom css-classes here: */
		$scale_smileys = array(
						"far fa-angry", 
						"far fa-frown", 
						"far fa-meh", 
						"far fa-smile",
						"far fa-laugh"
						);
		
		$twig = Trainingssystem_Plugin_Twig::getInstance()->twig;
		return $twig->render("forms/form.html", [	"formid" => $formid,
													"is_multiform" => $is_multiform,
													"multiform_ordering" => $multiform_ordering,
													"multiform_orientation" => $multiform_orientation,
													"submitmanually" => $submitmanually,
													"submitmanuallylink" => $submitmanuallylink,
													"form_css" => $form_css, 
													"groups" => $formgroups, 
													"preview" => $preview,
													"usermodus" => $usermodus,
													"keepdata" => $keep_data,
													"saveOnceDisable" => $saveOnceDisable,
													"saveOnceDate" => $saveOnceDate,
													"scale_smileys" => $scale_smileys,
											]);
	}

	/**
	 * Kalender-Prefill: Hole form_data_id pro Feld aus calendar_entries und injiziere die zugehörigen Formdata
	 */
	private function injectCalendarPrefill($formid, $userid, $calendarId, $date, $formgroups) {
		echo "<!-- injectCalendarPrefill: Called with formid=" . $formid . ", userid=" . $userid . ", calendarId=" . $calendarId . ", date=" . $date . " -->";
		global $wpdb;

		$calendar_entries_table = $wpdb->prefix . Trainingssystem_Plugin_Database_Calendar_Entry_Daoimple::$dbprefix; // wp_md_trainingsmgr_calendar_entries
		$formdata_table = $wpdb->prefix . Trainingssystem_Plugin_Database_Formdata_Daoimple::$dbprefix; // wp_md_trainingsmgr_ts_form_data

		        $dataRows = $wpdb->get_results($wpdb->prepare(
			"SELECT fd.ID, fd.field_ID, fd.user_ID, fd.data, fd.save_date, fd.form_group 
			 FROM {$formdata_table} fd
			 INNER JOIN {$calendar_entries_table} ce ON fd.ID = ce.form_data_id
			 WHERE ce.user_id = %d AND ce.calendar_id = %d AND ce.entry_date = %s AND ce.form_id = %d",
			$userid, $calendarId, $date, $formid
		));
		
		echo "<!-- injectCalendarPrefill: Found " . count($dataRows) . " data rows -->";
		
		if(empty($dataRows)) {
			echo "<!-- injectCalendarPrefill: No calendar entries found - clearing form data -->";
			
			// DEBUG: Zeige alle verfügbaren Formdata-Einträge für diesen User und diese Felder
			$fieldIds = array();
			foreach($formgroups as $gFields) {
				foreach($gFields as $ff) {
					$fieldIds[] = $ff->getFieldId();
				}
			}
			
			if(!empty($fieldIds)) {
				$placeholders = implode(',', array_fill(0, count($fieldIds), '%d'));
				$allFormData = $wpdb->get_results($wpdb->prepare(
					"SELECT fd.ID, fd.field_ID, fd.user_ID, fd.data, fd.save_date, fd.form_group 
					 FROM {$formdata_table} fd
					 WHERE fd.user_ID = %d AND fd.field_ID IN ($placeholders)",
					array_merge([$userid], $fieldIds)
				));
				
				echo "<!-- DEBUG: All formdata entries for user $userid and fields " . implode(',', $fieldIds) . ": -->";
				foreach($allFormData as $entry) {
					echo "<!-- Formdata: ID=" . $entry->ID . ", field_ID=" . $entry->field_ID . ", data='" . htmlspecialchars($entry->data) . "', form_group=" . $entry->form_group . " -->";
				}
				
				// Versuche Fallback-Prefill
				$fieldGroupToFormdata = array();
				foreach($allFormData as $r) {
					$key = $r->form_group . ':' . intval($r->field_ID);
					$fieldGroupToFormdata[$key] = new Trainingssystem_Plugin_Database_Formdata(
						intval($r->ID),
						intval($r->field_ID),
						intval($r->user_ID),
						$r->data,
						$r->save_date,
						intval($r->form_group)
					);
				}
				
				// Jetzt die Formgroups durchgehen und die Formdata setzen
				foreach($formgroups as $gIdx => &$gFields) {
					foreach($gFields as $ff) {
						// Versuche verschiedene form_group Kombinationen
						$key1 = $gIdx . ':' . $ff->getFieldId();
						$key2 = '0:' . $ff->getFieldId(); // Fallback auf Gruppe 0
						
						if(isset($fieldGroupToFormdata[$key1])) {
							echo "<!-- Setting formdata for field " . $ff->getFieldId() . " with key: $key1 -->";
							$ff->setFormdata($fieldGroupToFormdata[$key1]);
						} elseif(isset($fieldGroupToFormdata[$key2])) {
							echo "<!-- Setting formdata for field " . $ff->getFieldId() . " with key: $key2 -->";
							$ff->setFormdata($fieldGroupToFormdata[$key2]);
						} else {
							echo "<!-- No formdata found for field " . $ff->getFieldId() . " -->";
							$ff->setFormdata(null);
						}
					}
				}
				unset($gFields);
				return $formgroups;
			}
			
			// Es gibt keine Calendar-Entries mit Formdata -> Formular LEER lassen
			foreach($formgroups as $gIdx => &$gFields) {
				foreach($gFields as $ff) { $ff->setFormdata(null); }
			}
			unset($gFields);
			return $formgroups;
		}

		// Map (form_group, field_id) -> Formdata-Objekt
		$fieldGroupToFormdata = array();
		foreach($dataRows as $r) {
			// Kalender-Ansicht rendert nur Gruppe 0 -> immer auf Gruppe 0 mappen
			$key = '0:' . intval($r->field_ID);
			$fieldGroupToFormdata[$key] = new Trainingssystem_Plugin_Database_Formdata(
				intval($r->ID),
				intval($r->field_ID),
				intval($r->user_ID),
				$r->data,
				$r->save_date,
				0
			);
		}

		// In die aktuellen Formgroups einsetzen (Index entspricht form_group)
		// Wichtig: Zuerst alle bestehenden Formdata leeren, damit nur die in calendar_entries referenzierten Werte angezeigt werden
		foreach($formgroups as $groupIndex => &$groupFields) {
			foreach($groupFields as $formfield) {
				// Alles leeren
				$formfield->setFormdata(null);
				// Nur setzen, wenn für (form_group, field_id) ein Eintrag existiert
				$mapKey = $groupIndex . ':' . $formfield->getFieldId();
				if(isset($fieldGroupToFormdata[$mapKey])) {
					$formfield->setFormdata($fieldGroupToFormdata[$mapKey]);
				}
			}
		}
		unset($groupFields);

		return $formgroups;
	}

	/**
	 * HELPER
	 * 
	 * @param type FormField-Type
	 * @param data Array of Formfield Data
	 * 
	 * @return Array converted Data
	 */
	private function getInsertData($type, $data) {

		$idata = array();

		switch($type) {
			case "input":
				
				$idata['label'] = $data['textfeldLabel'];
				$idata['labelPosition'] = $data['textfeldLabelPosition'];
				$idata['placeholder'] = $data['textfeldPlaceholder'];
				$idata['maxlength'] = $data['textfeldMaxlength'];
				$idata['css'] = $data['textfeldCss'];
				$idata['parentcss'] = $data['textfeldParentCss'];
				$idata['value'] = $data['textfeldValue'];
				$idata['type'] = $data['textfeldType'];
				$idata['min'] = $data['textfeldMin'];
				$idata['max'] = $data['textfeldMax'];
				$idata['step'] = $data['textfeldStep'];
				$idata['disabled'] = $data['textfeldDisabled'];
				$idata['required'] = $data['textfeldRequired'];

				break;

			case "textarea":

				$idata['label'] = $data['textareaLabel'];
				$idata['labelPosition'] = $data['textareaLabelPosition'];
				$idata['placeholder'] = $data['textareaPlaceholder'];
				$idata['maxlength'] = $data['textareaMaxlength'];
				$idata['rows'] = $data['textareaRows'];
				$idata['css'] = $data['textareaCss'];
				$idata['parentcss'] = $data['textareaParentCss'];
				$idata['value'] = $data['textareaValue'];
				$idata['disabled'] = $data['textareaDisabled'];
				$idata['required'] = $data['textareaRequired'];

				break;

			case "select":

				$idata['label'] = $data['selectLabel'];
				$idata['labelPosition'] = $data['selectLabelPosition'];
				$idata['size'] = $data['selectSize'];
				$idata['css'] = $data['selectCss'];
				$idata['parentcss'] = $data['selectParentCss'];
				$idata['useradd'] = $data['selectUserAdd'];
				$idata['multiple'] = $data['selectMultiple'];
				$idata['disabled'] = $data['selectDisabled'];
				$idata['required'] = $data['selectRequired'];
				
				$idata['elements'] = $data['elements'];

				break;

			case "radio":

				$idata['title'] = $data['radioTitle'];
				$idata['labelPosition'] = $data['radioLabelPosition'];
				$idata['parentcss'] = $data['radioParentCss'];
				$idata['formCheckCss'] = $data['radioformCheckCss'];
				$idata['required'] = $data['radioRequired'];
				$idata['inline'] = $data['radioInline'];
				
				$idata['elements'] = $data['elements'];

				break;

			case "checkbox":

				$idata['label'] = $data['checkboxLabel'];
				$idata['value'] = $data['checkboxValue'];
				$idata['labelPosition'] = $data['checkboxLabelPosition'];
				$idata['css'] = $data['checkboxCss'];
				$idata['parentcss'] = $data['checkboxParentCss'];
				$idata['disabled'] = $data['checkboxDisabled'];
				$idata['selected'] = $data['checkboxSelected'];
				$idata['inline'] = $data['checkboxInline'];

				break;

			case "slider":

				$idata['label'] = $data['sliderLabel'];
				$idata['min'] = $data['sliderMin'];
				$idata['max'] = $data['sliderMax'];
				$idata['step'] = $data['sliderStep'];
				$idata['labelPosition'] = $data['sliderLabelPosition'];
				$idata['css'] = $data['sliderCss'];
				$idata['parentcss'] = $data['sliderParentCss'];
				$idata['value'] = $data['sliderValue'];
				$idata['disabled'] = $data['sliderDisabled'];
				$idata['tooltip'] = $data['sliderTooltip'];
				$idata['colorschema'] = $data['sliderColorSchema'];
				$idata['tooltipText'] = $data['sliderTooltipText'];
				$idata['valueLabels'] = isset($data['sliderValueLabels']) ? $data['sliderValueLabels'] : '';
				break;

			case "text":

				$idata['text'] = $data['textText'];
				$idata['type'] = $data['textType'];
				$idata['textPosition'] = $data['textPosition'];
				$idata['css'] = $data['textCss'];
				$idata['parentcss'] = $data['textParentCss'];
				break;

			case "scale":
				$idata['headline'] = $data['scaleHeadline'];
				$idata['selectCount'] = $data['scaleSelectcount'];
				$idata['headlinePosition'] = $data['scaleHeadlinePosition'];
				$idata['headlineType'] = $data['scaleHeadlineType'];
				$idata['headlineCss'] = $data['scaleHeadlineCss'];
				$idata['subheadlinePosition'] = $data['scaleSubheadlinePosition'];
				$idata['subheadlineType'] = $data['scaleSubheadlineType'];
				$idata['subheadlineCss'] = $data['scaleSubheadlineCss'];
				$idata['labelLeftPosition'] = $data['scaleLabelLeftPosition'];
				$idata['labelRightPosition'] = $data['scaleLabelRightPosition'];
				$idata['labelType'] = $data['scaleLabelType'];
				$idata['labelCss'] = $data['scaleLabelCss'];
				$idata['numberLabels'] = $data['scalenumberLabels'];
				$idata['visualInput'] = $data['scaleVisualInput'];
				$idata['tableCss'] = $data['scaleTableCss'];
				$idata['parentCss'] = $data['scaleParentCss'];
				$idata['striped'] = $data['scaleStriped'];
				$idata['border'] = $data['scaleBorder'];
				$idata['hover'] = $data['scaleHover'];
				$idata['small'] = $data['scaleSmall'];
				$idata['disabled'] = $data['scaleDisabled'];
				$idata['required'] = $data['scaleRequired'];

				$idata['elements'] = $data['elements'];
				break;

			case "matrix":
				$idata['headline'] = $data['matrixHeadline'];
				$idata['selectCount'] = $data['matrixSelectcount'];
				$idata['headlinePosition'] = $data['matrixHeadlinePosition'];
				$idata['headlineType'] = $data['matrixHeadlineType'];
				$idata['headlineCss'] = $data['matrixHeadlineCss'];
				$idata['headingsPosition'] = $data['matrixHeadingsPosition'];
				$idata['headingsPositionVertical'] = $data['matrixHeadingsPositionVertical'];
				$idata['headingsPositionRotate'] = $data['matrixHeadingsPositionRotate'];
				$idata['headingsPositionRotateOnMobile'] = $data['matrixHeadingsPositionRotateOnMobile'];
				$idata['headingsHeight'] = $data['matrixHeadingsHeight'];
				$idata['headingsPositionRepeatBottom'] = $data['matrixHeadingsPositionRepeatBottom'];
				$idata['headingsType'] = $data['matrixHeadingsType'];
				$idata['headingsCss'] = $data['matrixHeadingsCss'];
				$idata['headingsCssParent'] = $data['matrixHeadingsCssParent'];
				$idata['questionHeadline'] = $data['matrixQuestionHeadline'];
				$idata['questionHeadlineCss'] = $data['matrixQuestionHeadlineCss'];
				$idata['questionPosition'] = $data['matrixQuestionPosition'];
				$idata['questionType'] = $data['matrixQuestionType'];
				$idata['questionCss'] = $data['matrixQuestionCss'];
				$idata['questionCssParent'] = $data['matrixQuestionCssParent'];
				$idata['answerCss'] = $data['matrixAnswerCss'];
				$idata['answerCssParent'] = $data['matrixAnswerCssParent'];
				$idata['tableCss'] = $data['matrixTableCss'];
				$idata['parentCss'] = $data['matrixParentCss'];
				$idata['striped'] = $data['matrixStriped'];
				$idata['border'] = $data['matrixBorder'];
				$idata['hover'] = $data['matrixHover'];
				$idata['small'] = $data['matrixSmall'];
				$idata['disabled'] = $data['matrixDisabled'];
				$idata['required'] = $data['matrixRequired'];

				$idata['questions'] = $data['questions'];
				$idata['headings'] = $data['headings'];
				break;

			case "upload":
				$idata['label'] = $data['uploadLabel'];
				$idata['accept'] = $data['uploadAccept'];
				$idata['labelPosition'] = $data['uploadLabelPosition'];
				$idata['css'] = $data['uploadCss'];
				$idata['parentcss'] = $data['uploadParentCss'];
				$idata['disabled'] = $data['uploadDisabled'];
				$idata['required'] = $data['uploadRequired'];
				break;

			case "captcha":
				$idata['label'] = $data['captchaLabel'];
				$idata['length'] = $data['captchaLength'];
				$idata['characterset'] = $data['captchaCharacterset'];
				$idata['placeholder'] = $data['captchaPlaceholder'];
				$idata['width'] = $data['captchaWidth'];
				$idata['height'] = $data['captchaHeight'];
				$idata['pretext'] = wp_kses($data['captchaPretext'], wp_kses_allowed_html());
				$idata['labelPosition'] = $data['captchaLabelPosition'];
				$idata['imagecss'] = $data['captchaCssImage'];
				$idata['css'] = $data['captchaCss'];
				$idata['innercss'] = $data['captchaInnerCss'];
				$idata['parentcss'] = $data['captchaParentCss'];
				$idata['caseSensitive'] = $data['captchaCaseSensitive'];
				break;

		}

		return $idata;
	}

	/**
	 * HELPER
	 * 
	 * Validates Input Data Array
	 * 
	 * @param type FormField-Type
	 * @param data Array of Formfield Data
	 * 
	 * @return Boolean true/false
	 */
	private function validateInput($type, $data) {

		switch($type) {
			case "input":
			case "textarea":
			case "select":
			case "radio":
			case "checkbox":
			case "slider":
			case "text":
			case "upload":
				// Currently no checks here
				return true;

			case "scale":
				if($data['selectCount'] >= 2 && $data['selectCount'] <= 99) {
					return true;
				} else {
					return false;
				}
				break;
			
			case "matrix":
				if($data['selectCount'] >= 2 && $data['selectCount'] <= 11 && sizeof($data['headings']) == $data['selectCount']) {
					foreach($data['headings'] as $h) {
						if(trim($h['text']) == "" || trim($h['value']) == "") {
							return false;
						}
					}
					foreach($data['questions'] as $q) {
						if(trim($q['question']) == "") {
							return false;
						}
					}
					return true;
				} else {
					return false;
				}
				break;

			case "captcha":
				if(is_numeric($data['length']) && $data['length'] >= 2 && $data['length'] <= 20) {
					return true;
				} else {
					return false;
				}
				break;

			default:
				return false;
		}

	}

	/**
	 * HELPER
	 * 
	 * Checks if a select field with the user add function exists and has formdata so it must be merged
	 * 
	 * @param Array of FormGroup Objects
	 * 
	 * @return boolean true/false
	 */
	private function hasSelectUserAddField(Array $formgroups) {
		foreach($formgroups as $formgroup) {
			foreach($formgroup as $formfield) {
				if($formfield->getType() == "select" && $formfield->getAttributesJsonDecoded()['useradd'] == "1" && $formfield->getFormdata() != null) {
					return true;
				}
			}
		}

		return false;
	}

	/**
	 * HELPER
	 * 
	 * Merges FormData for a select field with all of the user's values
	 * 
	 * @param Array of FormGroup Objects
	 * 
	 * @return Array of Formgroup Objects with merged data
	 */
	private function mergeFormgroupData(Array $formgroups) {

		foreach($formgroups as $formgroup) {
			foreach($formgroup as $formfield) {
				if($formfield->getType() == "select" && $formfield->getAttributesJsonDecoded()['useradd'] == "1" && $formfield->getFormdata() != null) {

					$allformdata = Trainingssystem_Plugin_Database::getInstance()->Formdata->getAllFormfieldData($formfield->getFormdata()->getFieldId(), $formfield->getFormdata()->getUserId(), $formfield->getFormdata()->getFormgroup());

					$customvalues = array();
					foreach($allformdata as $fd) {
						if($fd->dataIsArray()) {
							foreach($fd->getDataJsonDecoded() as $data) {
								$customvalues[] = $data;
							}
						} else {
							$customvalues[] = $fd->getData();
						}
					}
					$customvalues = array_unique($customvalues);

					$todeleteindexes = array();
					$formfield_elements = $formfield->getAttributesJsonDecoded()['elements'];
					foreach($formfield_elements as $el) {
						if(in_array($el['value'], $customvalues)) {
							foreach($customvalues as $ck => $cv) {
								if($el['value'] === $cv) {
									$todeleteindexes[] = $ck;
								}
							}
						}
					}

					foreach($todeleteindexes as $tdi) {
						if(isset($customvalues[$tdi])) {
							unset($customvalues[$tdi]);
						}
					}

					$elements_new = array();
					$i = 0;
					foreach($customvalues as $cv) {
						$elements_new[$i]['text'] = $cv;
						$elements_new[$i]['value'] = $cv;
						$elements_new[$i]['selected'] = ($i == 0) ? true : false;
						$i++;
					}

					foreach($formfield_elements as $ffe) {
						$elements_new[$i]['text'] = $ffe['text'];
						$elements_new[$i]['value'] = $ffe['value'];
						$elements_new[$i]['selected'] = ($i == 0) ? true : false;
						$i++;
					}

					$attr = $formfield->getAttributesJsonDecoded();
					$attr['elements'] = $elements_new;
					$formfield->setAttributes(json_encode($attr));

				}
			}
		}	

		return $formgroups;
	}

	/**
	 * HELPER
	 * 
	 * Checks if a formgroup contains a captcha field
	 * 
	 * @param Array of FormGroup Objects
	 * 
	 * @return boolean true/false
	 */
	private function hasCaptchaField(Array $formgroups) {
		foreach($formgroups as $formgroup) {
			foreach($formgroup as $formfield) {
				if($formfield->getType() == "captcha") {
					return true;
				}
			}
		}

		return false;
	}

	/**
	 * HELPER
	 * 
	 * Creates Captcha-Data inside the Formfield-Element and the Database
	 * Warning: only one captcha per viewable page is allowed, last captcha in ts form wins!
	 * 
	 * @param Int User-ID
	 * @param Array of FormGroup Objects
	 */
	private function injectCaptchaData($userid, Array $formgroups) {
		foreach($formgroups as $formgroup) {
			foreach($formgroup as $formfield) {
				if($formfield->getType() == "captcha") {

					$charset = "";
					if($formfield->getAttributesJsonDecoded()['characterset'] == "all") {
						$charset = "abcdefghijklmnpqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789";
					} elseif($formfield->getAttributesJsonDecoded()['characterset'] == "numeric") {
						$charset = "0123456789";
					} elseif($formfield->getAttributesJsonDecoded()['characterset'] == "chars") {
						$charset = "abcdefghijklmnpqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
					} elseif($formfield->getAttributesJsonDecoded()['characterset'] == "charslower") {
						$charset = "abcdefghijklmnpqrstuvwxyz";
					} elseif($formfield->getAttributesJsonDecoded()['characterset'] == "charsupper") {
						$charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
					}

					$phraseBuilder = Builder::buildPhrase($formfield->getAttributesJsonDecoded()['length'], $charset);
					$captcha = Builder::create($phraseBuilder);
					$captcha->build($formfield->getAttributesJsonDecoded()['width'], $formfield->getAttributesJsonDecoded()['height']);

					$storedData = array();
					$storedData[$formfield->getFormId()] = array($formfield->getFieldId() => $captcha->phrase);

					if(update_user_meta($userid, self::$captchaUserMetaKey, $storedData)) {
						$formfield->setCaptchaData($captcha->inline(90, "jpg"));
					}
				}
			}
		}

		return $formgroups;
	}

	/**
	 * HELPER
	 * 
	 * Checks if a cpatcha exists, verifies its correctness and deletes the user's captcha input 
	 * from the data Array that is later stored in the database
	 * 
	 * @param Int User-ID
	 * @param boolean Usermodus
	 * @param Array Data passed-by-reference
	 * 
	 * @return boolean captcha check error'd: proceed with saving if false, skip saving if true
	 */
	private function validateCaptcha($userid, $usermodus, & $data) {

		$hasCaptcha = false;
		$meta = get_user_meta( $userid, self::$captchaUserMetaKey, true );
		if(is_array($meta) && !empty($meta)) {
			$hasCaptcha = true;
		}

		if($hasCaptcha && !$usermodus) {
			$captchaCorrect = "";
			foreach($meta as $formid => $field) {
				foreach($field as $fieldid => $value) {
					$captchaCorrect = $value;
					break 2;
				}
			}

			$formfield = Trainingssystem_Plugin_Database::getInstance()->Formfield->getFormfield($fieldid);
			
			$captchaBuilder = new Builder;

			if(isset($data[$formid][0][$fieldid]) && 
				(
					((is_null($formfield->getAttributesJsonDecoded()['caseSensitive']) || !$formfield->getAttributesJsonDecoded()['caseSensitive']) && $captchaBuilder->compare($captchaCorrect,  trim($data[$formid][0][$fieldid]))) // case in-sensitive (default)  => use built-in compare function
					||
					($formfield->getAttributesJsonDecoded()['caseSensitive'] && strcmp($captchaCorrect, trim($data[$formid][0][$fieldid])) === 0) // case sensitive => compare raw strings
				)) {

				unset($data[$formid][0][$fieldid]);
				delete_user_meta( $userid, self::$captchaUserMetaKey);
				return false;

			} elseif(!isset($data[$formid][0][$fieldid])) { // captcha on other page
				return false;
			} else {
				return true;
			}
		} elseif($hasCaptcha && $usermodus) {
			foreach($meta as $formid => $field) {
				foreach($field as $fieldid => $value) {
					break 2;
				}
			}
			if(isset($data[$formid][0][$fieldid])) {
				unset($data[$formid][0][$fieldid]);
				delete_user_meta( $userid, self::$captchaUserMetaKey);
			}
			return false;
		}
		return false;
	}
}
