/**
  * Subscribe to a mailing list.
  *
  * @param SubscriptionRecipientInterface $recipient The recipient that subscribe.
  * @param null                           $mailingLists
  * @param null                           $_
  * @param int                            $options   Subscription options, see SubscriptionManager::OPT_* constants.
  *
  * @return \Avisota\Contao\Entity\Subscription[] Return the list of all NEW subscriptions.
  *                        Existing subscriptions will be omited, until you pass OPT_INCLUDE_EXISTING to $options.
  * @internal param array|MailingList $mailingList One or more mailing lists to subscribe to.
  *                                                    Pass null or omit for global subscription.
  * TODO what is $_
  * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  * @SuppressWarnings(PHPMD.NPathComplexity)
  * @SuppressWarnings(PHPMD.CamelCaseParameterName)
  * @SuppressWarnings(PHPMD.UnusedFormalParameter)
  * @SuppressWarnings(PHPMD.ShortVariable)
  */
 public function subscribe(SubscriptionRecipientInterface $recipient, $mailingLists = null, $_ = null, $options = 0)
 {
     /** @var MailingList[] $mailingLists */
     $mailingLists = func_get_args();
     array_shift($mailingLists);
     if (is_int($mailingLists[count($mailingLists) - 1])) {
         $options = array_pop($mailingLists);
     } else {
         $options = 0;
     }
     while (count($mailingLists) == 1 && is_array($mailingLists[0])) {
         $mailingLists = $mailingLists[0];
     }
     $subscriptions = array();
     $newSubscriptions = array();
     foreach ($mailingLists as $mailingList) {
         $subscription = $this->getSubscription($recipient, $mailingList);
         if ($subscription) {
             if ($options & self::OPT_INCLUDE_EXISTING) {
                 $subscriptions[] = $subscription;
             }
             // skip when already subscribed
             continue;
         }
         $blacklists = $this->getBlacklistStatus($recipient, $mailingList);
         if (!($options & self::OPT_IGNORE_BLACKLIST) && count($blacklists)) {
             // skip when blacklisted
             continue;
         }
         $recipientType = get_class($recipient);
         $recipientId = $recipient->getId();
         $subscriptionId = md5($recipientType . '::' . $recipientId . '::' . ($mailingList ? $mailingList->getId() : 'global'));
         $subscription = new Subscription();
         $subscription->setId($subscriptionId);
         $subscription->setRecipientType($recipientType);
         $subscription->setRecipientId($recipientId);
         $subscription->setMailingList($mailingList);
         $subscription->setActive((bool) ($options & self::OPT_ACTIVATE));
         $subscription->setActivationToken(md5(mt_rand(-time(), time())));
         $this->entityManager->persist($subscription);
         foreach ($blacklists as $blacklist) {
             $this->entityManager->remove($blacklist);
         }
         $event = new PrepareSubscriptionEvent($subscription, $recipient);
         $this->eventDispatcher->dispatch(SubscriptionEvents::PREPARE_SUBSCRIPTION, $event);
         $subscriptions[] = $subscription;
         $newSubscriptions[] = $subscription;
     }
     if (count($newSubscriptions)) {
         $this->entityManager->flush();
         foreach ($newSubscriptions as $subscription) {
             $event = new SubscribeEvent($subscription, $options);
             $this->eventDispatcher->dispatch(SubscriptionEvents::SUBSCRIBE, $event);
         }
     }
     return $subscriptions;
 }