<?php

/**
 * @file
 * Functions to support theming in the Droopler theme.
 */

use Drupal\Core\Link;
use Drupal\Core\Template\Attribute;
use Drupal\node\Entity\Node;
use Drupal\node\NodeInterface;

/**
 * Implements hook_preprocess_HOOK() for HTML document templates.
 *
 * Adds body classes if certain regions have content.
 */
function droopler_theme_preprocess_html(&$variables) {
  // Add page specific info to <body>.
  $variables['path_info']['args'] = FALSE;
  $path = \Drupal::service('path.current')->getPath();
  $path = ltrim($path, '/');
  $path_args = explode('/', $path);
  if (isset($path_args[0]) && isset($path_args[1]) && ($path_args[0] == 'node') && (is_numeric($path_args[1]))) {
    $variables['attributes']['class'][] = 'page-node-' . $path_args[1];

    // Add node type when viewing a node revision.
    if (isset($path_args[2]) && $path_args[2] == 'revisions') {
      $variables['node_type'] = Node::load($path_args[1])->getType();
    }
  }
  if (isset($path_args[0]) && isset($path_args[1]) && ($path_args[0] == 'user')) {
    $variables['attributes']['class'][] = 'page-user-' . $path_args[1];
  }
  // Detect browser and attach browser specific libraries.
  $browser = detect_browser();
  if (!empty($browser) && $browser === 'Internet Explorer') {
    $variables['#attached']['library'][] = 'droopler_theme/ie-compatibility';
  }
}

/**
 * Implements hook_preprocess_HOOK() for page templates.
 */
function droopler_theme_preprocess_page(&$variables) {
  $layout = droopler_theme_get_page_layout($variables);

  // Define header type variables.
  $variables['header_layout'] = $layout;
  $variables['is_disabled_header'] = $layout === 'header_disabled';
  $variables['is_cta_header'] = $layout === 'header_with_cta';

  // Define default classes for containers.
  $page_attributes = [
    'class' => ['page-wrapper'],
    'id' => ['page-wrapper'],
  ];
  $navbar_top_attributes = [
    'class' => ['navbar123'],
    'id' => ['navbar-top'],
  ];
  $navbar_attributes = [
    'class' => ['navbar'],
    'id' => ['navbar-main'],
  ];
  $main_attributes = [
    'class' => ['container', 'py-4'],
    'id' => ['main'],
  ];
  $main_content_attributes = [
    'class' => ['col-12', 'main-content'],
  ];
  $section_attributes = [
    'class' => ['section'],
  ];
  $content_attributes = [
    'class' => ['main-content', 'col-md-12'],
    'id' => ['content'],
    'role' => ['main'],
  ];

  if (droopler_theme_is_special_route()) {
    $main_attributes['class'] = ['container-fluid'];
    $main_content_attributes['class'] = ['main-content'];
  }

  // Declare attributes.
  $variables['page_attributes'] = new Attribute($page_attributes);
  $variables['navbar_top_attributes'] = new Attribute($navbar_top_attributes);
  $variables['navbar_attributes'] = new Attribute($navbar_attributes);
  $variables['main_attributes'] = new Attribute($main_attributes);
  $variables['main_content_attributes'] = new Attribute($main_content_attributes);
  $variables['section_attributes'] = new Attribute($section_attributes);
  $variables['content_attributes'] = new Attribute($content_attributes);

  // Add attributes that depends of the page layout.
  if ($variables['is_cta_header']) {
    $variables['page_attributes']->addClass(['landing-page-header']);
    $variables['section_attributes']->addClass(['header-section']);
  }

  $footer_regions = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth'];
  $filled_regions = [];
  foreach ($footer_regions as $region) {
    if (!empty($variables['page']['footer_' . $region])) {
      $filled_regions[] = 'footer_' . $region;
    }
  }
  $variables['filled_regions'] = $filled_regions;
}

/**
 * Implements hook_preprocess_HOOK() for maintenance-page.html.twig.
 */
function droopler_theme_preprocess_maintenance_page(&$variables) {
  // By default, site_name is set to Drupal if no db connection is available
  // or during site installation.
  if (!$variables['db_is_active']) {
    $variables['site_name'] = 'Droopler';
  }

  // Droopler has custom styling for the maintenance page.
  $variables['#attached']['library'][] = 'droopler_theme/maintenance_page';
}

/**
 * Implements hook_preprocess_HOOK() for form_element.
 */
function droopler_theme_preprocess_form_element(&$variables) {
  if (!isset($variables['label']['#title'])) {
    $variables['input_title'] = NULL;
  }
  elseif (is_object($variables['label']['#title'])) {
    if (method_exists($variables['label']['#title'], 'render')) {
      $variables['input_title'] = $variables['label']['#title']->render();
    }
    else {
      $variables['input_title'] = $variables['label']['#title'];
    }
  }
  else {
    $variables['input_title'] = $variables['label']['#title'];
  }
  if (!empty($variables['input_title'])) {
    $allowed_tags = '<p><a><img><span><blockquote><b><strong><i><em><u>';
    $variables['input_title'] = strip_tags($variables['input_title'], $allowed_tags);
  }
  if (isset($variables['element']['#attributes'])) {
    $variables['input_attributes'] = new Attribute($variables['element']['#attributes']);
  }
}

/**
 * Implements hook_preprocess_menu_local_task().
 */
function droopler_theme_preprocess_menu_local_task(&$variables) {
  $link = $variables['element']['#link'];
  $url = $link['url'];
  $options = $url->getOptions();
  $url->setOptions($options + ($link['localized_options'] ?? []));
  $variables['item'] = Link::fromTextAndUrl($link['title'], $url);
}

/**
 * Implements hook_theme_suggestions_HOOK_alter() for links templates.
 */
function droopler_theme_theme_suggestions_links_alter(array &$suggestions, array $variables) {
  // @todo get from core a variable to flag inline links.
  if (in_array('inline', $variables['attributes']['class'])) {
    $suggestions[] = 'links__inline';
  }
}

/**
 * Implements hook_theme_suggestions_HOOK_alter() for form templates.
 */
function droopler_theme_theme_suggestions_form_alter(array &$suggestions, array $variables) {
  if ($variables['element']['#form_id'] == 'search_block_form') {
    $suggestions[] = 'form__search_block_form';
  }
  if ($variables['element']['#form_id'] == 'node_form') {
    $suggestions[] = 'node_edit_form';
  }
}

/**
 * Implements hook_theme_suggestions_page_alter().
 */
function droopler_theme_theme_suggestions_page_alter(array &$suggestions, array &$variables) {
  $route_match = \Drupal::routeMatch();
  if ($route_match->getRouteName() == 'entity.taxonomy_term.canonical') {
    $storage = \Drupal::service('entity_type.manager')
      ->getStorage('taxonomy_term');
    $tid = $route_match->getRawParameter('taxonomy_term');
    $term = $storage->load($tid);
    $suggestions[] = 'page__taxonomy__term__' . $term->bundle();
  }

  // Theme suggestions for pages derived from the views.
  $system_main = $variables['page']['content']['system_main'] ?? [];
  if (isset($system_main['#view_display_plugin_id']) && $system_main['#view_display_plugin_id'] == 'page') {
    $suggestions[] = 'page__views__' . $system_main['#view_id'];
  }
}

/**
 * Implements hook_preprocess_input().
 */
function droopler_theme_preprocess_input(&$variables) {
  // For submit elements.
  if ($variables['element']['#type'] == 'submit') {
    // Omit class manipulation if is geysir modal.
    if (\Drupal::service('d_geysir.utility.modal_detector')->isGeysirModalRequest()) {
      return;
    }

    // If button has some class.
    if (is_object($variables['attributes'])) {
      $classes = $variables['attributes']['class']->value();
    }
    else {
      $classes = $variables['attributes']['class'] ?? [];
    }

    // Skip when no-bootstrap class is set.
    if (in_array('no-bootstrap', $classes)) {
      return;
    }

    // If there is no .btn class - add it.
    if (!in_array('btn', $classes)) {
      $classes[] = 'btn';
    }

    // If there is no .btn-{type} class.
    $btn_styles = [
      'btn-primary',
      'btn-secondary',
      'btn-success',
      'btn-warning',
      'btn-danger',
      'btn-link',
    ];
    if (empty(array_intersect($btn_styles, $classes))) {
      $classes[] = 'btn-primary';
    }

    // Remove default .button class.
    $key = array_search('button', $classes);
    if ($key !== FALSE) {
      unset($classes[$key]);
    }

    if (!is_object($variables['attributes'])) {
      $variables['attributes']['class'] = $classes;
      $variables['attributes'] = new Attribute($variables['attributes']);
    }
    else {
      $variables['attributes']->removeAttribute('class');
      $variables['attributes']->addClass($classes);
    }
  }
}

/**
 * Implements hook_preprocess_HOOK() for pager.
 */
function droopler_theme_preprocess_pager(&$variables) {
  // Next.
  if (isset($variables['items']['next'])) {
    $variables['items']['next']['attributes'] = new Attribute([
      'class' => ['page-link'],
    ]);
  }
  // Previous.
  if (isset($variables['items']['previous'])) {
    $variables['items']['previous']['attributes'] = new Attribute([
      'class' => ['page-link'],
    ]);
  }
  // First.
  if (isset($variables['items']['first'])) {
    $variables['items']['first']['attributes'] = new Attribute([
      'class' => ['page-link'],
    ]);
  }
  // Last.
  if (isset($variables['items']['last'])) {
    $variables['items']['last']['attributes'] = new Attribute([
      'class' => ['page-link'],
    ]);
  }
  // Pages.
  if (!empty($variables['items']['pages'])) {
    foreach ($variables['items']['pages'] as &$page) {
      $page['attributes'] = new Attribute([
        'class' => ['page-link'],
      ]);
    }
  }
}

/**
 * Implements hook_preprocess_HOOK() for mini pager.
 */
function droopler_theme_preprocess_views_mini_pager(&$variables) {
  // Next.
  if (isset($variables['items']['next'])) {
    $variables['items']['next']['attributes'] = new Attribute([
      'class' => ['page-link'],
    ]);
  }
  // Previous.
  if (isset($variables['items']['previous'])) {
    $variables['items']['previous']['attributes'] = new Attribute([
      'class' => ['page-link'],
    ]);
  }
}

/**
 * Implements hook_preprocess_field() for HTML document templates.
 */
function droopler_theme_preprocess_field(&$variables) {
  if ($variables['field_name'] == 'field_d_product_media') {
    $variables['#attached']['library'][] = 'd_product/d_product_slider';
    $vid = $variables['element']['#object']->vid->value;
    $slider = views_embed_view('product_images', 'block_1', $vid);
    $variables['slider'] = \Drupal::service('renderer')->render($slider);
  }
}

/**
 * Implements hook_preprocess_HOOK() for block.
 */
function droopler_theme_preprocess_block(&$variables) {
  if ($variables['base_plugin_id'] == 'page_title_block') {
    $variables['show_title'] = droopler_theme_show_title_block();

    if (droopler_theme_is_special_route()) {
      $variables['attributes']['class'][] = 'container';
    }
  }
}

/**
 * Implements hook_preprocess_HOOK() for menu_local_action.
 */
function droopler_theme_preprocess_menu_local_action(&$variables) {
  $variables['link']['#options']['attributes']['class'] = [
    'btn',
    'btn-outline-primary',
    'btn-sm',
  ];
}

/**
 * Check if current route is node with paragraphs or other defined route.
 *
 * @return bool
 *   True if it matches special criteria.
 */
function droopler_theme_is_special_route() {
  $route = \Drupal::routeMatch();
  $route_name = $route->getRouteName();
  $node = $route->getParameter('node');
  if (!empty($node) && !($node instanceof NodeInterface)) {
    $node = Node::load($node);
  }
  $node_check = (!empty($node) && in_array($node->getType(), [
    'content_page',
    'blog_post',
    'd_product',
  ]));
  $route_check = $route_name == 'd_p_subscribe_file.downloadfile.checkLink';

  return ($node_check || $route_check);
}

/**
 * Checks if title block should not be displayed.
 *
 * @return bool
 *   True if it matches special criteria.
 */
function droopler_theme_show_title_block() {
  $route = \Drupal::routeMatch();
  $route_name = $route->getRouteName();
  $node = $route->getParameter('node');
  if (!empty($node) && !($node instanceof NodeInterface)) {
    $node = Node::load($node);
  }
  $node_check = (!empty($node) && in_array($node->getType(), [
    'content_page',
    'blog_post',
  ]));
  $route_check = $route_name == 'view.blog_listing.page_1';

  return !($node_check || $route_check);
}

/**
 * Getter for the page layout on node pages.
 *
 * @param array $variables
 *   Theme variables.
 *
 * @return string|null
 *   Layout name, defaults to null.
 */
function droopler_theme_get_page_layout(array $variables) {
  /** @var \Drupal\node\NodeInterface|null $node */
  $node = $variables['node'] ?? NULL;
  $layout = NULL;

  if ($node instanceof NodeInterface) {
    $layout_field = 'field_header_layout';
    if ($node->hasField($layout_field)) {
      $layout = $node->{$layout_field}->value;
    }
  }

  return $layout;
}

/**
 * Implements hook_preprocess_HOOK() for we_megamenu_li.
 */
function droopler_theme_preprocess_we_megamenu_li(&$variables) {
  if (isset($variables['content']['#item_config'])
    && isset($variables['content']['#item_config']->rows_content)) {
    foreach ($variables['content']['#item_config']->rows_content as $rows) {
      foreach ($rows as $col) {
        if (isset($col->col_content->block_id)) {
          $variables['attributes']['class'][] = 'mega';
          break;
        }
      }
    }
  }
}

/**
 * Implements hook_library_info_alter().
 */
function droopler_theme_library_info_alter(&$libraries, $extension) {
  if ($extension == 'we_megamenu' && isset($libraries['form.we-mega-menu-frontend'])) {
    unset($libraries['form.we-mega-menu-frontend']);
  }

  // Make Droopler compatible with Drupal.org.
  // Enable libraries in profile directory.
  $profile_libraries_dir = \Drupal::service('extension.path.resolver')->getPath('profile', 'droopler') . '/libraries';
  if (file_exists($profile_libraries_dir)) {
    foreach ($libraries as &$info) {
      // Alter JS.
      if (isset($info['js'])) {
        droopler_theme_change_asset_location($profile_libraries_dir, $info['js']);
      }
      // Alter CSS.
      if (isset($info['css'])) {
        foreach ($info['css'] as &$scripts) {
          droopler_theme_change_asset_location($profile_libraries_dir, $scripts);
        }
      }
    }
  }
}

/**
 * Change locations of assets.
 *
 * Take a list of assets and change their locations
 * to profile directory if needed.
 *
 * @param string $profile_libraries_dir
 *   The /libraries directory path inside the profile.
 * @param array $assets
 *   A list of assets.
 */
function droopler_theme_change_asset_location($profile_libraries_dir, array &$assets) {
  foreach ($assets as $old_path => &$options) {
    $new_path = preg_replace('|^/libraries/(.*)$|', '/' . $profile_libraries_dir . '/\\1', $old_path);
    if ($new_path != $old_path) {
      if (!file_exists(trim($old_path, '/')) && file_exists(trim($new_path, '/'))) {
        unset($assets[$old_path]);
        $assets[$new_path] = $options;
      }
    }
  }
}

/**
 * Function returns user's browser based on User-Agent request header.
 *
 * @return string
 *   User browser's name.
 */
function detect_browser() {
  $arr_browsers = [
    "Opera",
    "Edge",
    "Chrome",
    "Safari",
    "Firefox",
    "MSIE",
    "Trident",
  ];
  $agent = $_SERVER['HTTP_USER_AGENT'];
  $user_browser = '';
  foreach ($arr_browsers as $browser) {
    if (strpos($agent, $browser) !== FALSE) {
      $user_browser = $browser;
      break;
    }
  }
  switch ($user_browser) {
    case 'Trident':
    case 'MSIE':
      $user_browser = 'Internet Explorer';
      break;

    case 'Edge':
      $user_browser = 'Microsoft Edge';
      break;
  }

  return $user_browser;
}
