<?php

namespace Fgm\ComposerCheck;

/**
 * Class MergeBox merges requirements with locked versions and platform.
 */
class MergeBox {

  /**
   * The composer.lock loader.
   *
   * @var \Fgm\ComposerCheck\LockLoader
   */
  protected $lock;

  /**
   * The merged packages.
   *
   * @var array
   */
  protected $packages;

  /**
   * The composer.json loader.
   *
   * @var \Fgm\ComposerCheck\RequirementsLoader
   */
  protected $requirements;

  /**
   * MergeBox constructor.
   *
   * @param \Fgm\ComposerCheck\RequirementsLoader $requirementsLoader
   *   The composer.json loader.
   * @param \Fgm\ComposerCheck\LockLoader $lockLoader
   *   The composer.lock loader.
   * @param bool $all
   *   Include all packages or only those required ?
   */
  public function __construct(RequirementsLoader $requirementsLoader,
    LockLoader $lockLoader,
    bool $all) {
    $this->requirements = $requirementsLoader;
    $this->lock = $lockLoader;
    $this->all = $all;
  }

  /**
   * Perform reconciliation of requirements and locked packages/platform.
   */
  public function merge() {
    $packages = ['dev' => [], 'run' => []];

    foreach ($this->requirements->getRun() as $package => $requirement) {
      if ($this->all || !empty($requirement)) {
        $package = strtolower($package);
        $packages['run'][$package]['requirement'] = $requirement;
      }
    }

    foreach ($this->requirements->getDev() as $package => $requirement) {
      if ($this->all || !empty($requirement)) {
        $package = strtolower($package);
        $packages['dev'][$package]['requirement'] = $requirement;
      }
    }

    foreach ($this->lock->getRun() as $packageInfo) {
      $package = strtolower($packageInfo['name']);
      if ($this->all || !empty($packages['run'][$package])) {
        $version = $packageInfo['version'];
        $packages['run'][$package]['version'] = $version;
      }
    }

    foreach ($this->lock->getDev() as $packageInfo) {
      $package = strtolower($packageInfo['name']);
      if ($this->all || !empty($packages['dev'][$package])) {
        $version = $packageInfo['version'];
        $packages['dev'][$package]['version'] = $version;
      }
    }

    ksort($packages['dev']);
    ksort($packages['run']);
    $this->packages = $packages;
  }

  /**
   * Return the merge results.
   *
   * @return array
   *   An array of requirements and matching locked versions.
   */
  public function getRows() {
    return $this->packages;
  }

}