<?php

class HappyForms_Part_Attachment extends HappyForms_Form_Part {

	private $controller;

	public $type = 'attachment';

	public function __construct() {
		$this->label = __( 'File Upload', 'happyforms' );
		$this->description = __( 'For allowing file uploads with easy drag and drop zone.', 'happyforms' );
		$this->controller = happyforms_get_attachment_controller();

		add_filter( 'happyforms_part_class', array( $this, 'html_part_class' ), 10, 3 );
		add_filter( 'happyforms_part_data_attributes', array( $this, 'html_part_data_attributes' ), 10, 3 );
		add_filter( 'happyforms_frontend_dependencies', array( $this, 'script_dependencies' ), 10, 2 );
		add_filter( 'happyforms_style_dependencies', array( $this, 'style_dependencies' ), 10, 2 );
		add_filter( 'happyforms_stringify_part_value', array( $this, 'stringify_value' ), 10, 3 );
		add_filter( 'happyforms_message_part_value', array( $this, 'message_part_value' ), 10, 4 );
		add_filter( 'happyforms_email_part_value', array( $this, 'email_part_value' ), 10, 5 );
		add_filter( 'happyforms_frontend_settings', array( $this, 'attachment_settings' ), 10, 1 );
	}

	/**
	 * Get all part meta fields defaults.
	 *
	 * @since 1.0.0.
	 *
	 * @return array
	 */
	public function get_customize_fields() {
		$fields = array(
			'type' => array(
				'default' => $this->type,
				'sanitize' => 'sanitize_text_field',
			),
			'label' => array(
				'default' => __( '', 'happyforms' ),
				'sanitize' => 'sanitize_text_field',
			),
			'label_placement' => array(
				'default' => '',
				'sanitize' => 'sanitize_text_field'
			),
			'description' => array(
				'default' => '',
				'sanitize' => 'sanitize_text_field'
			),
			'description_mode' => array(
				'default' => '',
				'sanitize' => 'sanitize_text_field'
			),
			'width' => array(
				'default' => 'full',
				'sanitize' => 'sanitize_key'
			),
			'css_class' => array(
				'default' => '',
				'sanitize' => 'sanitize_text_field'
			),
			'placeholder' => array(
				'default' => __( 'Choose file', 'happyforms' ),
				'sanitize' => 'sanitize_text_field',
			),
			'allowed_file_types' => array(
				'default' => '',
				'sanitize' => array(
					'happyforms_sanitize_choice',
					array( '', 'documents', 'archives', 'images', 'media', 'custom' ),
				),
			),
			'allowed_file_extensions' => array(
				'default' => '',
				'sanitize' => array(
					'happyforms_sanitize_list',
					happyforms_get_file_types(),
				),
			),
			'max_file_size' => array(
				'default' => 2,
				'sanitize' => 'happyforms_sanitize_float'
			),
			'use_max_file_count' => array(
				'default' => 0,
				'sanitize' => 'happyforms_sanitize_checkbox',
			),
			'max_file_count' => array(
				'default' => 0,
				'sanitize' => 'intval'
			),
			'required' => array(
				'default' => 1,
				'sanitize' => 'happyforms_sanitize_checkbox',
			)
		);

		return happyforms_get_part_customize_fields( $fields, $this->type );
	}

	/**
	 * Get template for part item in customize pane.
	 *
	 * @since 1.0.0.
	 *
	 * @return string
	 */
	public function customize_templates() {
		$template_path = happyforms_get_include_folder() . '/templates/parts/customize-attachment.php';
		$template_path = happyforms_get_part_customize_template_path( $template_path, $this->type );

		require_once( $template_path );
	}

	/**
	 * Get front end part template with parsed data.
	 *
	 * @since 1.0.0.
	 *
	 * @param array $part_data  Form part data.
	 * @param array $form_data  Form (post) data.
	 *
	 * @return string   Markup for the form part.
	 */
	public function frontend_template( $part_data = array(), $form_data = array() ) {
		$part = wp_parse_args( $part_data, $this->get_customize_defaults() );
		$form = $form_data;

		include( happyforms_get_include_folder() . '/templates/parts/frontend-attachment.php' );
	}

	public function get_default_value( $part_data = array() ) {
		return array();
	}

	/**
	 * Sanitize submitted value before storing it.
	 *
	 * @since 1.0.0.
	 *
	 * @param array $part_data Form part data.
	 *
	 * @return string
	 */
	public function sanitize_value( $part_data = array(), $form_data = array(), $request = array() ) {
		$sanitized_value = $this->get_default_value( $part_data );
		$part_name = happyforms_get_part_name( $part_data, $form_data );

		$default_file_value = array(
			'id' => '',
			'name' => '',
			'size' => '',
		);

		if ( isset( $request[$part_name] ) ) {
			if ( ! is_array( $request[$part_name] ) ) {
				$request[$part_name] = array();
			}

			foreach( $request[$part_name] as $f => $file ) {
				if ( ! is_array( $file ) ) {
					$file = array();
				}

				$file = wp_parse_args( $file, $default_file_value );

				foreach ( $file as $field => $value ) {
					$file[$field] = sanitize_text_field( $value );
				}

				$sanitized_value[$f] = $file;
			}
		}

		return $sanitized_value;
	}

	/**
	 * Validate value before submitting it. If it fails validation, return WP_Error object, showing respective error message.
	 *
	 * @since 1.0.0.
	 *
	 * @param array $part Form part data.
	 * @param string $value Submitted value.
	 *
	 * @return string|object
	 */
	public function validate_value( $value, $part = array(), $form = array() ) {
		$validated_value = $value;
		$file_ids = wp_list_pluck( $validated_value, 'id' );
		$file_ids = array_filter( $file_ids );

		// Check if not empty
		if ( 1 === $part['required'] ) {
			if ( empty( $file_ids ) ) {
				return new WP_Error( 'error', happyforms_get_validation_message( 'file_not_uploaded' ) );
			}
		}

		$part_id = $part['id'];
		$attachments = $this->controller->get( array(
			'hash_id' => $file_ids,
			'part_id' => $part_id
		) );

		$attachments = array_filter( $attachments, function( $attachment ) use( $file_ids ) {
			return in_array( $attachment['hash_id'], $file_ids );
		} );

		// Check if valid
		if ( ! empty( $file_ids[0] ) && count( $attachments ) !== count( $file_ids ) ) {
			return new WP_Error( 'error', happyforms_get_validation_message( 'file_invalid' ) );
		}

		// Check count limit
		if ( ( $part['max_file_count'] > 0 ) && ( count( $attachments ) > $part['max_file_count'] ) ) {
			return new WP_Error( 'error', happyforms_get_validation_message( 'file_count_exceeded' ) );
		}

		return $validated_value;
	}

	public function html_part_class( $class, $part, $form ) {
		if ( $this->type === $part['type'] ) {
			if ( happyforms_get_part_value( $part, $form ) ) {
				$class[] = 'happyforms-part--filled';
			}
		}

		return $class;
	}

	public function html_part_data_attributes( $attributes, $part, $form ) {
		if ( $this->type === $part['type'] ) {
			$attributes['happyforms-part-id'] = $part['id'];
			$attributes['happyforms-max-file-size'] = $part['max_file_size'];
			$attributes['happyforms-max-file-count'] = $part['max_file_count'];
			$attributes['happyforms-allowed-file-types'] = $part['allowed_file_types'];
			$attributes['happyforms-allowed-file-extensions'] = $part['allowed_file_extensions'];
		}

		return $attributes;
	}

	public function stringify_value( $value, $part, $form ) {
		if ( $this->type === $part['type'] ) {
			$value = wp_list_pluck( $value, 'id' );
		}

		return $value;
	}

	public function message_part_value( $value, $original_value, $part, $destination ) {
		if ( isset( $part['type'] )
			&& $this->type === $part['type'] ) {

			$hash_ids = maybe_unserialize( $original_value );
			$hash_ids = array_filter( array_values( $hash_ids ) );

			if ( ! empty( $hash_ids ) ) {
				if ( 'email' === $destination ) {
					$value = sprintf( __( '%d attachments', 'happyforms' ), count( $hash_ids ) );
				} else if ( 'csv' === $destination ) {
					$attachments = $this->controller->get( array(
						'hash_id' => $hash_ids,
					) );

					$attachment_ids = wp_list_pluck( $attachments, 'ID' );
					$links = array_map( 'wp_get_attachment_url', $attachment_ids );
					$value = implode( ', ', $links );
				} else {
					$attachments = $this->controller->get( array(
						'hash_id' => $hash_ids,
					) );

					$links = array();

					foreach ( $attachments as $attachment ) {
						$attachment_id = $attachment['ID'];
						$title = $attachment['post_title'];
						$url = wp_get_attachment_url( $attachment_id );
						$file = get_attached_file( $attachment_id );
						$html_link_string = '';
						$file_size = '';
						
						if ( file_exists( $file ) ) {
							$file_size = size_format( filesize( $file ), 2 );
							$file_size = " ({$file_size})";
							$file_extension = wp_check_filetype( $file );
							$title .= '.' . $file_extension['ext'];
						}

						$links[] = "<a href=\"{$url}\" target=\"_blank\" download>{$title}</a>{$file_size}";
					}

					$deleted_attachments = happyforms_get_meta( get_the_ID(), 'deleted_attachments', true );
					$deleted_attachments = $deleted_attachments ? $deleted_attachments : array();

					foreach ( $deleted_attachments as $attachment ) {
						$file_name = $attachment['file_name'];
						$file_extension = $attachment['file_extension'];
						$file_size = $attachment['file_size'];
						$links[] = "<span class=\"happyforms-deleted-attachment\">{$file_name}.{$file_extension} ({$file_size})</span>";
					}

					$value = implode( ', ', $links );
				}
			}
		}

		return $value;
	}

	public function email_part_value( $value, $message, $part, $form, $context ) {
		if ( 'admin-email' !== $context ) {
			return $value;
		}

		if ( happyforms_is_falsy( $form['alert_email_attachment_links'] ) ) {
			return $value;
		}

		$parts = $message['parts'];
		$part_id = $part['id'];
		$value = happyforms_get_message_part_value( $parts[$part_id], $part, '' );

		return $value;
	}

	/**
	 * Enqueue scripts in customizer area.
	 *
	 * @since 1.0.0.
	 *
	 * @param array List of dependencies.
	 *
	 * @return void
	 */
	public function customize_enqueue_scripts( $deps = array() ) {
		wp_enqueue_script(
			'part-attachment',
			happyforms_get_plugin_url() . 'inc/assets/js/parts/part-attachment.js',
			$deps, HAPPYFORMS_UPGRADE_VERSION, true
		);
	}

	public function script_dependencies( $deps, $forms ) {
		$contains_attachment = false;
		$form_controller = happyforms_get_form_controller();

		foreach ( $forms as $form ) {
			if ( $form_controller->get_first_part_by_type( $form, $this->type ) ) {
				$contains_attachment = true;
				break;
			}
		}

		if ( ! happyforms_is_preview() && ! $contains_attachment ) {
			return $deps;
		}

		wp_register_script(
			'happyforms-attachment',
			happyforms_get_plugin_url() . 'inc/assets/js/frontend/attachment.js',
			array( 'plupload' ), HAPPYFORMS_UPGRADE_VERSION, true
		);

		/*
		$settings = array(
			'ajaxUrl' => admin_url( 'admin-ajax.php' ),
			'mimeGroups' => happyforms_get_file_mime_groups(),
		);

		wp_localize_script(
			'happyforms-attachment',
			'_happyFormsAttachmentSettings',
			$settings
		);
		*/

		$deps[] = 'happyforms-attachment';

		return $deps;
	}

	public function attachment_settings( $data ) {
		$data['mimeGroups'] = happyforms_get_file_mime_groups();

		return $data;
	}

	public function style_dependencies( $deps, $forms ) {
		$contains_attachment = false;
		$form_controller = happyforms_get_form_controller();

		foreach ( $forms as $form ) {
			if ( $form_controller->get_first_part_by_type( $form, $this->type ) ) {
				$contains_attachment = true;
				break;
			}
		}

		if ( ! happyforms_is_preview() && ! $contains_attachment ) {
			return $deps;
		}

		wp_register_style(
			'happyforms-attachment',
			happyforms_get_plugin_url() . 'inc/assets/css/frontend/attachment.css',
			array(), HAPPYFORMS_VERSION
		);

		$deps[] = 'happyforms-attachment';

		return $deps;
	}

}
