<?php

namespace Fgm\Drupal\Composer;

use Composer\Composer;
use Composer\EventDispatcher\Event;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\Installer\InstallerEvents;
use Composer\Installer\PackageEvent;
use Composer\Installer\PackageEvents;
use Composer\IO\IOInterface;
use Composer\Plugin\Capability\Capability;
use Composer\Plugin\Capability\CommandProvider;
use Composer\Plugin\Capable;
use Composer\Plugin\PluginInterface;
use Composer\Script\Event as ScriptEvent;
use Composer\Script\ScriptEvents;

class Builder implements Capable, Capability, CommandProvider, EventSubscriberInterface, PluginInterface {

  /**
   * @var IOInterface
   */
  protected $io;

  /**
   * Apply plugin modifications to Composer
   *
   * @param Composer $composer
   * @param IOInterface $io
   */
  public function activate(Composer $composer, IOInterface $io) {
    $this->io = $io;
  }

  public function getCapabilities() {
    return [
      CommandProvider::class => Builder::class,
    ];
  }

  /**
   * For CommandProvider::class.
   */
  public function getCommands() {
    echo __METHOD__ . "\n";
    return [
      new BuildSettingsCommand(),
    ];
  }

  /**
   * Returns an array of event names this subscriber wants to listen to.
   *
   * The array keys are event names and the value can be:
   *
   * * The method name to call (priority defaults to 0)
   * * An array composed of the method name to call and the priority
   * * An array of arrays composed of the method names to call and respective
   *   priorities, or 0 if unset
   *
   * For instance:
   *
   * * array('eventName' => 'methodName')
   * * array('eventName' => array('methodName', $priority))
   * * array('eventName' => array(array('methodName1', $priority), array('methodName2'))
   *
   * @return array The event names to listen to
   */
  public static function getSubscribedEvents() {
    return [
      InstallerEvents::POST_DEPENDENCIES_SOLVING => 'onEvent',
      InstallerEvents::PRE_DEPENDENCIES_SOLVING => 'onEvent',

      PackageEvents::POST_PACKAGE_INSTALL => 'onPackageEvent',
      PackageEvents::POST_PACKAGE_UNINSTALL => 'onPackageEvent',
      PackageEvents::POST_PACKAGE_UPDATE => 'onPackageEvent',
      PackageEvents::PRE_PACKAGE_INSTALL => 'onPackageEvent',
      PackageEvents::PRE_PACKAGE_UNINSTALL => 'onPackageEvent',
      PackageEvents::PRE_PACKAGE_UPDATE => 'onPackageEvent',

//      PluginEvents::COMMAND => 'onEvent',
//      PluginEvents::INIT => 'onEvent',
//      PluginEvents::PRE_FILE_DOWNLOAD => 'onEvent',

//      ScriptEvents::POST_ARCHIVE_CMD => 'onScriptEvent',
//      ScriptEvents::POST_AUTOLOAD_DUMP => 'onScriptEvent',
//      ScriptEvents::POST_CREATE_PROJECT_CMD => 'onScriptEvent',
      ScriptEvents::POST_INSTALL_CMD => 'onScriptEvent',
//      ScriptEvents::POST_ROOT_PACKAGE_INSTALL => 'onScriptEvent',
//      ScriptEvents::POST_STATUS_CMD => 'onScriptEvent',
      ScriptEvents::POST_UPDATE_CMD => 'onScriptEvent',
//      ScriptEvents::PRE_ARCHIVE_CMD => 'onScriptEvent',
//      ScriptEvents::PRE_AUTOLOAD_DUMP => 'onScriptEvent',
//      ScriptEvents::PRE_INSTALL_CMD => 'onScriptEvent',
//      ScriptEvents::PRE_STATUS_CMD => 'onScriptEvent',
//      ScriptEvents::PRE_UPDATE_CMD => 'onScriptEvent',
    ];
  }

  public function onEvent(Event $event) {
    $this->io->write($event->getName());
  }

  public function onPackageEvent(PackageEvent $event) {
    $this->io->write([
      $event->getName(),
      $event->getOperation()->getJobType() . ' - ' . $event->getOperation()->getReason(),
      json_encode($event->getArguments()),
      json_encode($event->getInstalledRepo()->getRepositories()),
    ]);
  }

  public function onScriptEvent(ScriptEvent $event) {
    $this->io->write([
      $event->getName(),
      json_encode($event->getArguments()),
    ]);
  }
}