<?php

namespace Drupal\languagewire_translation_provider\Platform;

use Drupal\languagewire_translation_provider\Adapter\SystemInterface;
use Drupal\languagewire_translation_provider\Adapter\TMGMT\TmgmtTranslatorInterface;
use Drupal\languagewire_translation_provider\Client\LanguageWireClient;
use Drupal\languagewire_translation_provider\Database\InvoicingAccountRepositoryInterface;
use Drupal\languagewire_translation_provider\Database\ProjectTemplateRepositoryInterface;
use Drupal\languagewire_translation_provider\Database\ServiceRepositoryInterface;
use Drupal\languagewire_translation_provider\Database\TermBaseRepositoryInterface;
use Drupal\languagewire_translation_provider\Database\TranslationMemoryRepositoryInterface;
use Drupal\languagewire_translation_provider\Database\UserRepositoryInterface;
use Drupal\languagewire_translation_provider\Database\WorkAreaRepositoryInterface;

/**
 * Configuration Item Importer.
 */
final class ConfigurationItemImporter {

  /**
   * Available Users.
   *
   * @var AvailableUsers
   */
  private AvailableUsers $availableUsers;

  /**
   * Available Invoicing Accounts.
   *
   * @var AvailableInvoicingAccounts
   */
  private AvailableInvoicingAccounts $availableInvoicingAccounts;

  /**
   * Available Services.
   *
   * @var AvailableServices
   */
  private AvailableServices $availableServices;

  /**
   * Available Translation Memories.
   *
   * @var AvailableTranslationMemories
   */
  private AvailableTranslationMemories $availableTranslationMemories;

  /**
   * Available Term Bases.
   *
   * @var AvailableTermBases
   */
  private AvailableTermBases $availableTermBases;

  /**
   * Available Work Areas.
   *
   * @var AvailableWorkAreas
   */
  private AvailableWorkAreas $availableWorkAreas;

  /**
   * Available Project Templates.
   *
   * @var AvailableProjectTemplates
   */
  private AvailableProjectTemplates $availableProjectTemplates;

  /**
   * Service Repository.
   *
   * @var \Drupal\languagewire_translation_provider\Database\ServiceRepositoryInterface
   */
  private ServiceRepositoryInterface $serviceRepository;

  /**
   * User Repository.
   *
   * @var \Drupal\languagewire_translation_provider\Database\UserRepositoryInterface
   */
  private UserRepositoryInterface $userRepository;

  /**
   * Invoicing Account Repository.
   *
   * @var \Drupal\languagewire_translation_provider\Database\InvoicingAccountRepositoryInterface
   */
  private InvoicingAccountRepositoryInterface $invoicingAccountRepository;


  /**
   * Translation Memory Repository.
   *
   * @var \Drupal\languagewire_translation_provider\Database\TranslationMemoryRepositoryInterface
   */
  private TranslationMemoryRepositoryInterface $translationMemoryRepository;

  /**
   * Term Base Repository.
   *
   * @var \Drupal\languagewire_translation_provider\Database\TermBaseRepositoryInterface
   */
  private TermBaseRepositoryInterface $termBaseRepository;

  /**
   * Work Area Repository.
   *
   * @var \Drupal\languagewire_translation_provider\Database\WorkAreaRepositoryInterface
   */
  private WorkAreaRepositoryInterface $workAreaRepository;

  /**
   * Project Template Repository.
   *
   * @var \Drupal\languagewire_translation_provider\Database\ProjectTemplateRepositoryInterface
   */
  private ProjectTemplateRepositoryInterface $projectTemplateRepository;

  /**
   * Platform Client.
   *
   * @var \Drupal\languagewire_translation_provider\Client\LanguageWireClient
   */
  private LanguageWireClient $platformClient;

  /**
   * Constructs a new ConfigurationItemImporter object.
   *
   * @param \Drupal\languagewire_translation_provider\Adapter\SystemInterface $system
   *   System.
   * @param \Drupal\languagewire_translation_provider\Platform\AvailableUsers $availableUsers
   *   Available Users.
   * @param \Drupal\languagewire_translation_provider\Platform\AvailableInvoicingAccounts $availableInvoicingAccounts
   *   Available Invoicing Accounts.
   * @param \Drupal\languagewire_translation_provider\Platform\AvailableServices $availableServices
   *   Available Services.
   * @param \Drupal\languagewire_translation_provider\Platform\AvailableTranslationMemories $availableTranslationMemories
   *   Available Translation Memories.
   * @param \Drupal\languagewire_translation_provider\Platform\AvailableTermBases $availableTermBases
   *   Available Term Bases.
   * @param \Drupal\languagewire_translation_provider\Platform\AvailableWorkAreas $availableWorkAreas
   *   Available Work Areas.
   * @param \Drupal\languagewire_translation_provider\Platform\AvailableProjectTemplates $availableProjectTemplates
   *   Available Project Templates.
   * @param \Drupal\languagewire_translation_provider\Client\LanguageWireClient $platformClient
   *   Platform Client.
   */
  public function __construct(
    SystemInterface $system,
    AvailableUsers $availableUsers,
    AvailableInvoicingAccounts $availableInvoicingAccounts,
    AvailableServices $availableServices,
    AvailableTranslationMemories $availableTranslationMemories,
    AvailableTermBases $availableTermBases,
    AvailableWorkAreas $availableWorkAreas,
    AvailableProjectTemplates $availableProjectTemplates,
    LanguageWireClient $platformClient
  ) {
    $this->availableUsers = $availableUsers;
    $this->availableInvoicingAccounts = $availableInvoicingAccounts;
    $this->availableServices = $availableServices;
    $this->availableTranslationMemories = $availableTranslationMemories;
    $this->availableTermBases = $availableTermBases;
    $this->availableWorkAreas = $availableWorkAreas;
    $this->availableProjectTemplates = $availableProjectTemplates;

    $this->serviceRepository = $system->serviceRepository();
    $this->userRepository = $system->userRepository();
    $this->invoicingAccountRepository = $system->invoicingAccountRepository();
    $this->translationMemoryRepository = $system->translationMemoryRepository();
    $this->termBaseRepository = $system->termBaseRepository();
    $this->workAreaRepository = $system->workAreaRepository();
    $this->projectTemplateRepository = $system->projectTemplateRepository();
    $this->platformClient = $platformClient;
  }

  /**
   * Import items.
   *
   * @param \Drupal\languagewire_translation_provider\Adapter\TMGMT\TmgmtTranslatorInterface $translator
   *   Translator.
   */
  public function importItems(TmgmtTranslatorInterface $translator): void {
    $this->clearAllItems($translator);
    $this->importServices($translator);
    $this->importUsers($translator);
    $this->importInvoicingAccounts($translator);
    $this->importTranslationMemories($translator);
    $this->importTermBases($translator);
    $this->importWorkAreas($translator);
    $this->importProjectTemplates($translator);
    $this->importApiLimits($translator);
  }

  /**
   * Clear all items.
   */
  public function clearAllItems(TmgmtTranslatorInterface $translator): void {
    $this->serviceRepository->removeAll($translator);
    $this->userRepository->removeAll($translator);
    $this->invoicingAccountRepository->removeAll($translator);
    $this->translationMemoryRepository->removeAll($translator);
    $this->termBaseRepository->removeAll($translator);
    $this->workAreaRepository->removeAll($translator);
    $this->projectTemplateRepository->removeAll($translator);
  }

  /**
   * Import services.
   */
  private function importServices(TmgmtTranslatorInterface $translator): void {
    $this->serviceRepository->saveAll(iterator_to_array($this->availableServices->get()), $translator);
  }

  /**
   * Import users.
   */
  private function importUsers(TmgmtTranslatorInterface $translator): void {
    $this->userRepository->saveAll(iterator_to_array($this->availableUsers->get()), $translator);
  }

  /**
   * Import invoicing accounts.
   */
  private function importInvoicingAccounts(TmgmtTranslatorInterface $translator): void {
    $this->invoicingAccountRepository->saveAll(iterator_to_array($this->availableInvoicingAccounts->get()), $translator);
  }

  /**
   * Import translation memories.
   */
  private function importTranslationMemories(TmgmtTranslatorInterface $translator): void {
    $this->translationMemoryRepository->saveAll(iterator_to_array($this->availableTranslationMemories->get()), $translator);
  }

  /**
   * Import term bases.
   */
  private function importTermBases(TmgmtTranslatorInterface $translator): void {
    $this->termBaseRepository->saveAll(iterator_to_array($this->availableTermBases->get()), $translator);
  }

  /**
   * Import work areas.
   */
  private function importWorkAreas(TmgmtTranslatorInterface $translator): void {
    $this->workAreaRepository->saveAll(iterator_to_array($this->availableWorkAreas->get()), $translator);
  }

  /**
   * Import project templates.
   */
  private function importProjectTemplates(TmgmtTranslatorInterface $translator): void {
    $this->projectTemplateRepository->saveAll($this->availableProjectTemplates->get(), $translator);
  }

  /**
   * Import api limits.
   */
  private function importApiLimits(TmgmtTranslatorInterface $translator): void {
    $apiLimits = $this->platformClient->getLimits();
    $translator->setMaxDocumentsPerProject($apiLimits->getMaxDocumentsPerProject());
  }

}
