<?php
/**
 * Main plugin coordinator.
 *
 * @package SubmissionInbox
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

// phpcs:disable PluginCheck.CodeAnalysis.DiscouragedFunctions.load_plugin_textdomainFound -- Loading the plugin text domain keeps translations available on older WordPress versions and is harmless on modern WordPress.

/**
 * Coordinates plugin services.
 */
class SUBIN_Plugin {
	/**
	 * Settings repository.
	 *
	 * @var SUBIN_SettingsRepository
	 */
	private $settings;

	/**
	 * SMTP mailer.
	 *
	 * @var \SUBIN\Mailer\SmtpMailer
	 */
	private $smtp_mailer;

	/**
	 * Form submission context.
	 *
	 * @var \SUBIN\Forms\FormSubmissionContext
	 */
	private $form_context;

	/**
	 * Mail logger.
	 *
	 * @var \SUBIN\MailLog\MailLogger
	 */
	private $mail_logger;

	/**
	 * Contact Form 7 integration.
	 *
	 * @var \SUBIN\Forms\ContactForm7Integration
	 */
	private $contact_form_7;

	/**
	 * WPForms integration.
	 *
	 * @var \SUBIN\Forms\WPFormsIntegration
	 */
	private $wpforms;

	/**
	 * Fluent Forms integration.
	 *
	 * @var \SUBIN\Forms\FluentFormsIntegration
	 */
	private $fluent_forms;

	/**
	 * Forminator integration.
	 *
	 * @var \SUBIN\Forms\ForminatorIntegration
	 */
	private $forminator;

	/**
	 * Ninja Forms integration.
	 *
	 * @var \SUBIN\Forms\NinjaFormsIntegration
	 */
	private $ninja_forms;

	/**
	 * Retention service.
	 *
	 * @var \SUBIN\Retention\RetentionService
	 */
	private $retention;

	/**
	 * Built-in form shortcode.
	 *
	 * @var \SUBIN\Forms\FormShortcode
	 */
	private $form_shortcode;

	/**
	 * Built-in form submission handler.
	 *
	 * @var \SUBIN\Forms\FormSubmissionHandler
	 */
	private $form_submission_handler;

	/**
	 * Register hooks.
	 *
	 * @return void
	 */
	public function run() {
		$this->settings     = new SUBIN_SettingsRepository();
		$this->form_context = new \SUBIN\Forms\FormSubmissionContext();

		$lead_repository       = new \SUBIN\Leads\LeadRepository();
		$lead_field_repository = new \SUBIN\Leads\LeadFieldRepository();
		$form_repository       = new \SUBIN\Forms\FormRepository();
		$form_field_repository = new \SUBIN\Forms\FormFieldRepository();
		$mail_event_repository  = new \SUBIN\MailLog\MailEventRepository();
		$sync_event_recorder    = new \SUBIN\Sync\SyncEventRecorder();
		$sync_event_recorder->register();
		$cloud_sync_service     = new \SUBIN\Cloud\CloudSyncService();
		$cloud_sync_service->register();
		$auto_reply_templates  = new \SUBIN\AutoReplies\AutoReplyTemplateRepository();
		$auto_reply_rules      = new \SUBIN\AutoReplies\AutoReplyRuleRepository();
		$auto_reply_rule_sender = new \SUBIN\AutoReplies\AutoReplyRuleSender( $auto_reply_rules, $auto_reply_templates, $mail_event_repository, $this->form_context );

		$this->form_submission_handler = new \SUBIN\Forms\FormSubmissionHandler(
			$this->settings,
			$form_repository,
			$form_field_repository,
			$lead_repository,
			$lead_field_repository,
			$this->form_context,
			new \SUBIN\AutoReplies\AutoReplySender( $auto_reply_templates, $mail_event_repository, $this->form_context, $form_field_repository, $auto_reply_rules ),
			$mail_event_repository,
			new \SUBIN\Forms\RecaptchaVerifier( $this->settings )
		);
		$this->form_submission_handler->register();

		$this->form_shortcode = new \SUBIN\Forms\FormShortcode(
			$form_repository,
			$form_field_repository,
			new \SUBIN\Forms\FormRenderer( $this->settings ),
			$this->form_submission_handler
		);
		$this->form_shortcode->register();

		$this->smtp_mailer = new \SUBIN\Mailer\SmtpMailer( $this->settings );
		$this->smtp_mailer->register();

		$this->mail_logger = new \SUBIN\MailLog\MailLogger(
			$mail_event_repository,
			$lead_repository,
			$this->form_context,
			$this->settings
		);
		$this->mail_logger->register();

		$this->contact_form_7 = new \SUBIN\Forms\ContactForm7Integration(
			$this->settings,
			$lead_repository,
			$lead_field_repository,
			$mail_event_repository,
			$this->form_context,
			$auto_reply_rule_sender
		);
		$this->contact_form_7->register();

		$this->wpforms = new \SUBIN\Forms\WPFormsIntegration(
			$this->settings,
			$lead_repository,
			$lead_field_repository,
			$mail_event_repository,
			$this->form_context,
			$auto_reply_rule_sender
		);
		$this->wpforms->register();

		$this->fluent_forms = new \SUBIN\Forms\FluentFormsIntegration(
			$this->settings,
			$lead_repository,
			$lead_field_repository,
			$mail_event_repository,
			$this->form_context,
			$auto_reply_rule_sender
		);
		$this->fluent_forms->register();

		$this->forminator = new \SUBIN\Forms\ForminatorIntegration(
			$this->settings,
			$lead_repository,
			$lead_field_repository,
			$mail_event_repository,
			$this->form_context,
			$auto_reply_rule_sender
		);
		$this->forminator->register();

		$this->ninja_forms = new \SUBIN\Forms\NinjaFormsIntegration(
			$this->settings,
			$lead_repository,
			$lead_field_repository,
			$mail_event_repository,
			$this->form_context,
			$auto_reply_rule_sender
		);
		$this->ninja_forms->register();

		$this->retention = new \SUBIN\Retention\RetentionService(
			$this->settings,
			$lead_repository,
			$lead_field_repository,
			$mail_event_repository
		);
		$this->retention->register();

		add_action( 'init', array( $this, 'load_textdomain' ) );
		add_action( 'admin_init', array( $this, 'maybe_upgrade_database' ) );

		if ( is_admin() ) {
			$forms_ajax_page = new SUBIN_FormsPage();
			add_action( 'wp_ajax_subin_save_grapesjs_project', array( $forms_ajax_page, 'ajax_save_grapesjs_project' ) );
			add_action( 'wp_ajax_subin_upload_design_studio_media', array( $forms_ajax_page, 'ajax_upload_design_studio_media' ) );

			$admin_menu = new SUBIN_AdminMenu( $this->settings, $this->form_context );
			$admin_menu->register();
		}
	}

	/**
	 * Load translations.
	 *
	 * @return void
	 */
	public function load_textdomain() {
		load_plugin_textdomain(
			SUBIN_PLUGIN_TEXT_DOMAIN,
			false,
			dirname( plugin_basename( SUBIN_PLUGIN_FILE ) ) . '/languages'
		);
	}

	/**
	 * Upgrade database schema only when the stored version is behind.
	 *
	 * @return void
	 */
	public function maybe_upgrade_database() {
		SUBIN_Database::maybe_upgrade();
	}
}
