<?php

namespace Drupal\localgov_elections\Plugin\views\field;

use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\node\NodeInterface;
use Drupal\views\Plugin\views\field\FieldPluginBase;
use Drupal\views\ResultRow;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Field handler to flag the node type.
 *
 * @ViewsField("election_seats_party")
 */
class ElectionSeatsParty extends FieldPluginBase {

  /**
   * Constructs a new plugin instance.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, protected RouteMatchInterface $routeMatch, protected EntityTypeManagerInterface $entityTypeManager) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('current_route_match'),
      $container->get('entity_type.manager'),
    );
  }

  /**
   * Leave empty to avoid a query on this field.
   */
  public function query(): void {

  }

  /**
   * Render function for the election_seats_party.
   *
   * Displays the difference between number of votes of first and second
   * results in an electoral area (Ward).
   *
   * @{inheritdoc}
   */
  public function render(ResultRow $values): ?int {
    $party = $values->_entity;
    $party_tid = $party->id();
    $seats = 0;
    $party_standing = FALSE;

    // Get ID of current election node (from URL argument)
    $node = $this->routeMatch->getParameter('node');
    if ($node instanceof NodeInterface) {
      // Arg must be NID of an Election content type.
      if ($node->getType() === 'localgov_election') {
        $election = $node->id();
        // Find all 'Area vote' (localgov_area_vote) nodes referencing this
        // election.
        $query = $this->entityTypeManager->getStorage('node')->getQuery()
          ->condition('type', 'localgov_area_vote')
          ->condition('localgov_election', $election);
        $query->accessCheck(FALSE);
        $areas = $query->execute();
        // Go through each ward/area/division.
        // If a party has a candidate in the area set $party_standing to TRUE
        // If a party won the seat increment the $seats counter;.
        foreach ($areas as $area_id) {
          if ($area = $this->entityTypeManager->getStorage('node')->load($area_id)) {
            // Iterate through each candidate to see if party standing -
            // only if not already flagged.
            if ($party_standing === FALSE) {
              $candidates = $area->get('localgov_election_candidates');

              foreach ($candidates->referencedEntities() as $candidate) {
                $cand_party = $candidate->get('localgov_election_party')->target_id;
                if ($party_tid == $cand_party) {
                  $party_standing = TRUE;
                }
              }
            }

            if (!$area->get('localgov_election_winner')->isEmpty()) {
              foreach ($area->get('localgov_election_winner')->referencedEntities() as $winner) {
                $winning_party = $winner->get('localgov_election_party')->target_id ?? NULL;
                if ($party_tid === $winning_party) {
                  // Catches uncontested seats.
                  $party_standing = TRUE;
                  $seats++;
                }
              }
            }
          }
        }
      }
    }

    return $party_standing ? $seats : NULL;
  }

}
