<?php 

namespace TSNV_SEO;

class PLL_ACF_Auto_Translate {
  private $fields;

  public function __construct() {
    add_filter('acf/update_value', [$this, 'store_updated_field'], 10, 3);
    add_filter('acf/delete_value', [$this, 'store_updated_field'], 10, 3);
    add_action('pll_save_term', [$this, 'store_term_fields'], 5);
    add_action('pll_duplicate_term', [$this, 'store_term_fields'], 5);

    add_filter('acf/load_value', [$this, 'load_value'], 10, 3);
    add_filter('acf/load_value/type=repeater', [$this, 'load_value'], 20, 3);
    add_filter('acf/load_value/type=flexible_content', [$this, 'load_value'], 20, 3);

    add_filter('pll_translate_post_meta', [$this, 'translate_meta'], 10, 5);
    add_filter('pll_translate_term_meta', [$this, 'translate_meta'], 10, 4);
  }

  public function store_updated_field($value, $post_id, $field) {
    $this->fields[$field['name']] = $field;
    return $value;
  }

  public function store_term_fields($term_id) {
    $this->fields = get_field_objects('term_' . $term_id);
  }

  public function load_value($value, $post_id, $field) {
    if ('term_0' === $post_id && isset($_GET['taxonomy'], $_GET['from_tag'], $_GET['new_lang'])) {
      $from = 'term_' . intval($_GET['from_tag']);
      $lang = sanitize_key($_GET['new_lang']);
      $fields = get_field_objects($from);

      if ($fields) {
        $keys = array_keys($fields);
        $keys = array_unique(apply_filters('pll_copy_term_metas', $keys, false, intval($_GET['from_tag']), 0, $lang));

        if (in_array($field['name'], $keys) || preg_match('#^(' . implode('|', $keys) . ')_(.+)#', $field['name'])) {
          $value = acf_get_value($from, $field);
          $empty = null;
          $value = $this->translate_fields($empty, $value, $field['name'], $field, $lang, true);
        }
      }
    }
    return $value;
  }

  public function translate_meta($value, $key, $lang, $from, $to = 0) {
    if (!empty($value) && ($field = $this->fields[$key] ?? $this->get_field_object($key, $from))) {
      $create = !empty($to) && $this->should_create_for_post($from, $to);
      $value = $this->translate_field($value, $lang, $field, $create);
    }
    return $value;
  }

  protected function should_create_for_post($from, $to) {
    $pt = get_post_type($to);
    if (!$pt || !pll_is_translated_post_type($pt)) return false;
    return true;
  }

  protected function get_field_object($key, $post_id) {
    $f = get_field_object($key, $post_id);
    if ($f) return $f;
    $pid = acf_get_valid_post_id($post_id);
    $ref = acf_get_reference($key, $pid);
    if (!is_string($ref)) return false;
    $ref = substr($ref, -19);
    if (!acf_is_field_key($ref)) return false;
    $f = acf_get_field($ref);
    if (!$f) return false;
    $f['value'] = acf_format_value(acf_get_value($pid, $f), $pid, $f);
    return $f;
  }

  protected function translate_field($value, $lang, $field, $create_if_not_exists = false) {
    $return = $value;
    switch ($field['type']) {
      case 'image':
      case 'file':
        if (PLL()->options['media_support']) {
          if ($tr = pll_get_post(intval($value), $lang)) {
            $return = $tr;
          } elseif ($create_if_not_exists) {
            $return = PLL()->posts->create_media_translation(intval($value), $lang);
          }
        }
        break;
      case 'gallery':
        if (PLL()->options['media_support'] && is_array($value)) {
          $res = [];
          foreach ($value as $img) {
            if ($tr = pll_get_post(intval($img), $lang)) {
              $res[] = $tr;
            } elseif ($create_if_not_exists) {
              $res[] = PLL()->posts->create_media_translation(intval($img), $lang);
            }
          }
          $return = array_map('strval', $res);
        }
        break;
    }
    return $return;
  }

  protected function translate_fields(&$r, $value, $name, $field, $lang, $create = false) {
    if (empty($value)) return;
    $r['_' . $name] = $field['key'];
    switch ($field['type']) {
      case 'group':
        $ret = [];
        foreach ($field['sub_fields'] as $sf) {
          if (isset($value[$sf['name']])) {
            $ret[$sf['name']] = $this->translate_fields($r, $value[$sf['name']], $sf['name'], $sf, $lang, $create);
          }
        }
        return $ret;
      case 'repeater':
        $out = [];
        foreach ($value as $i => $row) {
          foreach ($field['sub_fields'] as $sf) {
            $field_name = "{$name}_{$i}_{$sf['name']}";
            if (isset($row[$sf['name']])) {
              $out[$i][$sf['name']] = $this->translate_fields($r, $row[$sf['name']], $field_name, $sf, $lang, $create);
            }
          }
        }
        return $out;
      case 'flexible_content':
        $out = [];
        foreach ($value as $i => $row) {
          $layout = array_values(array_filter($field['layouts'], fn($l) => $l['name'] === $row['acf_fc_layout']))[0] ?? null;
          if ($layout) {
            foreach ($layout['sub_fields'] as $sf) {
              $field_name = "{$name}_{$i}_{$sf['name']}";
              if (isset($row[$sf['name']])) {
                $out[$i][$sf['name']] = $this->translate_fields($r, $row[$sf['name']], $field_name, $sf, $lang, $create);
              }
            }
          }
        }
        return $out;
      case 'clone':
        $ret = [];
        foreach ($field['sub_fields'] as $sf) {
          $ret[$sf['name']] = $this->translate_fields($r, $value[$sf['name']] ?? null, $sf['name'], $sf, $lang, $create);
        }
        return $ret;
      default:
        return $this->translate_field($value, $lang, $field, $create);
    }
  }
}


add_action('plugins_loaded', function () {
  if (class_exists('Polylang') && !class_exists('PLL_Pro')) {
    new \TSNV_SEO\PLL_ACF_Auto_Translate();
  }
});

