<?php

declare(strict_types=1);

namespace Drupal\languagewire_translation_provider\api\Models;

/**
 * Abstract model.
 */
abstract class AbstractModel implements ModelInterface {

  /**
   * Required fields.
   *
   * @var array
   */
  protected array $requiredFields = [];

  /**
   * Get all fields.
   */
  public function getAllFields(): array {
    $properties = (new \ReflectionObject($this))->getProperties(\ReflectionProperty::IS_PROTECTED);

    $fields = [];
    foreach ($properties as $property) {
      $fields[$property->getName()] = $property->getType()->getName();
    }

    return $fields;
  }

  /**
   * Set fields.
   */
  public function setFields(array $data): void {
    $allFields = $this->getAllFields();

    foreach ($data as $field => $value) {
      $valueType = gettype($value);
      $valueType = $valueType === 'integer' ? 'int' : $valueType;

      $keyExists = array_key_exists($field, $allFields);

      if ($keyExists && $valueType === 'object' && $allFields[$field] !== $valueType) {
        $valueType = get_class($value);
      }

      if (!$keyExists || ($allFields[$field] !== $valueType)) {
        continue;
      }

      $this->{$field} = $value;
    }
  }

  /**
   * Get required fields.
   */
  public function getRequiredFields(): array {
    return $this->requiredFields;
  }

  /**
   * Check if model has required fields.
   */
  public function hasRequiredFields(): bool {
    $requiredFields = $this->getRequiredFields();

    if (count($requiredFields) === 0) {
      $requiredFields = $this->getAllFields();
    }

    foreach ($requiredFields as $field) {
      if (empty($this->{$field})) {
        return FALSE;
      }
    }

    return TRUE;
  }

  /**
   * Check if model is created.
   */
  public function isCreated(): bool {
    return isset($this->id) && $this->id > 0;
  }

}
