<?php

use Drupal\Component\Serialization\Yaml;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\paragraphs\Entity\ParagraphsType;

/**
 * Change configs.
 *
 * @param string $module
 *   The module name.
 * @param array $files
 *   The array of file names to be changed.
 * @param string $path_name
 *   The path name under the config directory.
 */
function _kamihaya_cms_common_change_configs($module, array $files, $path_name) {
  $module_path = \Drupal::service('extension.path.resolver')->getPath('module', $module);
  $config_path = "$module_path/config/$path_name";
  $config_manager = \Drupal::service('config.manager');
  $entity_type_manager = \Drupal::entityTypeManager();

  foreach ($files as $file) {
    $filename = $config_path . '/' . $file;
    $file = file_get_contents($filename);
    if (!$file) {
      continue;
    }
    $value = Yaml::decode($file);
    $type = $config_manager->getEntityTypeIdByName(basename($filename));

    $definition = $entity_type_manager->getDefinition($type);
    $id_key = $definition->getKey('id');

    $id = $value[$id_key];
    /** @var \Drupal\Core\Config\Entity\ConfigEntityStorage $entity_storage */
    $entity_storage = $entity_type_manager->getStorage($type);
    $entity = $entity_storage->load($id);
    if ($entity) {
      $entity = $entity_storage->updateFromStorageRecord($entity, $value);
      $entity->save();
    }
    else {
      $entity = $entity_storage->createFromStorageRecord($value);
      $entity->save();
    }
  }
}

/**
 * Save translation configs.
 *
 * @param string $module
 *   The module name.
 * @param array $files
 *   The array of file names to be changed.
 * @param string $lang_code
 *   The lang code.
 * @param string $path_name
 *   The path name under the config directory.
 */
function _kamihaya_cms_common_save_translation_configs(array $files, $lang_code) {
  $config_manager = \Drupal::service('locale.config_manager');
  $names = [];
  foreach ($files as $file) {
    $names[] = basename($file);
  }
  $config_manager->updateConfigTranslations($names, [$lang_code]);
}

/**
 * Load the config file.
 *
 * @param string $module
 *   The module name.
 * @param string $file
 *   The config file name.
 * @param string $path_name
 *   The path name under the config directory.
 *
 * @return array
 *   The config array.
 */
function _kamihaya_cms_common_load_config_file($module, $file, $path_name) {
  $module_path = \Drupal::service('extension.path.resolver')->getPath('module', $module);
  $config_path = "$module_path/config/$path_name";
  $config_manager = \Drupal::service('config.manager');
  $entity_type_manager = \Drupal::entityTypeManager();

  $filename = $config_path . '/' . $file;
  $file = file_get_contents($filename);
  if (!$file) {
    return [];
  }
  return Yaml::decode($file);
}

/**
 * Add a paragraph to a field.
 *
 * @param string $entity_type
 *   The entity type.
 * @param string $bundle
 *   The bundle.
 * @param string $paragraph_type
 *   The paragraph type.
 * @param string $field
 *   The field name.
 */
function _kamihaya_cms_common_add_paragraph($entity_type, $bundle, $paragraph_type, $field) {
  if (empty(ParagraphsType::load($paragraph_type))) {
    return;
  }
  $field_config = \Drupal::configFactory()->getEditable("field.field.{$entity_type}.{$bundle}.{$field}");
  if (empty($field_config)) {
    return;
  }
  $dependencies = $field_config->get('dependencies.config');
  $target_bundles = $field_config->get('settings.handler_settings.target_bundles');
  $target_bundles_drag_drop = $field_config->get('settings.handler_settings.target_bundles_drag_drop');
  $max_weight = 0;
  foreach($target_bundles_drag_drop ?: [] as $target_bundle) {
    if (!$target_bundle['enabled'] || $target_bundle['weight'] < $max_weight) {
      continue;
    }
    $max_weight = $target_bundle['weight'];
  }

  $paragraph = "paragraphs.paragraphs_type.{$paragraph_type}";
  if (!in_array($paragraph, $dependencies)) {
    $dependencies[] = $paragraph;
  }
  if (!in_array($paragraph_type, $target_bundles)) {
    $target_bundles[$paragraph_type] = $paragraph_type;
  }
  if (!in_array($paragraph_type, $target_bundles_drag_drop)) {
    $target_bundles_drag_drop[$paragraph_type] = [
      'enabled' => TRUE,
      'weight' => ++$max_weight,
    ];
  }

  $field_config->set('dependencies.config', $dependencies);
  $field_config->set('settings.handler_settings.target_bundles', $target_bundles);
  $field_config->set('settings.handler_settings.target_bundles_drag_drop', $target_bundles_drag_drop);
  $field_config->save(TRUE);
}

/**
 * Add a paragraph to a field.
 *
 * @param string $module
 *  The module name.
 * @param string $entity_type
 *   The entity type.
 * @param string $bundle
 *   The bundle.
 * @param array $fields
 *   The field names.
 * @param string $path_name
 *   The path name under the config directory.
 */
function _kamihaya_cms_common_add_fields($module, $entity_type, $bundle, array $fields, $path_name = 'install') {
  $storage_configs = [];
  $install_configs = [];

  foreach($fields as $field) {
    $field_storage = FieldStorageConfig::loadByName($entity_type, $field);
    if ($field_storage) {
      continue;
    }
    $field_storage_file_name = "field.storage.{$entity_type}.{$field}.yml";
    $storage_configs[] = $field_storage_file_name;
  }

  foreach($fields as $field) {
    $field_config_file_name = "field.field.{$entity_type}.{$bundle}.{$field}.yml";
    $install_configs[] = $field_config_file_name;
  }

  if (empty($storage_configs) && empty($install_configs)) {
    return;
  }
  if (!empty($storage_configs)) {
    _kamihaya_cms_common_change_configs($module, $storage_configs, $path_name);
  }
  if (!empty($install_configs)) {
    _kamihaya_cms_common_change_configs($module, $install_configs, $path_name);
    _kamihaya_cms_common_save_translation_configs($install_configs, 'ja');
  }

  foreach($fields as $field) {
    _kamihaya_cms_common_set_field_display($module, $entity_type, $bundle, $field, $path_name);
    _kamihaya_cms_common_set_field_display($module, $entity_type, $bundle, $field, $path_name, FALSE);
  }
}


/**
 * Add a paragraph to a field.
 *
 * @param string $module
 *  The module name.
 * @param string $entity_type
 *   The entity type.
 * @param string $bundle
 *   The bundle.
 * @param string $field
 *   The field name.
 */
function _kamihaya_cms_common_set_field_display($module, $entity_type, $bundle, $field, $path_name = 'install', $form_flg = TRUE) {
  $module_path = \Drupal::service('extension.path.resolver')->getPath('module', $module);
  if ($form_flg) {
    $filename = "$module_path/config/{$path_name}/core.entity_form_display.{$entity_type}.{$bundle}.default.yml";
  }
  else {
    $filename = "$module_path/config/{$path_name}/core.entity_view_display.{$entity_type}.{$bundle}.default.yml";
  }
  $file = file_get_contents($filename);
  $config = !empty($file) ? Yaml::decode($file) : [];

  /** @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface $display_repository */
  $display_repository = \Drupal::service('entity_display.repository');

  $display = $form_flg
    ? $display_repository->getFormDisplay($entity_type, $bundle)
    : $display_repository->getViewDisplay($entity_type, $bundle);
  if (empty($config['content'][$field])) {
    return;
  }
  $display->setComponent($field, $config['content'][$field])->save();
}

/**
 * Add a paragraph type.
 *
 * @param string $paragraph_type
 *   The paragraph type.
 * @param array $fields
 *   The field names.
 * @param array $add_fields
 *   The field of paragraphs to add the new paragraph.
 * @param string $path_name
 *   The path name under the config directory.
 */
function _kamihaya_cms_common_create_paragraph($paragraph_type, array $fields, array $add_fields = [], $path_name = 'install') {
  if (!empty(ParagraphsType::load($paragraph_type))) {
    return;
  }
  $configs = [
    'paragraph' => [
      "paragraphs.paragraphs_type.{$paragraph_type}.yml",
    ],
    'storage' => [],
    'field' => [],
    'entity_display' => [
      "core.entity_form_display.paragraph.{$paragraph_type}.default.yml",
      "core.entity_view_display.paragraph.{$paragraph_type}.default.yml",
    ],
  ];
  foreach($fields as $field) {
    $field_storage = FieldStorageConfig::loadByName('paragraph', $field);
    if ($field_storage) {
      continue;
    }
    $field_storage_file_name = "field.storage.paragraph.{$field}.yml";
    $configs['storage'][] = $field_storage_file_name;
  }

  foreach($fields as $field) {
    $field_config_file_name = "field.field.paragraph.{$paragraph_type}.{$field}.yml";
    $configs['field'][] = $field_config_file_name;
  }

  foreach($configs as $key => $config) {
    _kamihaya_cms_common_change_configs('kamihaya_cms_paragraph_type', $config, $path_name);
    if ($key === 'storage' || $key === 'entity_display') {
      continue;
    }
    _kamihaya_cms_common_save_translation_configs($config, 'ja');
  }

  foreach($add_fields ?: [] as $paragraph_name => $field) {
    $field_config = \Drupal::configFactory()->getEditable("field.field.paragraph.{$paragraph_name}.{$field}");
    if (empty($field_config)) {
      return;
    }
    $dependencies = $field_config->get('dependencies.config');
    $target_bundles = $field_config->get('settings.handler_settings.target_bundles');
    $target_bundles_drag_drop = $field_config->get('settings.handler_settings.target_bundles_drag_drop');
    $max_weight = 0;
    foreach($target_bundles_drag_drop ?: [] as $target_bundle) {
      if (!$target_bundle['enabled'] || $target_bundle['weight'] < $max_weight) {
        continue;
      }
      $max_weight = $target_bundle['weight'];
    }

    $paragraph = "paragraphs.paragraphs_type.{$paragraph_type}";
    if (!empty($dependencies) && !in_array($paragraph, $dependencies)) {
      $dependencies[] = $paragraph;
    }
    if (!empty($target_bundles) && !in_array($paragraph_type, $target_bundles)) {
      $target_bundles[$paragraph_type] = $paragraph_type;
    }
    if (!empty($target_bundles_drag_drop) && !in_array($paragraph_type, $target_bundles_drag_drop)) {
      $target_bundles_drag_drop[$paragraph_type] = [
        'enabled' => TRUE,
        'weight' => ++$max_weight,
      ];
    }

    $field_config->set('dependencies.config', $dependencies);
    $field_config->set('settings.handler_settings.target_bundles', $target_bundles);
    $field_config->set('settings.handler_settings.target_bundles_drag_drop', $target_bundles_drag_drop);
    $field_config->save(TRUE);
  }
}
