<?php

declare(strict_types=1);

namespace Drupal\lms_xapi_activity\Plugin\ActivityAnswer;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\lms\Attribute\ActivityAnswer;
use Drupal\lms\Entity\Answer;
use Drupal\lms\Plugin\ActivityAnswerBase;
use Drupal\lms_xapi\XapiService;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Xapi/TinCan activity plugin.
 */
#[ActivityAnswer(
  id: 'xapi',
  name: new TranslatableMarkup('Xapi / TinCan'),
)]
final class Xapi extends ActivityAnswerBase {

  /**
   * The Xapi service.
   */
  protected XapiService $xapi;

  /**
   * Static score storage.
   */
  private ?float $score = NULL;

  /**
   * {@inheritdoc}
   */
  public function injectServices(ContainerInterface $container): void {
    parent::injectServices($container);
    $this->xapi = $container->get(XapiService::class);
  }

  /**
   * {@inheritdoc}
   */
  public function getScore(Answer $answer): float {
    if ($this->score !== NULL) {
      return $this->score;
    }

    $account = $answer->getOwner();
    $activity = $answer->getActivity();
    $cacheable_metadata = new CacheableMetadata();
    $lms_id = $this->xapi->getLmsId($activity, $account, $cacheable_metadata);
    $score = $this->xapi->getScoreFromLrs($lms_id);
    $this->score = $score ?? 0;

    return $this->score;
  }

  /**
   * {@inheritdoc}
   */
  public function evaluatedOnSave(Answer $answer): bool {
    if ($this->getScore($answer) === 0.0) {
      return FALSE;
    }
    return TRUE;
  }

  /**
   * {@inheritdoc}
   */
  public function answeringForm(array &$form, FormStateInterface $form_state, Answer $answer): void {
    $disable_submit = FALSE;

    // Save the answer without data so details can be displayed any time.
    // even when the activity is in progress.
    if ($answer->isNew()) {
      $answer->save();
      $disable_submit = TRUE;
    }
    // If the user got back to the activity and has a score of 0 it means
    // the course has not been finished yet - we should disable the submit
    // button.
    // @see self::getScore()
    elseif ($this->getScore($answer) === 0.0) {
      $disable_submit = TRUE;
    }

    // Add some js to handle the submit button.
    $form['xapi_attachments'] = [
      '#attached' => [
        'library' => ['lms_xapi_activity/frontend'],
      ],
    ];

    $form['actions']['submit']['#attributes']['data-xapi-submit'] = '';
    if ($disable_submit) {
      $form['actions']['submit']['#attributes']['disabled'] = 'disabled';
    }
  }

  /**
   * {@inheritdoc}
   */
  public function evaluationDisplay(Answer $answer): array {
    $activity = $answer->getActivity();

    if (!$activity->hasField('field_xapi_package')) {
      throw new \Exception('Xapi field missing on activity.');
    }
    $items = $activity->get('field_xapi_package');
    if ($items->isEmpty()) {
      return [];
    }
    /** @var \Drupal\lms_xapi\Plugin\Field\FieldType\XapiItem */
    $xapi_item = $items->first();
    $cacheable_metadata = new CacheableMetadata();
    /** @var \Drupal\Core\Session\AccountInterface */
    $account = $answer->get('user_id')->entity;
    $launch_url = $this->xapi->getLaunchUrl(
      $xapi_item->getPackagePath(),
      $activity,
      $account,
      $cacheable_metadata
    );
    if ($launch_url === NULL) {
      return [];
    }

    // Display the entire package with student data loaded from LRS.
    $build = [
      '#type' => 'html_tag',
      '#tag' => 'iframe',
      '#attributes' => [
        'src' => $launch_url,
        'style' => 'width: 100%; min-height: 800px; border: 0;',
      ],
      '#value' => '',
    ];
    $cacheable_metadata->applyTo($build);

    return $build;
  }

}
