<?php

namespace Drupal\mymodule\Plugin\rest\resource;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use \Drupal\node\Entity\Node;
use \Drupal\Core\Cache\Cache;


/**
 * Provides a resource to get people
 *
 * @RestResource(
 *   id = "get_people",
 *   label = @Translation("Get peoples"),
 *   uri_paths = {
 *     "canonical" = "/api/people",
 *     "create" = "/api/people/test"
 *   }
 * )
 */
class GetPeoples extends ResourceBase {

  public function get() {
    $query = \Drupal::request()->query->get('page');

    $cache = new CacheableMetadata();
    $cache->setCacheMaxAge(900);
    $cache->addCacheContexts(['url.query_args']);

    if (empty($query)) {
      $query = 1;
    }

    $nodes = \Drupal::entityTypeManager()
      ->getStorage('node')
      ->loadByProperties([
        'type' => 'people'
      ]);
    $nodes = array_values($nodes);
    $count_nodes = count($nodes);
    $limit_page = (int)ceil($count_nodes/10);
    $i = 0;
    $response['count'] = $count_nodes;
    $host = \Drupal::request()->getHost();
    $host = 'http://' . $host . '/api/people?page=';

    if ($query <= $limit_page) {
      if ($count_nodes > 10 and (empty($query) or $query == 1)) {
        $response['next'] = $host . '2';
        $response['previous'] = null;
      } elseif ($query != $limit_page) {
        $response['next'] = $host . ($query + 1);
        $response['previous'] = $host . ($query - 1);
      } else {
        $response['next'] = null;
        $response['previous'] = $host . ($limit_page - 1);
      }
    } else {
      return new ResourceResponse('404 error');
    }

    if (!empty($query)) {
      $i = ($query * 10) - 10;
    }

    if ($query == $limit_page) {
      $last_index = count($nodes);
    } else {
      $last_index = $query * 10;
    }
    $response['results'] = [];
    for ($i; $i < $last_index; $i++) {
      $node = $nodes[$i];
      unset($result);
      if (count($response['results']) < 11) {
        $result['name'] = $node->label();
        $result['height'] = $this->getFieldValue('field_height', $node);
        $result['mass'] = $this->getFieldValue('field_mass', $node);
        $result['hair_color'] = $this->getFieldValue('field_hair_color', $node);
        $result['skin_color'] = $this->getFieldValue('field_skin_color', $node);
        $result['eye_color'] = $this->getFieldValue('field_eye_color', $node);
        $result['birth_year'] = $this->getFieldValue('field_birth_year', $node);
        $result['gender'] = $this->getFieldValue('field_gender', $node);

        $node_homeworld = $node->field_homeworld->referencedEntities();
        $node_homeworld = $node_homeworld[0];
        $cache->addCacheableDependency($node_homeworld);
        $result['homeworld']['id'] = $node_homeworld->id();
        $result['homeworld']['label'] = $node_homeworld->label();

        $result['films'][] = $this->fillReference('films', $node);
        $result['species'][] = $this->fillReference('species', $node);
        $result['vehicles'][] = $this->fillReference('vehicles', $node);
        $result['starships'][] = $this->fillReference('starships', $node);

        $films = $node->field_films->referencedEntities();
        foreach ($films as $film) {
          $cache->addCacheableDependency($film);
        }
        $species = $node->field_species->referencedEntities();
        foreach ($species as $specie) {
          $cache->addCacheableDependency($specie);
        }
        $vehicles = $node->field_vehicles->referencedEntities();
        foreach ($vehicles as $vehicle) {
          $cache->addCacheableDependency($vehicle);
        }
        $starships = $node->field_starships->referencedEntities();
        foreach ($starships as $starship) {
          $cache->addCacheableDependency($starship);
        }

        $created = $node->get('created')->getValue();
        $created = date("Y-m-d H:i:s", (int)$created[0]['value']);
        $result['created'] = $created;

        $changed = $node->get('changed')->getValue();
        $changed = date("Y-m-d H:i:s", (int)$changed[0]['value']);
        $result['changed'] = $changed;

        $url = $node->toUrl()->setAbsolute()->toString(TRUE);
        $result['url'] = $url->getGeneratedUrl();

        $response['results'][] = $result;
        $cache->addCacheableDependency($node);
      }
    }
    $resource = new ResourceResponse($response, 200);

    $resource->addCacheableDependency($cache);
    $resource->setPublic();
    $resource->setMaxAge(900);
    return $resource;
  }

  public function post($data) {
    if ($data['swapi_id']) {
      if ($this->checkNode($data['swapi_id'])) {
        return new ResourceResponse(['Нода с таким swapi_id уже существует!']);
      }
      if (isset($data['name'])) {
        $node = Node::create([
          'type' => 'people',
          'title' => $data['name']
        ]);
        foreach($data as $key => $value) {
          if ($key == 'name') {
            continue;
          }
          $field_name = "field_" . $key;
          if ($node->hasField($field_name)) {
            $node->set($field_name, $value);
          } else {
            return new ResourceResponse("$field_name данное поле не найдено");
          }
        }
        $node->save();
        return new ResourceResponse("Нода с названием {$data['name']} успешно создана");
      } else {
        return new ResourceResponse(['Укажите обязательное поле name!']);
      }
    } else {
      return new ResourceResponse(['Укажите обязательное поле swapi_id!']);
    }
  }

  public function fillReference($nameAttr, $node) {
    $field_name = "field_" . $nameAttr;

    $items = $node->$field_name->referencedEntities();
    if (!empty($items)) {
      foreach ($items as $item) {
        $obj = [
          'id' => $item->id(),
          'label' => $item->label(),
        ];
        $result[$nameAttr][] = $obj;
      }
    } else {
      $result[$nameAttr][] = null;
    }
    return $result[$nameAttr];
  }

  public function getFieldValue($field_name, $node) {
    $value = $node->get($field_name)->getValue();
    $value = $value[0]['value'];
    return $value;
  }

  public function checkNode($swapi_id) {
    $nodes = \Drupal::entityTypeManager()
      ->getStorage('node')
      ->loadByProperties([
        'type' => 'people',
        'field_swapi_id' => $swapi_id,
      ]);

    if (!empty($nodes)) {
      return true;
    }
    return false;
  }

}
