<?php

declare(strict_types=1);

namespace Drupal\languagewire_translation_provider\api\Managers;

use Drupal\languagewire_translation_provider\api\Core\Settings;
use Drupal\languagewire_translation_provider\api\Endpoints\Files\AddFiles;
use Drupal\languagewire_translation_provider\api\Endpoints\Files\AddReferenceFiles;
use Drupal\languagewire_translation_provider\api\Endpoints\Files\DeleteFile;
use Drupal\languagewire_translation_provider\api\Endpoints\Files\DeleteReferenceFile;
use Drupal\languagewire_translation_provider\api\Endpoints\Files\DownloadFile;
use Drupal\languagewire_translation_provider\api\Endpoints\Files\DownloadReferenceFile;
use Drupal\languagewire_translation_provider\api\Endpoints\Files\FileMetadata;
use Drupal\languagewire_translation_provider\api\Endpoints\Files\ReferenceFileMetadata;
use Drupal\languagewire_translation_provider\api\Models\Files\FileModel;

/**
 * File manager.
 */
class FileManager extends AbstractManager {

  /**
   * Project manager.
   *
   * @var \Drupal\languagewire_translation_provider\api\Managers\ProjectManager
   */
  private ProjectManager $projectManager;

  /**
   * Files.
   *
   * @var \Drupal\languagewire_translation_provider\api\Models\Files\FileModel[]
   */
  private array $files = [];

  /**
   * Reference files.
   *
   * @var \Drupal\languagewire_translation_provider\api\Models\Files\FileModel[]
   */
  private array $referenceFiles = [];

  public function __construct(Settings $settings, ProjectManager $projectManager) {
    parent::__construct($settings);

    $this->projectManager = $projectManager;
  }

  /**
   * Get files.
   */
  public function getFiles(): array {
    return $this->files;
  }

  /**
   * Upload file.
   */
  public function uploadFile(FileModel $file, string $targetLanguage): ?FileModel {
    $addFiles = new AddFiles($this->settings);

    $addFiles->addFile(
          $this->projectManager->getProject()->getId(),
          $file->getSourceFileName(),
          $file->getSourceLanguage(),
          $targetLanguage,
          json_decode($file->getSourceContent())
      );

    $addFileResult = $addFiles->execute();

    if ($addFileResult === NULL) {
      return NULL;
    }

    $file->setFields(['sourceFileId' => $addFileResult['fileId']]);

    $this->files[] = $file;

    return $file;
  }

  /**
   * Download file.
   */
  public function downloadFile(string $fileID): ?string {
    $downloadFile = new DownloadFile($this->settings);

    $downloadFile->setFileData(
          $this->projectManager->getProject()->getId(),
          $fileID
      );

    $downloadResult = $downloadFile->execute();

    if ($downloadResult === NULL) {
      return NULL;
    }

    return json_encode($downloadResult);
  }

  /**
   * Download file metadata.
   */
  public function downloadFileMetadata(string $fileID): ?array {
    $fileMetadata = new FileMetadata($this->settings);

    $fileMetadata->setFileData(
          $this->projectManager->getProject()->getId(),
          $fileID
      );

    $fileMetadataResult = $fileMetadata->execute();

    if ($fileMetadataResult === NULL) {
      return NULL;
    }

    return $fileMetadataResult;
  }

  /**
   * Delete file.
   */
  public function deleteFile(string $fileID): bool {
    $deleteFile = new DeleteFile($this->settings);

    $deleteFile->setFileData(
          $this->projectManager->getProject()->getId(),
          $fileID
      );

    $deleteFileResult = $deleteFile->execute();

    if ($deleteFileResult === NULL) {
      return FALSE;
    }

    return TRUE;
  }

  /**
   * Get reference files.
   */
  public function getReferenceFiles(): array {
    return $this->referenceFiles;
  }

  /**
   * Upload reference file.
   */
  public function uploadReferenceFile(FileModel $referenceFileModel): ?FileModel {
    $addReferenceFiles = new AddReferenceFiles($this->settings);

    $addReferenceFiles->addReferenceFile(
          $this->projectManager->getProject()->getId(),
          $referenceFileModel->getSourceFileName(),
          $referenceFileModel->getSourceContent()
      );

    $addReferenceFileResult = $addReferenceFiles->execute();

    if ($addReferenceFileResult === NULL) {
      return NULL;
    }

    $referenceFileModel->setFields(['sourceFileId' => $addReferenceFileResult['fileId']]);

    $this->files[] = $referenceFileModel;

    return $referenceFileModel;
  }

  /**
   * Download reference file.
   */
  public function downloadReferenceFile(string $referenceFileID): ?string {
    $downloadReferenceFile = new DownloadReferenceFile($this->settings);

    $downloadReferenceFile->setFileData(
          $this->projectManager->getProject()->getId(),
          $referenceFileID
      );

    $downloadResult = $downloadReferenceFile->execute();

    if ($downloadResult === NULL) {
      return NULL;
    }

    return current($downloadResult);
  }

  /**
   * Download reference file metadata.
   */
  public function downloadReferenceFileMetadata(string $referenceFileID): ?array {
    $referenceFileMetadata = new ReferenceFileMetadata($this->settings);

    $referenceFileMetadata->setFileData(
          $this->projectManager->getProject()->getId(),
          $referenceFileID
      );

    $referenceFileMetadataResult = $referenceFileMetadata->execute();

    if ($referenceFileMetadataResult === NULL) {
      return NULL;
    }

    return $referenceFileMetadataResult;
  }

  /**
   * Delete reference file.
   */
  public function deleteReferenceFile(string $referenceFileID): bool {
    $deleteReferenceFile = new DeleteReferenceFile($this->settings);

    $deleteReferenceFile->setFileData(
          $this->projectManager->getProject()->getId(),
          $referenceFileID
      );

    $deleteReferenceFileResult = $deleteReferenceFile->execute();

    if ($deleteReferenceFileResult === NULL) {
      return FALSE;
    }

    return TRUE;
  }

}
