<?php
declare( strict_types=1 );

namespace FiboFilters\DI;

use FiboFilters\AdminPages\Pages\Debug as DebugPage;
use FiboFilters\AdminPages\Pages\Settings as SettingsPage;
use FiboFilters\API\API;
use FiboFilters\API\Filters as APIFilters;
use FiboFilters\API\Index as APIIndex;
use FiboFilters\API\SEORules as APISEORules;
use FiboFilters\API\Settings as APISettings;
use FiboFilters\API\SettingsController as APISettingsController;
use FiboFilters\API\Troubleshooting as APITroubleshooting;
use FiboFilters\Blocks\Blocks;
use FiboFilters\Blocks\Filters as FiltersBlock;
use FiboFilters\Config\AdminAssetsLoader;
use FiboFilters\Config\AdminBar;
use FiboFilters\Config\AssetsLoader;
use FiboFilters\Config\FreemiusConfig;
use FiboFilters\Config\Index;
use FiboFilters\Config\IndexPusher;
use FiboFilters\Config\Initializer;
use FiboFilters\Config\Install;
use FiboFilters\Config\Menu;
use FiboFilters\Config\Requirements;
use FiboFilters\Config\Troubleshooting;
use FiboFilters\Config\WpCli;
use FiboFilters\Filtering\Front;
use FiboFilters\Filtering\Request;
use FiboFilters\Filtering\VariationAdjuster;
use FiboFilters\Filters\FilterFactory;
use FiboFilters\Filters\FiltersDebugger;
use FiboFilters\Filters\FiltersManager;
use FiboFilters\Filters\FilterSources;
use FiboFilters\Filters\FiltersQuery;
use FiboFilters\Filters\SourceAnalyser;
use FiboFilters\Filters\StoreFilters;
use FiboFilters\Index\Descriptors;
use FiboFilters\Index\Documents;
use FiboFilters\Index\Sources;
use FiboFilters\Index\Values;
use FiboFilters\Indexer\AsyncRebuildIndex;
use FiboFilters\Indexer\BackgroundProductUpdater;
use FiboFilters\Indexer\Builder;
use FiboFilters\Indexer\BuilderUI;
use FiboFilters\Indexer\BuildInfo;
use FiboFilters\Indexer\Config;
use FiboFilters\Indexer\DescriptorsCache;
use FiboFilters\Indexer\DocumentFactory;
use FiboFilters\Indexer\Filters\AsyncProcess;
use FiboFilters\Indexer\Filters\Database as DatabaseFilters;
use FiboFilters\Indexer\Filters\Indexer as IndexerFilters;
use FiboFilters\Indexer\Logger;
use FiboFilters\Indexer\Scheduler;
use FiboFilters\Indexer\SourceQueryFactory;
use FiboFilters\Indexer\Updater;
use FiboFilters\Integrations\BulkIntegrations;
use FiboFilters\Integrations\Multilingual;
use FiboFilters\Integrations\Multilingual\Polylang;
use FiboFilters\Integrations\Multilingual\TranslatePress;
use FiboFilters\Integrations\Multilingual\WPML;
use FiboFilters\Integrations\Plugins;
use FiboFilters\Integrations\Themes;
use FiboFilters\Product\ProductFactory;
use FiboFilters\SeoRules\SeoRuleMatcher;
use FiboFilters\SeoRules\SeoRuleUrlResolver;
use FiboFilters\SeoRules\SeoRuleEngine;
use FiboFilters\SeoRules\SeoRuleProductEstimator;
use FiboFilters\SeoRules\SeoRuleRepository;
use FiboFilters\SeoRules\SeoRuleUrlGenerator;
use FiboFilters\Settings\Onboarding;
use FiboFilters\Settings\Settings;
use FiboFilters\Settings\Storage;
use FiboFilters\Shortcodes\FiboFilters as FiboFiltersShortcode;
use FiboFilters\Shortcodes\FiboFiltersAppliedFilters as FiboFiltersAppliedFiltersShortcode;
use FiboFilters\Shortcodes\FiboFiltersInfiniteScrollTrigger as FiboFiltersInfiniteScrollTriggerShortcode;
use FiboFilters\Shortcodes\FiboFiltersOrdering as FiboFiltersOrderingShortcode;
use FiboFilters\Shortcodes\FiboFiltersPagination as FiboFiltersPaginationShortcode;
use FiboFilters\Shortcodes\FiboFiltersShowMoreProductsBtn as FiboFiltersShowMoreProductsBtnShortcode;
use FiboFilters\Shortcodes\FiboFiltersShowPreviousProductsBtn as FiboFiltersShowPreviousProductsBtnShortcode;
use FiboFilters\Sorting\CustomSortOptionsProvider;
use FiboFilters\Sorting\Sorting;
use FiboFilters\Util\Cache;
use FiboFilters\Util\DbUtil;
use FiboFilters\Util\Localization;
use FiboFilters\Widgets\Widgets;
use FiboFilters\WooCommerce\Helper as WooCommerceHelper;
use FiboFilters\WP\Helper as WPHelper;
use FiboFilters\WP\WPDB;
use FiboFilters\WP\WPDBSecond;
use FiboFilters\WpCli\FibofiltersIndexCommand;
use FiboFiltersVendor\Psr\Container\ContainerInterface;
use FiboFiltersVendor\Symfony\Component\DependencyInjection\ContainerBuilder;
use FiboFiltersVendor\Symfony\Component\DependencyInjection\Reference;
use Freemius;

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

/**
 * Class ContainerConfigurator
 */
class ContainerConfigurator implements IContainerConfigurator {

	public function get_dump_namespace(): string {
		return 'FiboFiltersGenerated';
	}

	public function get_dump_class_name(): string {
		return 'FreeCachedContainer';
	}

	/**
	 * @param ContainerBuilder $container Container.
	 */
	public function configure( ContainerBuilder $container ): ContainerBuilder {
		$container->register( 'dich' )->setSynthetic( true )->setPublic( true );

		$container->register( Freemius::class, Freemius::class )
			->setPublic( true )
			->setFactory(
				[
					self::class,
					'get_freemius_service',
				]
			);

		// Pro plugin services factory.
		$container->register( IContainerConfigurator::PRO_CONTAINER_SERVICE_SLUG )
			->setSynthetic( true )
			->setPublic( true );
		// Container wrapper service.
		$container->register( ContainerWrapper::class )
			->setPublic( true )
			->setFactory(
				[
					ContainerWrapper::class,
					'get_instance',
				]
			);

		// API.
		$container->autowire( API::class )->setPublic( true );
		$container->setAlias( 'api.api', API::class )->setPublic( true );
		$container->autowire( APIFilters::class )->setPublic( true );
		$container->autowire( APIIndex::class )->setPublic( true );
		$container->autowire( APISettings::class )->setPublic( true );
		$container->autowire( APISettingsController::class )->setPublic( true );
		$container->autowire( APITroubleshooting::class )->setPublic( true );
		$container->autowire( APISEORules::class )->setPublic( true );

		// Blocks.
		$container->autowire( Blocks::class )->setPublic( true );
		$container->autowire( FiltersBlock::class )->setPublic( true );

		// Widgets.
		$container->autowire( Widgets::class )->setPublic( true );

		// Shortcodes.
		$container->autowire( FiboFiltersShortcode::class )->setPublic( true );
		$container->autowire( FiboFiltersAppliedFiltersShortcode::class )->setPublic( true );
		$container->autowire( FiboFiltersShowMoreProductsBtnShortcode::class )->setPublic( true );
		$container->autowire( FiboFiltersShowPreviousProductsBtnShortcode::class )->setPublic( true );
		$container->autowire( FiboFiltersInfiniteScrollTriggerShortcode::class )->setPublic( true );
		$container->autowire( FiboFiltersOrderingShortcode::class )->setPublic( true );
		$container->autowire( FiboFiltersPaginationShortcode::class )->setPublic( true );

		// Sorting.
		$container->autowire( CustomSortOptionsProvider::class )->setPublic( true );
		$container->autowire( Sorting::class )->setPublic( true );

		// Config.
		$container->autowire( AdminAssetsLoader::class )->setPublic( true );
		$container->setAlias( 'config.admin_assets_loader', AdminAssetsLoader::class )->setPublic( true );
		$container->autowire( AssetsLoader::class )->setPublic( true );
		$container->setAlias( 'config.assets_loader', AssetsLoader::class )->setPublic( true );
		$container->autowire( FreemiusConfig::class )->setPublic( true );
		$container->autowire( IndexPusher::class )->setPublic( true );
		$container->autowire( Initializer::class )->setPublic( true );
		$container->autowire( Install::class )->setPublic( true );
		$container->setAlias( 'config.install', Install::class )->setPublic( true );
		$container->autowire( AdminBar::class )->setPublic( true );
		$container->setAlias( 'config.admin_bar', AdminBar::class )->setPublic( true );
		$container->autowire( Menu::class )->setPublic( true );
		$container->setAlias( 'config.menu', Menu::class )->setPublic( true );
		$container->autowire( Request::class )->setPublic( true );
		$container->autowire( VariationAdjuster::class )->setPublic( true );
		$container->autowire( Requirements::class )->setPublic( true );
		$container->autowire( Troubleshooting::class )->setPublic( true );
		$container->autowire( WpCli::class )->setPublic( true );
		$container->setAlias( 'config.wpcli', WpCli::class )->setPublic( true );

		// Filters.
		$container->autowire( FiltersManager::class )->setPublic( true );
		$container->autowire( FilterFactory::class )->setPublic( true );
		$container->autowire( FiltersDebugger::class )->setPublic( true );
		$container->autowire( FiltersQuery::class )->setPublic( true );
		$container->autowire( FilterSources::class )->setPublic( true );
		$container->autowire( SourceAnalyser::class )->setPublic( true );
		$container->autowire( StoreFilters::class )->setPublic( true );

		// Integrations.
		$container->autowire( Multilingual::class )->setPublic( true );
		$container->autowire( Polylang::class )->setPublic( true );
		$container->autowire( TranslatePress::class )->setPublic( true );
		$container->autowire( WPML::class )->setPublic( true );
		$container->autowire( Plugins::class )->setPublic( true );
		$container->autowire( Plugins\AdvancedCustomFields::class )->setPublic( true );
		$container->setAlias( 'plugins.advanced_custom_fields', Plugins\AdvancedCustomFields::class )->setPublic( true );
		$container->autowire( Plugins\Breakdance\Breakdance::class )->setPublic( true );
		$container->setAlias( 'plugins.breakdance', Plugins\Breakdance\Breakdance::class )->setPublic( true );
		$container->autowire( Plugins\Elementor\Elementor::class )->setPublic( true );
		$container->setAlias( 'plugins.elementor', Plugins\Elementor\Elementor::class )->setPublic( true );
		$container->autowire( Plugins\Elementor\Utils::class )->setPublic( true );
		$container->autowire( Plugins\FlyingPress::class )->setPublic( true );
		$container->setAlias( 'plugins.flying_press', Plugins\FlyingPress::class )->setPublic( true );
		$container->autowire( Plugins\HideCategoriesProductsWooCommerce::class )->setPublic( true );
		$container->setAlias( 'plugins.hide_categories_products_wc', Plugins\HideCategoriesProductsWooCommerce::class )->setPublic( true );
		$container->autowire( Plugins\IconicWooImageSwap::class )->setPublic( true );
		$container->setAlias( 'plugins.iconic_woo_image_swap', Plugins\IconicWooImageSwap::class )->setPublic( true );
		$container->autowire( Plugins\JVMWooCommerceWishlist::class )->setPublic( true );
		$container->setAlias( 'plugins.jvm_woocommerce_wishlist', Plugins\JVMWooCommerceWishlist::class )->setPublic( true );
		$container->autowire( Plugins\LiteSpeedCache::class )->setPublic( true );
		$container->setAlias( 'plugins.litespeed_cache', Plugins\LiteSpeedCache::class )->setPublic( true );
		$container->autowire( Plugins\KinstaMUPlugins::class )->setPublic( true );
		$container->setAlias( 'plugins.kinsta_mu_plugins', Plugins\KinstaMUPlugins::class )->setPublic( true );
		$container->autowire( Plugins\VariationSwatchesForWooCommercePro::class )->setPublic( true );
		$container->setAlias( 'plugins.variation_swatches_for_woocommerce_pro', Plugins\VariationSwatchesForWooCommercePro::class )->setPublic( true );
		$container->autowire( Plugins\Perfmatters::class )->setPublic( true );
		$container->setAlias( 'plugins.perfmatters', Plugins\Perfmatters::class )->setPublic( true );
		$container->autowire( Plugins\PixelManagerProForWooCommerce::class )->setPublic( true );
		$container->setAlias( 'plugins.pixel_manager_pro_for_woocommerce', Plugins\PixelManagerProForWooCommerce::class )->setPublic( true );
		$container->autowire( Plugins\WPRocket::class )->setPublic( true );
		$container->setAlias( 'plugins.wp_rocket', Plugins\WPRocket::class )->setPublic( true );
		$container->autowire( Plugins\WooCommerce\WooCommerce::class )->setPublic( true );
		$container->setAlias( 'plugins.woocommerce', Plugins\WooCommerce\WooCommerce::class )->setPublic( true );
		$container->autowire( Plugins\WooCompositeProducts::class )->setPublic( true );
		$container->setAlias( 'plugins.woo_composite_products', Plugins\WooCompositeProducts::class )->setPublic( true );
		$container->autowire( Plugins\YITHWooCommerceWishlist::class )->setPublic( true );
		$container->setAlias( 'plugins.yith_woocommerce_wishlist', Plugins\YITHWooCommerceWishlist::class )->setPublic( true );
		$container->autowire( Plugins\PwWooCommerceGiftCards::class )->setPublic( true );
		$container->setAlias( 'plugins.pw_woocommerce_gift_cards', Plugins\PwWooCommerceGiftCards::class )->setPublic( true );
		$container->autowire( Plugins\AeliaCurrencySwitcherForWooCommerce::class )->setPublic( true );
		$container->setAlias( 'plugins.woocommerce_aelia_currencyswitcher', Plugins\AeliaCurrencySwitcherForWooCommerce::class )->setPublic( true );
		$container->autowire( Plugins\Imagify::class )->setPublic( true );
		$container->setAlias( 'plugins.imagify', Plugins\Imagify::class )->setPublic( true );
		$container->autowire( Plugins\EssentialAddonsForElementor::class )->setPublic( true );
		$container->setAlias( 'plugins.essential_addons_for_elementor', Plugins\EssentialAddonsForElementor::class )->setPublic( true );
		$container->autowire( Plugins\ProductVariationSwatchesforWooCommerce::class )->setPublic( true );
		$container->setAlias( 'plugins.product_variation_swatches_for_woocommerce', Plugins\ProductVariationSwatchesforWooCommerce::class )->setPublic( true );
		$container->autowire( Plugins\Breeze::class )->setPublic( true );
		$container->setAlias( 'plugins.breeze', Plugins\Breeze::class )->setPublic( true );
		$container->autowire( Plugins\Relevanssi::class )->setPublic( true );
		$container->setAlias( 'plugins.relevanssi', Plugins\Relevanssi::class )->setPublic( true );
		$container->autowire( Plugins\WpAllImport::class )->setPublic( true );
		$container->setAlias( 'plugins.wp_all_import', Plugins\WpAllImport::class )->setPublic( true );
		$container->autowire( Plugins\FiboSearchPro::class )->setPublic( true );
		$container->setAlias( 'plugins.fibosearch_pro', Plugins\FiboSearchPro::class )->setPublic( true );
		$container->autowire( Plugins\WpcProductBundlesForWooCommerce::class )->setPublic( true );
		$container->setAlias( 'plugins.wpc_product_bundles_for_wooCommerce', Plugins\WpcProductBundlesForWooCommerce::class )->setPublic( true );

		$container->autowire( BulkIntegrations::class )->setPublic( true );

		// Theme Integrations.
		$container->autowire( Themes::class )->setPublic( true );
		$container->autowire( Themes\GenericTheme::class )->setPublic( true );
		$container->setAlias( 'themes.generic_theme', Themes\GenericTheme::class )->setPublic( true );

		// Astra theme.
		$container->autowire( Themes\Astra::class )->setPublic( true );
		$container->setAlias( 'themes.astra', Themes\Astra::class )->setPublic( true );

		// Botiga theme.
		$container->autowire( Themes\Botiga::class )->setPublic( true );
		$container->setAlias( 'themes.botiga', Themes\Botiga::class )->setPublic( true );

		// Bricks theme.
		$container->autowire( Themes\Bricks::class )->setPublic( true );
		$container->setAlias( 'themes.bricks', Themes\Bricks::class )->setPublic( true );

		// Divi theme.
		$container->autowire( Themes\Divi::class )->setPublic( true );
		$container->setAlias( 'themes.divi', Themes\Divi::class )->setPublic( true );

		// Kadence theme.
		$container->autowire( Themes\Kadence::class )->setPublic( true );
		$container->setAlias( 'themes.kadence', Themes\Kadence::class )->setPublic( true );

		// Avada theme.
		$container->autowire( Themes\Avada::class )->setPublic( true );
		$container->setAlias( 'themes.avada', Themes\Avada::class )->setPublic( true );

		// WoodMart theme.
		$container->autowire( Themes\WoodMart::class )->setPublic( true );
		$container->setAlias( 'themes.woodmart', Themes\WoodMart::class )->setPublic( true );

		// Electro theme.
		$container->autowire( Themes\Electro::class )->setPublic( true );
		$container->setAlias( 'themes.electro', Themes\Electro::class )->setPublic( true );

		// GeneratePress theme.
		$container->autowire( Themes\GeneratePress::class )->setPublic( true );
		$container->setAlias( 'themes.generatepress', Themes\GeneratePress::class )->setPublic( true );

		// XStore theme.
		$container->autowire( Themes\XStore::class )->setPublic( true );
		$container->setAlias( 'themes.xstore', Themes\XStore::class )->setPublic( true );

		// Neve theme.
		$container->autowire( Themes\Neve::class )->setPublic( true );
		$container->setAlias( 'themes.neve', Themes\Neve::class )->setPublic( true );

		// The7 theme.
		$container->autowire( Themes\The7::class )->setPublic( true );
		$container->setAlias( 'themes.the7', Themes\The7::class )->setPublic( true );
		$container->setAlias( 'themes.dt-the7', Themes\The7::class )->setPublic( true );

		// Uncode theme.
		$container->autowire( Themes\Uncode::class )->setPublic( true );
		$container->setAlias( 'themes.uncode', Themes\Uncode::class )->setPublic( true );

		// Porto theme.
		$container->autowire( Themes\Porto::class )->setPublic( true );
		$container->setAlias( 'themes.porto', Themes\Porto::class )->setPublic( true );

		// Product.
		$container->autowire( ProductFactory::class )->setPublic( true );

		// Settings.
		$container->autowire( Settings::class )->setPublic( true );
		$container->autowire( Onboarding::class )->setPublic( true );
		$container->autowire( Storage::class )->setPublic( true );

		// Admin Pages.
		$container->autowire( DebugPage::class )->setPublic( true );
		$container->autowire( SettingsPage::class )->setPublic( true );

		// Indexer.
		$container->autowire( Index::class )->setPublic( true );
		$container->autowire( AsyncRebuildIndex::class )->setPublic( true );
		$container->autowire( AsyncProcess::class )->setPublic( true );
		$container->autowire( BackgroundProductUpdater::class )->setPublic( true );
		$container->autowire( Builder::class )->setPublic( true );
		$container->autowire( BuilderUI::class )->setPublic( true );
		$container->autowire( BuildInfo::class )->setPublic( true );
		$container->autowire( Config::class )->setPublic( true );
		$container->autowire( DescriptorsCache::class )->setPublic( true );
		$container->autowire( DocumentFactory::class )->setPublic( true );
		$container->autowire( Logger::class )->setPublic( true );
		$container->autowire( DatabaseFilters::class )->setPublic( true );
		$container->autowire( IndexerFilters::class )->setPublic( true );
		$container->autowire( IndexerFilters::class )->setPublic( true );
		$container->autowire( Scheduler::class )->setPublic( true );
		$container->autowire( SourceQueryFactory::class )->setPublic( true );
		$container->autowire( Updater::class )->setPublic( true );

		// Index.
		$container->autowire( Descriptors::class )->setPublic( true );
		$container->autowire( Values::class )->setPublic( true );
		$container->autowire( Sources::class )->setPublic( true );
		$container->autowire( Documents::class )->setPublic( true );

		// Seo Rules.
		$container->autowire( SeoRuleRepository::class )->setPublic( true );
		$container->autowire( SeoRuleUrlResolver::class )->setPublic( true );
		$container->autowire( SeoRuleUrlGenerator::class )->setPublic( true );
		$container->autowire( SeoRuleProductEstimator::class )->setPublic( true );
		$container->autowire( SeoRuleEngine::class )->setPublic( true );
		$container->autowire( SeoRuleMatcher::class )->setPublic( true );

		// Util.
		$container->autowire( DbUtil::class )->setPublic( true );
		$container->autowire( Front::class )->setPublic( true );
		$container->setAlias( 'filtering.front', Front::class )->setPublic( true );
		$container->autowire( Cache::class )->setPublic( true );
		$container->autowire( Localization::class )->setPublic( true );

		// WooCommerce.
		$container->autowire( WooCommerceHelper::class )->setPublic( true );

		// WordPress.
		$container->autowire( WPHelper::class )->setPublic( true );
		$container->autowire( WPDB::class )->setPublic( true );
		$container->autowire( WPDBSecond::class )->setPublic( true );

		// WP-CLI.
		$container->autowire( FibofiltersIndexCommand::class )->setPublic( true );

		return $container;
	}

	public static function get_freemius_service(): Freemius {
		// TODO Add auto deactivation of the free version: https://dashboard.freemius.com/#!/live/plugins/8912/integration/.
		// phpcs:ignore ImportDetection.Imports.RequireImports.Symbol
		return fs_dynamic_init(
			[
				'id'              => '12025',
				'slug'            => 'fibofilters',
				'premium_slug'    => 'fibofilters-pro',
				'type'            => 'plugin',
				'public_key'      => 'pk_fa5f47bd89e5e70e508b35349eb20',
				'is_premium'      => true,
				'is_premium_only' => true,
				'has_addons'      => false,
				'has_paid_plans'  => true,
				'menu'            => [
					'slug'       => Menu::MAIN_PAGE_SLUG,
					'parent'     => [
						'slug' => 'woocommerce',
					],
					'first-path' => 'admin.php?page=fibofilters',
					'account'    => false,
					'contact'    => false,
					'support'    => false,
					'pricing'    => false,
				],
			]
		);
	}

	/**
	 * @param ContainerBuilder $container Container.
	 * @param string           $id Identifier of the entry to register.
	 */
	private function register_pro_service( ContainerBuilder $container, string $id ): void { // phpcs:ignore @phpstan-ignore-line
		$container->register( $id )
			->setPublic( true )
			->addArgument( $id )
			->addArgument( new Reference( 'service_container' ) )
			->setFactory(
				[
					self::class,
					'get_pro_service',
				]
			);
	}

	/**
	 * @param string                  $id Identifier of the entry to get.
	 * @param ContainerInterface|null $container Container.
	 *
	 * @return null|object
	 */
	public static function get_pro_service( string $id, ContainerInterface $container = null ) {
		if ( $container === null ) {
			return null;
		}
		if ( ! $container->has( IContainerConfigurator::PRO_CONTAINER_SERVICE_SLUG ) ) {
			return null;
		}

		return $container->get( IContainerConfigurator::PRO_CONTAINER_SERVICE_SLUG )->get( $id );
	}
}
