<?php

/**
 * @file
 * Contains heartbeat.module.
 */


use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormState;
use Drupal\node\NodeInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Entity;
use Drupal\Core\Database\Database;
use Drupal\heartbeat\Entity\FILE_FIELD;
use Drupal\heartbeat\Entity\Heartbeat;
use GuzzleHttp\Exception\RequestException;
use Drupal\heartbeat\Entity\HeartbeatType;
use Drupal\heartbeat\Ajax\UpdateFeedCommand;



/**
 * Implements hook_help().
 */
function heartbeat_help($route_name, RouteMatchInterface $route_match) {
  switch ($route_name) {
    // Main module help for the heartbeat module.
    case 'help.page.heartbeat':
      $output = '';
      $output .= '<h3>' . t('About') . '</h3>';
      $output .= '<p>' . t('Heartbeat for Drupal 8') . '</p>';
      return $output;

    default:
  }
}


/**
 * Implements hook_theme().
 */
function heartbeat_theme() {
  $theme = [];
  $theme['heartbeat'] = array(
    'render element' => 'elements',
    'file' => 'heartbeat.page.inc',
    'template' => 'heartbeat',
  );
  $theme['heartbeat_content_add_list'] = [
    'render element' => 'content',
    'variables' => ['content' => NULL],
    'file' => 'heartbeat.page.inc',
  ];
  $theme['heartbeat_stream'] = [
    'variables' => array(
      'messages' => NULL,
      'zilla' => 2,
    )
  ];
  return $theme;
}

/**
 * Implements hook_theme_suggestions_HOOK().
 */
function heartbeat_theme_suggestions_heartbeat(array $variables) {
  $suggestions = array();
  $entity = $variables['elements']['#heartbeat'];
  $sanitized_view_mode = strtr($variables['elements']['#view_mode'], '.', '_');

  $suggestions[] = 'heartbeat__' . $sanitized_view_mode;
  $suggestions[] = 'heartbeat__' . $entity->bundle();
  $suggestions[] = 'heartbeat__' . $entity->bundle() . '__' . $sanitized_view_mode;
  $suggestions[] = 'heartbeat__' . $entity->id();
  $suggestions[] = 'heartbeat__' . $entity->id() . '__' . $sanitized_view_mode;
  return $suggestions;
}




/**
 * Implements hook_entity_insert().
 */
function heartbeat_entity_insert(EntityInterface $entity) {
  $bundleSaved = false;
  switch (true) {
    case $entity instanceof \Drupal\node\Entity\Node:

      $user = $entity->getOwner();
      $media = HeartBeat::mediaFieldTypes($entity->getFields());

      if ($entity->id() && $user->isAuthenticated()) {

        $heartbeatTypeService = \Drupal::service('heartbeat.heartbeattype');
        $tokenService = \Drupal::service('token');

        foreach ($heartbeatTypeService->getTypes() as $type) {

          $heartbeatTypeEntity = $heartbeatTypeService->load($type);

          if ($heartbeatTypeEntity->getMainEntity() == 'node') {

            $arguments = json_decode($heartbeatTypeEntity->getArguments());

            foreach ($arguments as $key => $argument) {
              $variables[$key] = $argument;
            }

            $preparsedMessageString = strtr($heartbeatTypeEntity->getMessage(), $variables);

            $entities = array(
              'node' => $entity,
              'user' => $user,
            );

            if ($entity->bundle() === $heartbeatTypeEntity->getBundle()
              &&
              array_key_exists($heartbeatTypeEntity->getBundle(), $heartbeatTypeService->getEntityBundles($entity->getEntityType()))
            ) {

              $heartbeatMessage = Heartbeat::buildMessage($tokenService, $preparsedMessageString, $entities, $entity->getEntityTypeId(), $media);


              $heartbeatActivity = Heartbeat::create([
                'type' => $heartbeatTypeEntity->id(),
                'uid' => $user->id(),
                'nid' => $entity->id(),
                'name' => 'Dev Test',
              ]);

              $heartbeatActivity->setMessage($heartbeatMessage);
              if ($heartbeatActivity->save()) {
                $bundleSaved = true;
              }
              continue;
            } else if ($heartbeatTypeEntity->getBundle() === null || trim($heartbeatTypeEntity->getBundle()) === '') {

              $heartbeatMessage = Heartbeat::buildMessage($tokenService, $preparsedMessageString, $entities, $entity->getEntityTypeId(), $media);

              //      $translatedMessage = t($messageTemplate);

              $heartbeatActivity = Heartbeat::create([
                'type' => $heartbeatTypeEntity->id(),
                'uid' => $user->id(),
                'nid' => $entity->id(),
                'name' => 'Dev Test',
                'status' => !$bundleSaved ? 1 : 0,
              ]);

              $heartbeatActivity->setMessage($heartbeatMessage);
              $heartbeatActivity->save();
            } else {
              continue;
            }
          }
        }
        updateFeeds();
      }
      break;
    case $entity instanceof \Drupal\user\Entity\User:
//      $userService = \Drupal\User\Entity\user

      break;
    case $entity instanceof \Drupal\flag\Entity\Flag:
      break;

    case $entity instanceof \Drupal\statusmessage\Entity\Status:

      $user = \Drupal\user\Entity\User::load($entity->get('uid')->getValue()[0]['target_id']);
      $heartbeatTypeService = \Drupal::service('heartbeat.heartbeattype');
      $tokenService = \Drupal::service('token');

      heartbeat_handle_entity($entity, $tokenService, $heartbeatTypeService, $user, 'status');

      break;

  }
}


function heartbeat_handle_entity($entity, $tokenService, $heartbeatTypeService, $user, $mainEntity) {
  $bundleSaved = false;
  if ($entity->id() && $user->isAuthenticated()) {

    $media = HeartBeat::mediaFieldTypes($entity->getFields());

    foreach ($heartbeatTypeService->getTypes() as $type) {

      $heartbeatTypeEntity = $heartbeatTypeService->load($type);

      if ($heartbeatTypeEntity->getMainEntity() == $mainEntity) {

        $arguments = json_decode($heartbeatTypeEntity->getArguments());

        foreach ($arguments as $key => $argument) {
          $variables[$key] = $argument;
        }

        $preparsedMessageString = strtr($heartbeatTypeEntity->getMessage(), $variables);

        $entities = array(
          $mainEntity => $entity,
          'user' => $user,
        );

        if ($entity->bundle() === $heartbeatTypeEntity->getBundle()
          &&
          array_key_exists($heartbeatTypeEntity->getBundle(), $heartbeatTypeService->getEntityBundles($entity->getEntityType()))
        ) {

          $heartbeatMessage = Heartbeat::buildMessage($tokenService, $preparsedMessageString, $entities, $entity->getEntityTypeId(), $media);


          $heartbeatActivity = Heartbeat::create([
            'type' => $heartbeatTypeEntity->id(),
            'uid' => $user->id(),
            'nid' => $entity->id(),
            'name' => 'Dev Test',
          ]);

          $heartbeatActivity->setMessage($heartbeatMessage);
          if ($heartbeatActivity->save()) {
            $bundleSaved = true;
          }
          continue;
        } else if ($heartbeatTypeEntity->getBundle() === null || trim($heartbeatTypeEntity->getBundle()) === '') {

          $heartbeatMessage = Heartbeat::buildMessage($tokenService, $preparsedMessageString, $entities, $entity->getEntityTypeId(), $media);

          //      $translatedMessage = t($messageTemplate);

          $heartbeatActivity = Heartbeat::create([
            'type' => $heartbeatTypeEntity->id(),
            'uid' => $user->id(),
            'nid' => $entity->id(),
            'name' => 'Dev Test',
            'status' => !$bundleSaved ? 1 : 0,
          ]);

          $heartbeatActivity->setMessage($heartbeatMessage);
          $heartbeatActivity->save();

        } else {
          continue;
        }

      }
    }
  }
  updateFeeds();

}

function updateFeeds() {
  $configFactory = \Drupal::service('config.factory');
  $updateFeedConfig = $configFactory->getEditable('heartbeat_update_feed.settings');
  $feedConfig = $configFactory->get('heartbeat_feed.settings');

//  $form = \Drupal::formBuilder()->getForm('\Drupal\heartbeat\Form\HeartbeatUpdateFeedForm');

//  $form_state = new FormState();
//  $form_state->set('timestamp', $updateFeedConfig->get('timestamp'));

//  \Drupal::formBuilder()->submitForm('\Drupal\heartbeat\Form\HeartbeatUpdateFeedForm', $form_state);

//  $errors = $form_state->getErrors();


  //  $updateFeedConfig->set('update', true)->save();
//  $feedUpdateConfig = new stdClass();
//  $feedUpdateConfig->feed = $feedConfig->get('message');
//  $feedUpdateConfig->update = true;
//  $feedUpdateConfig->timestamp = $updateFeedConfig->get('timestamp');


//  $curlQuery = '/heartbeat/update_feed/' . $updateFeedConfig->get('timestamp');
  //Set options for the curl request



//  $curlOptions = array(
//    'headers' => array(
//      'X-DataSource-Auth' => 'a',
//      'method' => 'POST',
//    ),
//  );
//  //Perform the request and decode the results
//  $result = chr_curl_http_request($curlQuery, $curlOptions);

}
//public function saveHeartbeatMessage($entity, $tokenService, $preparsedMessageString, $entities, $entityTypeId, $media) {
//  $heartbeatMessage = Heartbeat::buildMessage($tokenService, $preparsedMessageString, $entities, $entity->getEntityTypeId(), $media);
//
//
//  $heartbeatActivity = Heartbeat::create([
//    'type' => $heartbeatTypeEntity->id(),
//    'uid' => $user->id(),
//    'nid' => $entity->id(),
//    'name' => 'Dev Test',
//  ]);
//
//  $heartbeatActivity->setMessage($heartbeatMessage);
//  $heartbeatActivity->save();
//}


/**
 * Implements hook_ajax_render_alter().
 */
function heartbeat_ajax_render_alter(array &$data) {

  $nullll = 'null';

  $muhData = $data;

  if ($data !== null) {

    $saysomething = 'here';


  }
}

/**
 * Implements hook_cron().
 */
function heartbeat_cron() {
  $friendship = false;
  //Iterate over the Heartbeat Types and ensure that the weight of bundle-specific types are lower than that of their
  //parent type. This will allow us to ensure Bundle specific types end up being published as opposed to
  //Types which represent all content types
  $heartbeatTypes = \Drupal::service('entity.query')->get('heartbeat_type')->condition('mainentity', 'node')->execute();


  foreach($heartbeatTypes as $heartbeatType) {

    $entity = \Drupal::service('entity_type.manager')->getStorage('heartbeat_type')->load($heartbeatType);

    if ($entity->getBundle() === null) {
      $entity->setWeight(99);
      $entity->save();
    } else {
      $entity->setWeight(0);
      $entity->save();
    }

    if ($entity->getMainEntity() === 'flagging') {
      $friendship = true;
      $flagService = \Drupal::service('flag');
      foreach ($flagService->getAllFlags('user') as $flag) {
        if ($flag->id() === 'friendship') {
          $flaggings = \Drupal\Core\Database\Database::getConnection()->select('flagging', 'f')
            ->fields('f', array('entity_id', 'uid'))
            ->condition('flag_id', $flag->id())->execute();

          foreach ($flaggings->fetchAll() as $flagging) {
            $friendship = \Drupal\Core\Database\Database::getConnection()->select('heartbeat_friendship', 'hf')
              ->fields(array('status'))
              ->condition('uid', $flagging->uid)
              ->condition('uid_target', $flagging->entity_id)
              ->execute();

            if ($friendship = $friendship->fetchObject()) {
              $status = $friendship->status;

              $revFriendship = \Drupal\Core\Database\Database::getConnection()->select('heartbeat_friendship', 'hf')
                ->fields(array('status'))
                ->condition('uid', $flagging->entity_id)
                ->condition('uid_target', $flagging->uid)
                ->execute();

              if ($revFriendship = $revFriendship->fetchObject()) {
                $revStatus = $revFriendship->status;
              }

            }
          }
        }
      }
    }
//      $entityQuery = \Drupal::service('entity.query')->get('flag

//    foreach ($flagService->)
  }
  heartbeat_friendship_maintenance();
}

function heartbeat_friendship_maintenance() {
  $flagService = \Drupal::service('flag');
  $entityTypeManager = \Drupal::service('entity_type.manager');
  $flag = $flagService->getFlagById('friendship');

  $friendships = Database::getConnection()->select("heartbeat_friendship", "hf")
    ->fields('hf', array('status', 'uid', 'uid_target'))
    ->execute();

  foreach ($friendships->fetchAll() as $friendship) {
    $revFriendship = Database::getConnection()->select('heartbeat_friendship', 'hf')
      ->fields('hf', array('status'))
      ->condition('uid', $friendship->uid_target)
      ->condition('uid_target', $friendship->uid)
      ->execute();

    $revFriendResult = $revFriendship->fetchField();

    if ($revFriendResult > -2) {
      if ($revFriendResult !== $friendship->status) {
        $update = Database::getConnection()->update('heartbeat_friendship')
          ->fields(array(
              ':status' => 1,
            )
          )
          ->condition('uid', $friendship->uid)
          ->condition('uid_target', $friendship->uid_target);
        if ($updated = !$update->execute()) {
          \Drupal::logger('Heartbeat Cron')->error('Could not update status for friendship');
        }
      }

      if ($revFriendResult === $friendship->status ||
        $updated) {

        $userEntity = $entityTypeManager->getStorage('user')->load($friendship->uid);
        $userTargetEntity = $entityTypeManager->getStorage('user')->load($friendship->uid_target);
        $flaggingFound = false;

        foreach ($flagService->getEntityFlaggings($flag, $userTargetEntity) as $flagging) {
          $flOwner = $flagging->getOwnerId();
          $usId = $userEntity->id();
          $flaggableId = $flagging->getFlaggableId();
          //TODO ownerId and entity Id seem to be reversed.

          if ($flagging->getOwnerId() == $userEntity->id() && $flagging->getFlaggableId() == $friendship->uid_target) {
            $flaggingFound = true;
            break;
          }
        }

        if (!$flaggingFound) {
          $flagging = $flagService->flag($flag, $userTargetEntity, $userEntity);
        }

        $flaggingReverseFound = false;

        foreach ($flagService->getEntityFlaggings($flag, $userEntity) as $flagging) {
          if ($flagging->getOwnerId() == $userTargetEntity->id() && $flagging->getFlaggableId() == $friendship->uid) {
            $flaggingReverseFound = true;
            break;
          }
        }

        if (!$flaggingReverseFound) {
          $flagging = $flagService->flag($flag, $userEntity, $userTargetEntity);
        }
        //TODO update flagging values or create flaggings

      }
    } else if ($friendship->status === 1) {
      //TODO Add reverse friendship
      $insertReverse = Database::getConnection()->insert('heartbeat_friendship')
        ->fields([
          'uid' => $friendship->uid_target,
          'uid_target' => $friendship->uid,
          'created' => time(),
          'status' => 1
        ]);

      if ($insertReverse->execute()) {

        if ($friendship->status < 1) {
          $updateFriendship = Database::getConnection()->update('heartbeat_friendship')
            ->fields(array(
              'status' => 1,
            ))
            ->condition('uid', $friendship->uid)
            ->condition('uid_target', $friendship->uid_target);
          if (!$updateFriendship->execute()) {
            \Drupal::logger('Friendship update failed');
          }
        }
      } else {
        \Drupal::logger('Heartbeat')->debug('Unable to insert or update for User with ID %id', ['%id' => $friendship->uid]);
      }
    } else {
      //TODO figure out how to set friendship pending
    }
  }
}



/**
 * Implements hook_cron().
 */
function heartbeat_update_type_weight() {
  //Iterate over the Heartbeat Types and ensure that the weight of bundle-specific types are lower than that of their
  //parent type. This will allow us to ensure Bundle specific types end up being published as opposed to
  //Types which represent all content types
  $heartbeatTypes = \Drupal::service('entity.query')->get('heartbeat_type')->condition('mainentity', 'node')->execute();

  if (count($heartbeatTypes) > 1) {
    foreach($heartbeatTypes as $heartbeatType) {

      $entity = \Drupal::service('entity_type.manager')->getStorage('heartbeat_type')->load($heartbeatType);

      if ($entity->getBundle() === null) {
        $entity->setWeight(99);
        $entity->save();
      } else {
        $entity->setWeight(0);
        $entity->save();
      }

    }
  }
}


/**
 * Implements hook_page_attachments_alter().
 */
function heartbeat_page_attachments_alter(array &$attachments) {

  $jigganull  = 'naul';
  $jiagganull  = 'naul';
  $mattachments = $attachments;

  $attachments['#attached']['library'][] = 'heartbeat/heartbeat';
}