<?php

declare(strict_types=1);

namespace Drupal\farm_sensor\Hook;

use Drupal\Component\Datetime\TimeInterface;
use Drupal\Component\Utility\Html;
use Drupal\Core\DependencyInjection\AutowireTrait;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Hook\Attribute\Hook;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Drupal\asset\Entity\AssetInterface;
use Drupal\data_stream\Entity\DataStreamInterface;

/**
 * Theme hook implementations for farm_sensor.
 */
class ThemeHooks {

  use AutowireTrait;
  use StringTranslationTrait;

  public function __construct(
    protected TimeInterface $time,
  ) {}

  /**
   * Implements hook_ENTITY_TYPE_view_alter().
   */
  #[Hook('asset_view_alter')]
  public function assetViewAlter(array &$build, AssetInterface $asset, EntityViewDisplayInterface $display) {

    // Bail if this is not a sensor asset.
    if ($asset->bundle() != 'sensor') {
      return;
    }

    // If the user has permission to edit this sensor asset, display developer
    // information.
    // Only render developer information in the full view mode.
    // Use getOriginalMode() because getMode() is not reliable. The default
    // display mode will return "full" unless a "default" display is actually
    // saved in config. In either case, the original mode is always "full".
    if ($asset->access('update') === TRUE && $display->getOriginalMode() === 'full') {

      // Add a Developer information details element with brief description.
      $build['api'] = [
        '#type' => 'details',
        '#title' => $this->t('Developer information'),
        '#description' => $this->t('This sensor asset will listen for data posted to it from other web-connected devices and save it to data streams based on the name of the value used in the request. If a data stream by that name does not exist, a new one will be created automatically. Data for multiple streams may be included in each request. Use the information below to configure your device to begin posting data to this sensor.'),
        '#open' => FALSE,
      ];

      // Build URL to the sensor API endpoint.
      $url = new Url('farm_sensor.data_stream_data', ['uuid' => $asset->uuid()]);

      // If the sensor is not public, include the private key.
      if (!$asset->get('public')->value) {
        $url->setOption('query', ['private_key' => $asset->get('private_key')->value]);
      }

      // Render the API url.
      $url_string = $url->setAbsolute()->toString();
      $url_string_label = $this->t('URL');
      $build['api']['url'] = [
        '#type' => 'link',
        '#title' => $url_string,
        '#url' => $url,
        '#prefix' => '<p><strong>' . $url_string_label . ':</strong> ',
        '#suffix' => '</p>',
        '#weight' => -10,
      ];

      // Load referenced basic data streams.
      $basic_data_streams = array_filter($asset->get('data_stream')->referencedEntities(), function (DataStreamInterface $data_stream) {
        return $data_stream->bundle() === 'basic';
      });

      // Generate example stream names. If there are basic data streams already
      // referenced then replace them with actual names.
      $example_stream_names = [
        'value',
        'value2',
      ];
      if (!empty($basic_data_streams)) {
        foreach ($basic_data_streams as $key => $data_stream) {
          if (!empty($data_stream->label())) {
            $example_stream_names[$key] = Html::escape($data_stream->label());
          }
        }
      }

      // Render JSON examples.
      $request_time = $this->time->getRequestTime();
      $json_example = '{ "timestamp": ' . $request_time . ', "' . $example_stream_names[0] . '": 76.5 }';
      $json_example_label = $this->t('JSON example');
      $build['api']['json_example'] = [
        '#markup' => '<p><strong>' . $json_example_label . ':</strong> ' . $json_example . '</p>',
      ];
      $json_example_multiple = '{ "timestamp": ' . $request_time . ', "' . $example_stream_names[0] . '": 76.5, "' . $example_stream_names[1] . '": 60 }';
      $json_example_multiple_label = $this->t('JSON example (multiple values)');
      $build['api']['json_example_multiple'] = [
        '#markup' => '<p><strong>' . $json_example_multiple_label . ':</strong> ' . $json_example_multiple . '</p>',
      ];

      // Render example CURL command.
      $curl_example = 'curl -H "Content-Type: application/json" -X POST -d \'' . $json_example . '\' ' . $url_string;
      $curl_example_label = $this->t('Example CURL command');
      $build['api']['curl_example'] = [
        '#markup' => '<p><strong>' . $curl_example_label . ':</strong> ' . $curl_example . '</p>',
      ];
    }
  }

}
