<?php

namespace LakeDrops\Component\Composer;

use Composer\Composer;
use Composer\IO\IOInterface;
use Composer\Package\PackageInterface;
use Composer\Script\Event;
use Symfony\Component\Console\Input\InputInterface;

/**
 * Base handler class to provide common functionality.
 *
 * @package LakeDrops\Component\Composer
 */
abstract class BaseHandler implements BaseHandlerInterface {

  /**
   * The composer object of this session.
   *
   * @var \Composer\Composer
   */
  protected Composer $composer;

  /**
   * The input-output object of the composer session.
   *
   * @var \Composer\IO\IOInterface
   */
  protected IOInterface $io;

  /**
   * The project config.
   *
   * @var \LakeDrops\Component\Composer\Config
   */
  protected Config $config;

  /**
   * The input service.
   *
   * @var \Symfony\Component\Console\Input\InputInterface
   */
  protected InputInterface $consoleInput;

  /**
   * The event that triggered the action.
   *
   * @var \Composer\Script\Event
   */
  protected Event $event;

  /**
   * The Drupal core package.
   *
   * @var \Composer\Package\PackageInterface
   */
  protected PackageInterface $drupalCorePackage;

  /**
   * The .env service.
   *
   * @var \LakeDrops\Component\Composer\Dotenv
   */
  protected Dotenv $env;

  /**
   * Handler constructor.
   *
   * @param \Composer\Composer $composer
   *   The composer object of this session.
   * @param \Composer\IO\IOInterface $io
   *   The input-output object of the composer session.
   */
  public function __construct(Composer $composer, IOInterface $io) {
    $this->composer = $composer;
    $this->io = $io;
  }

  /**
   * Initialize configuration.
   */
  protected function init(): void {
    if (!isset($this->config)) {
      $this->env = new Dotenv($this->configId(), $this->io);
      $this->config = new Config($this->configId(), $this->configDefault(), $this->env);
      $this->postInit();
    }
  }

  /**
   * Provides the default config array.
   *
   * @return array
   *   The default config array.
   */
  protected function configDefault(): array {
    return [];
  }

  /**
   * May be overwritten by implementing classes.
   */
  protected function postInit(): void {}

  /**
   * Provides the config object.
   *
   * @return \LakeDrops\Component\Composer\Config
   *   The config object.
   */
  public function getConfig(): Config {
    $this->init();
    return $this->config;
  }

  /**
   * {@inheritdoc}
   */
  public function setEvent(Event $event): self {
    $this->event = $event;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function setInput(InputInterface $input): BaseHandler {
    $this->consoleInput = $input;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getDrupalCorePackage(): ?PackageInterface {
    if (!isset($this->drupalCorePackage)) {
      $this->drupalCorePackage = $this->getPackage('drupal/core');
    }
    return $this->drupalCorePackage;
  }

  /**
   * {@inheritdoc}
   */
  public function getPackage(string $name): ?PackageInterface {
    return $this->composer->getRepositoryManager()->getLocalRepository()->findPackage($name, '*');
  }

  /**
   * {@inheritdoc}
   */
  public function isDevMode(): bool {
    if (isset($this->event)) {
      return $this->event->isDevMode();
    }
    if (isset($this->consoleInput)) {
      return !$this->consoleInput->hasOption('no-dev');
    }
    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function isLocalDevMode(): bool {
    $local_dev_mode = getenv('LAKEDROPS_DEV_ENV');
    return !empty($local_dev_mode);
  }

  /**
   * {@inheritdoc}
   */
  public function isCiContext(): bool {
    $ci_project_dir = getenv('CI_PROJECT_DIR');
    return !empty($ci_project_dir);
  }

  /**
   * {@inheritdoc}
   */
  public function git(string $command, string $path = NULL): void {
    Utils::git($command, $path);
  }

  /**
   * {@inheritdoc}
   */
  public function gitIgnore(string $pattern): void {
    Utils::gitIgnore($pattern);
  }

  /**
   * {@inheritdoc}
   *
   * @phpcs:disable Squiz.NamingConventions.VaildMethodName.NotCamelCaps
   */
  public function gitLfs(string $pattern): void {
    Utils::gitLfs($pattern);
  }

}