<?php

namespace WPDesk\ActivationReminder\Composer;

use Composer\Command\BaseCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;


/**
 * Can prepare activation reminder for plugin.
 *
 * @package WPDesk\Composer\GitPlugin\Command
 */
class PrepareActivationReminderCommand extends BaseCommand
{

    protected function configure()
    {
        $this
            ->setName('prepare-activation-reminder')
            ->setDescription('Prepares activation reminder for WP Desk plugin.');
    }

    /**
     * Execute command.
     *
     * @param InputInterface $input
     * @param OutputInterface $output
     * @return int|void|null
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
	    $output->writeln("Creating activation reminder.");

	    if ( $this->package_has_activation_remider() ) {
		    $classLoader = require( 'vendor/autoload.php' );

		    $class_map = $classLoader->getClassMap();

		    $random_class = $this->get_random_class( $class_map );

		    $random_letter = strtolower( chr( rand( 65, 90 ) ) );

		    $target_file = $class_map[ $random_class ];
		    $target_file = str_replace( '.php', $random_letter . '.php', $target_file );
		    $target_file = str_replace( getcwd() . '/vendor/composer/../../', '', $target_file );

		    $target_dir = dirname( $target_file );

		    $output->writeln( "Target file name: $target_file" );

		    $this->clear_vendor_prefixed();

		    passthru( 'composer generate-vendor-prefixed' );

		    copy( 'vendor/wpdesk/wp-wpdesk-activation-reminder/src/Reminder.php', $target_file );

		    $this->regenerate_autoload( $target_file );

		    $popup_javascript_file = $target_dir . '/popup.js';
		    $popup_css_file        = $target_dir . '/popup.css';

		    copy( 'vendor/wpdesk/wp-wpdesk-activation-reminder/assets/js/popup.js', $popup_javascript_file );
		    copy( 'vendor/wpdesk/wp-wpdesk-activation-reminder/assets/css/popup.css', $popup_css_file );

		    $this->prepare_class( $random_class . $random_letter, $target_file, $popup_javascript_file, $popup_css_file );

		    $output->writeln( "Activation reminder created." );
	    } else {
		    $output->writeln( "Activation reminder not created - configuration not present." );
	    }
    }

	/**
	 * @return bool
	 */
    private function package_has_activation_remider() {
	    $extra = $this->getComposer()->getPackage()->getExtra();

    	return isset( $extra['activation-reminder'] );
    }

	/**
	 * @param string $class_file
	 */
    private function regenerate_autoload( $class_file ) {
	    $composer = $this->getComposer();
	    $config = $composer->getConfig();
	    $localRepo = $composer->getRepositoryManager()->getLocalRepository();
	    $package = $composer->getPackage();
	    $installationManager = $composer->getInstallationManager();
	    $optimize = $config->get('optimize-autoloader');

	    $autoload = $package->getAutoload();
	    $autoload['files'] = isset( $autoload['files'] ) ? $autoload['files'] : [];
	    $autoload['files'][] = $class_file;
	    $package->setAutoload( $autoload );

	    $composer->getAutoloadGenerator()->dump( $config, $localRepo, $package, $installationManager, 'composer', $optimize );
    }

	/**
	 * @param string $class_name
	 * @param string $class_file
	 * @param string $popup_javascript_file
	 * @param string $popup_css_file
	 */
    private function prepare_class( $class_name, $class_file, $popup_javascript_file, $popup_css_file ) {
	    $composer = $this->getComposer();
	    $package = $composer->getPackage();
	    $extra = $package->getExtra();

	    $plugin_title = $extra['activation-reminder']['plugin-title'];
	    $plugin_dir = $extra['activation-reminder']['plugin-dir'];
	    $logo_url = $extra['activation-reminder']['logo-url'];
	    $buy_plugin_url = $extra['activation-reminder']['buy-plugin-url'];

	    $namespace = $this->prepare_namespace_from_class_name( $class_name );
    	$short_classname = $this->prepare_short_class_name_from_class_name( $class_name );

    	$file_contents = file_get_contents( $class_file );
    	$file_contents = str_replace( 'namespace ReminderNamespace;', 'namespace ' . $namespace . ';', $file_contents );
    	$file_contents = str_replace( 'class Reminder', 'class ' . $short_classname, $file_contents );
	    $file_contents = str_replace( 'plugin-dir', $plugin_dir, $file_contents );
	    $file_contents = str_replace( 'plugin-title', $plugin_title, $file_contents );
	    $file_contents = str_replace( 'popup-javascript-file', $plugin_dir . '/' . $popup_javascript_file, $file_contents );
	    $file_contents = str_replace( 'popup-css-file', $plugin_dir . '/' . $popup_css_file, $file_contents );
	    $file_contents = str_replace( 'script-version', rand(1, 1000), $file_contents );
	    $file_contents = str_replace( 'logo-url', $logo_url, $file_contents );
	    $file_contents = str_replace( 'buy-plugin-url', $buy_plugin_url, $file_contents );
	    $file_contents = str_replace( 'new Reminder();', 'new ' . $short_classname . '();', $file_contents );
    	file_put_contents( $class_file, $file_contents );
    }

	/**
	 * @param string $class_name
	 *
	 * @return string
	 */
    private function prepare_namespace_from_class_name( $class_name ) {
    	$exploded = explode( '\\', $class_name );
    	unset( $exploded[ count( $exploded ) - 1 ] );

    	return implode( '\\', $exploded );
    }

	/**
	 * @param string $class_name
	 *
	 * @return string
	 */
	private function prepare_short_class_name_from_class_name( $class_name ) {
		$exploded = explode( '\\', $class_name );

		return $exploded[ count( $exploded ) - 1 ];
	}

	/**
	 * @param array $class_map
	 *
	 * @return string
	 */
    private function get_random_class( $class_map ) {
    	do {
    		$class_name = array_rand( $class_map );
	    } while ( strpos( $class_map[ $class_name ], '../../vendor_prefixed/wpdesk' ) === false );

    	return $class_name;
    }

	/**
	 *
	 */
    private function clear_vendor_prefixed() {
	    $this->delete_all( 'vendor_prefixed' );
    }

	/**
	 * @param string $dir
	 */
    private function delete_all( $dir ) {
	    foreach ( glob( $dir . '/*' ) as $file ) {
		    if ( is_dir( $file ) ) {
			    $this->delete_all( $file );
		    } else {
			    unlink( $file );
		    }
	    }
	    rmdir( $dir );
    }

}