<?php

/**
 * @file
 * Contains install-time code for the Acquia CMS profile.
 */

use Drupal\acquia_cms_common\Facade\ConfigHandlerFacade;
use Drupal\cohesion\Controller\AdministrationController;
use Drupal\cohesion_sync\Event\SiteStudioSyncFilesEvent;
use Drupal\cohesion_sync\EventSubscriber\Import\SiteStudioSyncFilesSubscriber;
use Drupal\Core\Config\FileStorage;
use Drupal\Core\Installer\InstallerKernel;
use Drupal\editor\Entity\Editor;
use Drupal\user\Entity\Role;

/**
 * Implements hook_install().
 *
 * @throws Exception
 */
function acquia_cms_site_studio_install($is_syncing) {
  if (!$is_syncing) {
    // If site studio key available in the environment variables
    // then pick it from there else check for settings overrides.
    $config = \Drupal::config('cohesion.settings');
    $site_studio_api_key = getenv('SITESTUDIO_API_KEY') ?? $config->get('api_key');
    $site_studio_org_key = getenv('SITESTUDIO_ORG_KEY') ?? $config->get('organization_key');

    // Set default theme as cohesion.
    _acquia_cms_site_studio_set_theme();

    // Update cohesion.settings config.
    _acquia_cms_site_studio_update_settings();

    // Set credentials if module being installed independently.
    if (!InstallerKernel::installationAttempted() && $site_studio_api_key && $site_studio_org_key) {
      _acquia_cms_site_studio_set_credentials($site_studio_api_key, $site_studio_org_key);
      if (PHP_SAPI === 'cli') {
        batch_set(AdministrationController::batchAction(TRUE));
      }
    }

    // Update search & search_fallback views display_options's style
    // type as cohesion_layout and option's views_template & master_template
    // if acquia_cms_site_studio module is present else use default one.
    $module_handler = \Drupal::service('module_handler');
    $entity_type_manager = \Drupal::entityTypeManager();
    if ($module_handler->moduleExists('acquia_cms_search')) {
      _acquia_cms_common_update_view_display_options_style('search');
      _acquia_cms_common_update_view_display_options_style('search_fallback');

      // Disable acquia_search view provided by Acquia Search Solrmodule,
      // so that search view provided by acquia_cms_search module can be used
      // which will allow content's related test to pass in isolation.
      $view_storage = $entity_type_manager->getStorage('view');
      if (!empty($view_storage->load('acquia_search'))) {
        $view_storage->load('acquia_search')
          ->setStatus(FALSE)
          ->save();
      }
    }

    // If module getting install stand alone.
    if (!InstallerKernel::installationAttempted()) {
      // Update content views on module install.
      if ($module_handler->moduleExists('acquia_cms_search')) {
        if ($module_handler->moduleExists('acquia_cms_article')) {
          _acquia_cms_common_update_view_display_options_style('articles');
          _acquia_cms_common_update_view_display_options_style('articles_fallback');
        }
        if ($module_handler->moduleExists('acquia_cms_event')) {
          _acquia_cms_common_update_view_display_options_style('events');
          _acquia_cms_common_update_view_display_options_style('events_fallback');
        }
        if ($module_handler->moduleExists('acquia_cms_place')) {
          _acquia_cms_common_update_view_display_options_style('places');
          _acquia_cms_common_update_view_display_options_style('places_fallback');
        }
        if ($module_handler->moduleExists('acquia_cms_person')) {
          _acquia_cms_common_update_view_display_options_style('people', 'default', 'view_tpl_people_grid');
          _acquia_cms_common_update_view_display_options_style('people_fallback');
        }
      }
    }

    // Re-write the editor and filter format config from
    // optional directory since we have done some update to it.
    $module_path = $module_handler->getModule('acquia_cms_site_studio')->getPath();
    $config_optional = $module_path . '/config/optional';
    $source_optional_dir = new FileStorage($config_optional);

    $config_storage = \Drupal::service('config.storage');
    $config_storage->write('editor.editor.cohesion', $source_optional_dir->read('editor.editor.cohesion'));
    $config_storage->write('filter.format.cohesion', $source_optional_dir->read('filter.format.cohesion'));

    // Re-write filter format filtered html.
    $editor_object = $entity_type_manager
      ->getStorage('editor')
      ->load('filtered_html');
    if ($editor_object instanceof Editor) {
      $filters_object = $editor_object->getFilterFormat();
      $filters_instance_ids = $editor_object->getFilterFormat()->filters()->getInstanceIds();
      if (!in_array('black_list_html_tags', $filters_instance_ids)) {
        $filters_object->setFilterConfig('black_list_html_tags', [
          'id' => 'black_list_html_tags',
          'provider' => 'cohesion',
          'status' => FALSE,
          'weight' => '-41',
          'settings' => [],
        ]);
      }
    }

    $module_installer = \Drupal::service('module_installer');
    // Install cohesion_style_guide & sitestudio_config_management module.
    $modules_to_install = [
      'node_revision_delete',
      'responsive_preview',
      'cohesion_style_guide',
      'sitestudio_config_management',
    ];
    $module_installer->install($modules_to_install);

    // Add text format permission to a developer role.
    $role = $entity_type_manager->getStorage('user_role')->load('developer');
    $editors = $entity_type_manager->getStorage('editor')->loadMultiple([
      'cohesion',
      'filtered_html',
      'full_html',
    ]);
    foreach($editors as $editor) {
      $role->grantPermission('use text format ' . $editor->id())->save(TRUE);
    }
  }
}

/**
 * Implements hook_module_preinstall().
 */
function acquia_cms_site_studio_module_preinstall($module) {
  \Drupal::service('acquia_cms_common.utility')->setModulePreinstallTriggered($module);
}

/**
 * Update site studio credentials from environment.
 *
 * @param string $site_studio_api_key
 *   The site studio api key.
 * @param string $site_studio_org_key
 *   The site studio organisation key.
 */
function _acquia_cms_site_studio_set_credentials(string $site_studio_api_key, string $site_studio_org_key) {
  \Drupal::configFactory()->getEditable('cohesion.settings')
    ->set('api_key', $site_studio_api_key)
    ->set('organization_key', $site_studio_org_key)
    ->save(TRUE);
}

/**
 * Set default theme as site studio theme.
 */
function _acquia_cms_site_studio_set_theme() {
  \Drupal::service('theme_installer')->install(['cohesion_theme']);
  \Drupal::configFactory()
    ->getEditable('system.theme')
    ->set('default', 'cohesion_theme')
    ->save();
}

/**
 * Implements hook_uninstall().
 *
 * Reset page field body's label and description to default.
 */
function acquia_cms_site_studio_uninstall($is_syncing) {
  if (!$is_syncing) {
    $config = \Drupal::service('config.factory')->getEditable('field.field.node.page.body');
    if ($config) {
      $config->set('label', 'Body');
      $config->set('description', '');
      $config->save();
    }
  }
}

/**
 * Update Site Studio configuration to use IMCE as Image Browser.
 */
function acquia_cms_site_studio_update_8001() {
  // Using media browser, creates problem if you ever want to export
  // the configuration using the Site Studio package manager
  // as the media entity won't be included as Site Studio
  // does not export content entities as part of packages.
  $config = \Drupal::service('config.factory')->getEditable('cohesion.settings');
  if ($config) {
    $config->set('image_browser.config', [
      'type' => 'imce_imagebrowser',
      'dx8_entity_browser' => 'media_browser',
      'cohesion_media_lib_types' => ['image'],
      'dx8_imce_stream_wrapper' => 'public',
    ]);
    $config->save();
  }
}

/**
 * Install site studio page builder module.
 */
function acquia_cms_site_studio_update_8002() {
  \Drupal::service('module_installer')->install(['sitestudio_page_builder']);
}

/**
 * Install Node Revision Delete module with default configuration.
 *
 * Site Studio 6.8.x has a soft dependency on node_revision_delete module,
 * Install module with default configuration.
 */
function acquia_cms_site_studio_update_8003() {
  // Stale hook_update_n because of node_revision_delete 2.x release.
}

/**
 * Install and update new site studio roles.
 */
function acquia_cms_site_studio_update_8004() {
  $role = Role::load('developer');
  if ($role instanceof Role) {
    $role->set('label', 'Low Code Site Builder');
    $role->save();
  }
}

/**
 * Update and refactor permissions in new site studio.
 */
function acquia_cms_site_studio_update_8005() {
  $roles = [
    'content_administrator',
    'content_editor',
    'content_author',
  ];
  $permissions = [
    'access cpt_cat_general_components cohesion_component_category group',
    'access cpt_cat_hero_components cohesion_component_category group',
    'access cpt_cat_interactive_components cohesion_component_category group',
    'access cpt_cat_media_components cohesion_component_category group',
    'access cpt_cat_template_components cohesion_component_category group',
    'access hlp_cat_general_helpers cohesion_helper_category group',
    'access hlp_cat_interactive_helpers cohesion_helper_category group',
  ];
  $user_role = \Drupal::entityTypeManager()->getStorage('user_role')->loadMultiple($roles);
  foreach ($user_role as $role) {
    user_role_revoke_permissions($role->id(), $permissions);
  }
}

/**
 * Update missing image previews in Site Studio components.
 */
function acquia_cms_site_studio_update_8006() {
  if (\Drupal::config('cohesion.settings')->get('use_dx8')) {
    $modules = [
      'acquia_cms_article' => 'pack_acquia_cms_article',
      'acquia_cms_audio' => 'pack_acquia_cms_audio',
      'acquia_cms_site_studio' => 'pack_acquia_cms_core',
      'acquia_cms_event' => 'pack_acquia_cms_event',
      'acquia_cms_video' => 'pack_acquia_cms_video',
    ];
    $module_handler = \Drupal::service('module_handler');
    foreach ($modules as $key => $module) {
      if ($module_handler->moduleExists($key)) {
        $module_path = \Drupal::service('extension.list.module')->getPath($key);
        $package_file = $module_path . "/config/" . $module . "/sitestudio_package_files.json";
        if (file_exists($package_file)) {
          $files = file_get_contents($package_file);
          $files = json_decode($files, TRUE);
          $event = new SiteStudioSyncFilesEvent($files, $module_path . "/config/" . $module . "/");
          $event_subscriber = new SiteStudioSyncFilesSubscriber(
            \Drupal::entityTypeManager(),
            \Drupal::service('file_system'),
            \Drupal::service('logger.factory'),
          );
          $event_subscriber->handleFileImport($event);
        }
      }
    }
  }
}

/**
 * Added enforced dependency in site studio templates for Acquia CMS SiteStudio.
 *
 * Implements hook_update_N().
 */
function acquia_cms_site_studio_update_8007() {
  $module_path = \Drupal::service('extension.list.module')->getPath('acquia_cms_site_studio');
  $directory = $module_path . '/config/pack_acquia_cms_site_studio';
  if (is_dir($directory)) {
    $files = \Drupal::service('file_system')->scanDirectory($directory, '/.*\.yml$/');
    $base_templates = [
      'cohesion_base_styles.cohesion_base_styles.blockquote',
      'cohesion_base_styles.cohesion_base_styles.body',
      'cohesion_base_styles.cohesion_base_styles.button',
      'cohesion_base_styles.cohesion_base_styles.description',
      'cohesion_base_styles.cohesion_base_styles.heading_1',
      'cohesion_base_styles.cohesion_base_styles.heading_2',
      'cohesion_base_styles.cohesion_base_styles.heading_3',
      'cohesion_base_styles.cohesion_base_styles.heading_4',
      'cohesion_base_styles.cohesion_base_styles.heading_5',
      'cohesion_base_styles.cohesion_base_styles.heading_6',
      'cohesion_base_styles.cohesion_base_styles.html',
      'cohesion_base_styles.cohesion_base_styles.link',
      'cohesion_base_styles.cohesion_base_styles.ordered_list',
      'cohesion_base_styles.cohesion_base_styles.paragraph',
      'cohesion_base_styles.cohesion_base_styles.unordered_list',
      'cohesion_website_settings.cohesion_font_stack.arial',
      'cohesion_templates.cohesion_master_templates.master_template',
      'cohesion_website_settings.cohesion_website_settings.base_unit_settings',
      'cohesion_website_settings.cohesion_website_settings.default_font_settings',
      'cohesion_website_settings.cohesion_website_settings.responsive_grid_settings',
    ];
    foreach ($files as $file) {
      if (!in_array($file->name, $base_templates)) {
        $sitestudio_template = \Drupal::configFactory()->getEditable($file->name);
        if ($sitestudio_template && is_null($sitestudio_template->get('dependencies.enforced.module')) && $sitestudio_template->get('status')) {
          $sitestudio_template->set('dependencies.enforced.module', [
            'acquia_cms_site_studio',
          ]);
          $sitestudio_template->save(TRUE);
        }
      }
    }
  }
}

/**
 * Re-save all cohesion config to recalculate dependencies.
 */
function acquia_cms_site_studio_update_8008() {
  $dx8_no_send_to_api = &drupal_static('dx8_no_send_to_api');
  $dx8_no_send_to_api = TRUE;
  $cohesion_sync_lock = &drupal_static('running_dx8_batch');
  $cohesion_sync_lock = TRUE;

  $ignore_list = [
    'cohesion.settings',
    'cohesion.sync.settings',
    'cohesion_amp.settings',
    'cohesion_devel.settings',
    'cohesion_theme.settings',
  ];

  $configFactory = \Drupal::service('config.factory');
  foreach ($configFactory->listAll('cohesion') as $name) {
    if (in_array($name, $ignore_list)) {
      continue;
    }
    $name_array = explode('.', $name);
    if (isset($name_array[1]) && isset($name_array[2])) {
      if ($name_array[1] == 'cohesion_custom_style_type') {
        $entity = \Drupal::entityTypeManager()->getStorage('custom_style_type')->load($name_array[2]);
      }
      else {
        $entity = \Drupal::entityTypeManager()->getStorage($name_array[1])->load($name_array[2]);
      }
      if ($entity) {
        $entity->save();
      }
    }
  }
}

/**
 * Deletes the Site Studio configurations containing invalid data.
 *
 * Implements hook_update_N().
 */
function acquia_cms_site_studio_update_8009() {
  $module_path = \Drupal::service('extension.list.module')->getPath('acquia_cms_site_studio');
  $directory = $module_path . '/config/pack_acquia_cms_core';
  if (is_dir($directory)) {
    $files = \Drupal::service('file_system')->scanDirectory($directory, '/.*\.yml$/');
    $base_templates = [
      'cohesion_base_styles.cohesion_base_styles.blockquote',
      'cohesion_base_styles.cohesion_base_styles.body',
      'cohesion_base_styles.cohesion_base_styles.button',
      'cohesion_base_styles.cohesion_base_styles.description',
      'cohesion_base_styles.cohesion_base_styles.heading_1',
      'cohesion_base_styles.cohesion_base_styles.heading_2',
      'cohesion_base_styles.cohesion_base_styles.heading_3',
      'cohesion_base_styles.cohesion_base_styles.heading_4',
      'cohesion_base_styles.cohesion_base_styles.heading_5',
      'cohesion_base_styles.cohesion_base_styles.heading_6',
      'cohesion_base_styles.cohesion_base_styles.html',
      'cohesion_base_styles.cohesion_base_styles.link',
      'cohesion_base_styles.cohesion_base_styles.ordered_list',
      'cohesion_base_styles.cohesion_base_styles.paragraph',
      'cohesion_base_styles.cohesion_base_styles.unordered_list',
      'cohesion_website_settings.cohesion_font_stack.arial',
      'cohesion_templates.cohesion_master_templates.master_template',
      'cohesion_website_settings.cohesion_website_settings.base_unit_settings',
      'cohesion_website_settings.cohesion_website_settings.default_font_settings',
      'cohesion_website_settings.cohesion_website_settings.responsive_grid_settings',
    ];
    foreach ($files as $file) {
      if (!in_array($file->name, $base_templates)) {
        $sitestudio_template = \Drupal::configFactory()->getEditable($file->name);
        if ($sitestudio_template && !$sitestudio_template->isNew() && !$sitestudio_template->get("uuid") && !$sitestudio_template->get("id")) {
          $sitestudio_template->delete();
          \Drupal::logger("acquia_cms_site_studio")->notice(
            sprintf("The configuration `%s` deleted containing invalid data.", $file->name)
          );
        }
      }
    }
  }
}

/**
 * Install Node Revision Delete module with default configuration.
 *
 * Implements hook_update_n()
 */
function acquia_cms_site_studio_update_9000() {
  $config_handler = \Drupal::classResolver(ConfigHandlerFacade::class);
  $config_handler->setModuleName('node_revision_delete');
  // Node revision default config settings.
  $default_settings = [
    'defaults' => [
      'amount' => [
        'status' => TRUE,
        'settings' => [
          'amount' => 50,
        ],
      ],
      'created' => [
        'status' => TRUE,
        'settings' => [
          'age' => 12,
        ],
      ],
      'drafts' => [
        'status' => TRUE,
        'settings' => [
          'age' => 12,
        ],
      ],
    ],
  ];
  // Set default node revision delete settings shipped by Acquia CMS.
  $config_handler->processConfigSettings($default_settings);
}

/**
 * Implements hook_update_N().
 *
 *  Update site-studio editor format filter.
 */
function acquia_cms_site_studio_update_9001() {
  $config_data = [
    'settings.plugins.ckeditor5_list' => [
      'properties' => [
        'reversed' => TRUE,
        'startIndex' => TRUE,
      ],
    ],
  ];

  _acquia_cms_common_update_page_configurations('editor.editor.cohesion', $config_data);
}
