<?php

namespace Drupal\reader\Services;

use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Entity\EntityFormBuilderInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Link;
use Drupal\Core\Pager\PagerManagerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Site\Settings;
use Drupal\Core\Url;
use Drupal\reader\ReaderBase;
use Symfony\Component\HttpFoundation\RequestStack;

class Reader extends ReaderBase {

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The entity form builder.
   *
   * @var \Drupal\Core\Entity\EntityFormBuilderInterface
   */
  protected $entityFormBuilder;

  /**
   * The module handler.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;

  /**
   * @var \Drupal\Core\Datetime\DateFormatInterface
   */
  protected $dateFormatter;

  /**
   * The pager manager.
   *
   * @var \Drupal\Core\Pager\PagerManagerInterface
   */
  protected $pagerManager;

  /**
   * The request stack.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  protected $requestStack;

  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $currentUser;

  /**
   * Reader constructor.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\Entity\EntityFormBuilderInterface $entity_form_builder
   *   The entity form builder.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   The module handler.
   * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
   *   The date formatter.
   * @param \Drupal\Core\Pager\PagerManagerInterface $pager_manager
   *   The pager manager.
   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
   *   The request stack.
   * @param \Drupal\Core\Session\AccountInterface $current_user
   *   The current user.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager, EntityFormBuilderInterface $entity_form_builder, ModuleHandlerInterface $module_handler, DateFormatterInterface $date_formatter, PagerManagerInterface $pager_manager, RequestStack $request_stack, AccountInterface $current_user) {
    $this->entityTypeManager = $entity_type_manager;
    $this->entityFormBuilder = $entity_form_builder;
    $this->moduleHandler = $module_handler;
    $this->dateFormatter = $date_formatter;
    $this->pagerManager = $pager_manager;
    $this->requestStack = $request_stack;
    $this->currentUser = $current_user;
  }

  /**
   * {@inheritdoc}
   */
  public function getChannels() {

    if (!$this->moduleHandler->moduleExists('aggregator') || !$this->currentUser->hasPermission('access reader')) {
      return [];
    }

    return [
      'label' => $this->t('Aggregator'),
      'channels' => [
        (object) [
          'uid' => 'aggregator',
          'unread' => 0,
          'name' => $this->t('All feeds'),
        ],
      ],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function getSourcesPage($op) {
    switch ($op) {
      case 'add':
        $build = $this->addSourcesButton($this->t('Back to feeds'), 'reader');
        $feed = $this->entityTypeManager->getStorage('aggregator_feed')->create();
        $form = $this->entityFormBuilder->getForm($feed);
        $form['#action'] .= '?destination=' . $this->getSourcesListUrl('reader');
        $build['add'] = $form;
        break;

      case 'edit':
        $build = $this->addSourcesButton($this->t('Back to feeds'), 'reader');
        $feed = $this->entityTypeManager->getStorage('aggregator_feed')->load($_GET['id']);
        $form = $this->entityFormBuilder->getForm($feed);
        $form['#action'] .= '&destination=' . $this->getSourcesListUrl('reader');
        $form['actions']['delete']['#access'] = FALSE;
        $build['edit'] = $form;
        break;

      case 'delete':
        $build = $this->addSourcesButton($this->t('Back to feeds'), 'reader');
        $feed = $this->entityTypeManager->getStorage('aggregator_feed')->load($_GET['id']);
        $form = $this->entityFormBuilder->getForm($feed, 'delete');
        $form['actions']['cancel']['#access'] = FALSE;
        $form['#action'] .= '&destination=' . $this->getSourcesListUrl('reader');
        $build['delete'] = $form;
        $build['delete']['#prefix'] = $this->addSourcesConfirmDeleteText($feed->label());
        break;

      default:
        $build = $this->addSourcesButton($this->t('+ Add feed'), 'reader', 'add');

        $rows = [];
        $feeds = $this->entityTypeManager->getStorage('aggregator_feed')->loadMultiple();
        foreach ($feeds as $feed) {
          $row = [];
          $row[] = $feed->label();
          $row[] = Link::fromTextAndUrl($this->t('Edit'), Url::fromRoute('reader.sources', [
            'module' => 'reader',
            'op' => 'edit',
          ], ['query' => ['id' => $feed->id()]]))->toString();
          $row[] = Link::fromTextAndUrl($this->t('Delete'), Url::fromRoute('reader.sources', [
            'module' => 'reader',
            'op' => 'delete',
          ], ['query' => ['id' => $feed->id()]]))->toString();
          $rows[] = $row;
        }

        $build['table'] = [
          '#type' => 'table',
          '#rows' => $rows,
          '#empty' => $this->t('No feeds available'),
          '#attributes' => ['class' => ['reader-content-table']],
        ];

        break;
    }

    $build['#title'] = $this->t('Manage Aggregator feeds');
    return $build;
  }

  /**
   * {@inheritdoc}
   */
  public function getTimeline($id, $search = NULL) {
    $items = [];
    $paging = [];
    $limit = Settings::get('reader_aggregator_items_per_page', 10);

    if ($this->moduleHandler->moduleExists('aggregator') && $this->currentUser->hasPermission('access reader')) {
      /** @var \Drupal\aggregator\ItemInterface[] $posts */

      $page = $this->requestStack->getCurrentRequest()->get('page', 0);

      if (empty($search)) {
        $posts = $this->entityTypeManager->getStorage('aggregator_item')->loadAll($limit);
      }
      else {
        $posts = $this->searchAggregatorPosts($search, $limit);
      }
      foreach ($posts as $post) {
        /** @var \Drupal\aggregator\FeedInterface $feed */
        $feed = $this->entityTypeManager->getStorage('aggregator_feed')->load($post->getFeedId());
        $item = [];
        $item['_id'] = $post->id();
        $item['_is_read'] = 1;
        $item['type'] = 'entry';
        $item['url'] = $post->getLink();
        $item['name'] = $post->getTitle();
        $item['content'] = (object) ['html' => $post->getDescription()];
        $item['author'] = (object) ['url' => $feed->getUrl(), 'name' => $feed->label()];
        $item['published'] = $this->dateFormatter->format($post->getPostedTime(), 'custom', 'Y-m-dTH:i:s');

        $items[] = (object) $item;
      }

      $pager = $this->pagerManager->getPager();
      $pager_total = $pager->getTotalPages();
      if (isset($pager_total) && is_numeric($pager_total)) {
        $page++;
        if ($pager_total > $page || $page > 0) {
          $paging = ['paging' => (object) ['after' => $page]];
        }
      }
    }

    return ['items' => $items] + $paging;
  }

  /**
   * Search in the aggregator posts.
   *
   * @param $search
   * @param $limit
   *
   * @return \Drupal\Core\Entity\EntityInterface[]
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  protected function searchAggregatorPosts($search, $limit) {
    $query = $this->entityTypeManager->getStorage('aggregator_item')->getQuery();

    $query->accessCheck(FALSE)
      ->sort('timestamp', 'DESC')
      ->sort('iid', 'DESC');

    $group = $query
      ->orConditionGroup()
      ->condition('title', '%' . \Drupal::database()->escapeLike($search) . '%', 'LIKE')
      ->condition('description', '%' . \Drupal::database()->escapeLike($search) . '%', 'LIKE');
    $query->condition($group);

    if (!empty($limit)) {
      $query->pager($limit);
    }

    return $this->entityTypeManager->getStorage('aggregator_item')->loadMultiple($query->execute());
  }

}
