<?php

/**
 * Plugin Name:     Wpct i18n
 * Plugin URI:      https://git.coopdevs.org/codeccoop/wp/wpct-i18n
 * Description:     String translation
 * Author:          Còdec Cooperativa
 * Author URI:      https://www.codeccoop.org
 * Text Domain:     wpct-i18n
 * Domain Path:     /languages
 * Version:         1.0.5
 *
 * @package         Wpct_i18n
 */

namespace WPCT_I18N;

use WP_Post;
use WP_Term;

if (!defined('ABSPATH')) {
    exit;
}

if (!class_exists('\WPCT_I18N\Wpct_i18n')) :

require_once 'abstracts/class-plugin.php';

define('WPCT_I18N_VERSION', '1.0.5');

class Wpct_i18n extends \WPCT_ABSTRACT\Plugin
{
    private $_integration;

    public static $name = 'Wpct i18n';
    public static $textdomain = 'wpct-i18n';

    public static function activate()
    {
    }

    public static function deactivate()
    {
    }

    public function __construct()
    {
        parent::__construct();

    }

    public function init()
    {
        // Hooks
        add_filter('wpct_i18n_default_language', [$this, 'default_language'], 10, 2);
        add_filter('wpct_i18n_current_language', [$this, 'current_language'], 10, 2);
        add_filter('wpct_i18n_active_languages', [$this, 'active_languages'], 10, 2);

        add_filter('wpct_i18n_post_language', [$this, 'post_language'], 10, 2);
        add_filter('wpct_i18n_post_translations', [$this, 'post_translations'], 10);
        add_filter('wpct_i18n_term_translations', [$this, 'term_translations'], 10);
        add_filter('wpct_i18n_is_translation', [$this, 'is_translation'], 10);
        add_filter('wpct_i18n_translate_post', [$this, 'translate_post'], 10, 2);

        add_action('wpct_i18n_language_switcher', [$this, 'language_switcher']);

        // Configure integration
        if (apply_filters('wpct_is_plugin_active', false, 'polylang/polylang.php')) {
            $this->_integration = 'pll';
        } elseif (apply_filters('wpct_is_plugin_active', false, 'sitepress-multilingual-cms/sitepress.php')) {
            $this->_integration = 'wpml';
        }

        $this->trans_status();
    }

    private function get_wpml_language_by_slug($slug)
    {
        $languages = apply_filters('wpml_active_languages', null);
        $codes = array_values(array_filter(array_keys($languages), function ($code) use ($slug, $languages) {
            $lang = $languages[$code];
            return $lang['language_code'] === $slug;
        }));

        if (count($codes) === 0) {
            return null;
        }

        return $languages[$codes[0]];
    }

    public function default_language($null = null, $format = 'slug')
    {
        switch ($this->_integration) {
            case 'pll':
                return pll_default_language($format);
            case 'wpml':
                $slug = apply_filters('wpml_default_language', null);
                if ($format === 'slug') {
                    return $slug;
                } else {
                    $language = $this->get_wpml_language_by_slug($slug);
                    return $language['default_locale'];
                }
                break;
            default:
                $locale = get_locale();
                if ($format === 'locale') {
                    return $locale;
                }

                return strtolower(preg_replace('/_\w+$/', '', $locale));
        }
    }

    public function current_language($null = null, $format = 'slug')
    {
        switch ($this->_integration) {
            case 'pll':
                return pll_current_language($format);
            case 'wpml':
                $slug = apply_filters('wpml_current_language', null);
                if ($format === 'slug') {
                    return $slug;
                } else {
                    $language = $this->get_wpml_language_by_slug($slug);
                    return $language['default_locale'];
                }
                // no break
            default:
                $locale = get_locale();
                if ($format === 'locale') {
                    return $locale;
                }
                return strtolower(preg_replace('/_\w+$/', '', $locale));
        }
    }

    public function active_languages($null = null, $format = 'slug')
    {
        switch ($this->_integration) {
            case 'pll':
                return pll_languages_list(['fields' => $format, 'hide_empty' => false]);
            case 'wpml':
                $languages = apply_filters('wpml_active_languages', null);
                $field = $format === 'slug' ? 'language_code' : 'default_locale';
                return array_map(function ($lng) use ($field) {
                    return $lng[$field];
                }, $languages);
            default:
                $languages = [get_locale()];
                if ($format === 'locale') {
                    return $languages;
                }
                return array_map(function ($locale) {
                    return strtolower(preg_replace('/_\w+$/', '', $locale));
                }, $languages);
        }
    }

    public function language_switcher($echo = true)
    {
        if (!$echo) {
            ob_start();
        }
        switch ($this->_integration) {
            case 'pll':
                pll_the_languages();
                break;
            case 'wpml':
                do_action('wpml_add_language_selector');
                break;
            default:
                // do nothing
        }
        if (!$echo) {
            return ob_get_clean();
        }
    }

    public function post_language($post_id, $format = 'slug')
    {
        if ($post_id instanceof WP_Post) {
            $post_id = $post_id->ID;
        }

        switch ($this->_integration) {
            case 'pll':
                return pll_get_post_language($post_id, $format);
            case 'wpml':
                $details = apply_filters('wpml_post_language_details', null, $post_id);
                if ($format === 'slug') {
                    return $details['language_code'];
                } else {
                    return $details['locale'];
                }
                break;
            default:
                return null;
        }
    }

    public function post_translations($post_id)
    {
        if ($post_id instanceof WP_Post) {
            $post_id = $post_id->ID;
        }

        switch ($this->_integration) {
            case 'pll':
                return pll_get_post_translations($post_id);
            case 'wpml':
                $type = apply_filters('wpml_element_type', get_post_type($post_id));
                $trid = apply_filters('wpml_element_trid', false, $post_id, $type);
                $translations = [];
                foreach (apply_filters('wpml_get_element_translations', [], $trid, $type) as $trans) {
                    $translations[$trans->language_code] = (int) $trans->element_id;
                }

                return $translations;
            default:
                $current_lang = $this->current_language();
                return [$current_lang => $post_id];
        }
    }

    public function term_translations($term_id)
    {
        if ($term_id instanceof WP_Term) {
            $term_id = $term_id->term_id;
        }

        switch ($this->_integration) {
            case 'pll':
                return pll_get_term_translations($term_id);
            case 'wpml':
                $type = apply_filters('wpml_element_type', 'category');
                $trid = apply_filters('wpml_element_trid', false, $term_id, $type);
                $translations = [];
                foreach (apply_filters('wpml_get_element_translations', [], $trid, $type) as $trans) {
                    $translations[$trans->language_code] = (int) $trans->element_id;
                }
                return $translations;
            default:
                $current_lang = $this->current_language();
                return [$current_lang => $term_id];
        }
    }

    public function is_translation($post_id)
    {
        if ($post_id instanceof WP_Post) {
            $post_id = $post_id->ID;
        }

        switch ($this->_integration) {
            case 'pll':
                $post_lang = pll_get_post_language($post_id);
                return $post_lang !== $this->default_language();
            case 'wpml':
                $lang_details = apply_filters('wpml_post_language_details', null, $post_id);
                return !empty($lang_details['language_code']) && $lang_details['language_code'] !== $this->default_language();
            default:
                return false;
        }
    }

    public function translate_post($post, $lang)
    {
        if (is_int($post)) {
            $post = get_post($post);
        }

        $post_data = wp_slash((array) $post);
        $post_data['_thumbnail_id'] = get_post_thumbnail_id($post_data['ID']);
        unset($post_data['ID']);
        $post_data['post_status'] = 'translating';
        $trans_id = wp_insert_post($post_data);

        switch ($this->_integration) {
            case 'pll':
                $post_lang = pll_get_post_language($post->ID);
                pll_set_post_language($trans_id, $lang);
                pll_save_post_translations([
                    $lang => $trans_id,
                    $post_lang => $post->ID,
                ]);
                break;
            case 'wpml':
                $element_type = apply_filters('wpml_element_type', $post->post_type);
                $lang_details = apply_filters(
                    'wpml_element_language_details',
                    null,
                    [
                        'element_id' => $post->ID,
                        'element_type' => $element_type
                    ]
                );
                do_action('wpml_set_element_language_details', [
                    'element_id' => $trans_id,
                    'element_type' => $element_type,
                    'trid' => $lang_details->trid,
                    'language_code' => $lang,
                    'source_language_code' => $lang_details->language_code
                ]);
                break;
            default:
                return null;
        }

        wp_update_post([
            'ID' => $trans_id,
            'post_status' => $post->post_status
        ]);

        return $trans_id;
    }

    public function trans_status()
    {
        register_post_status('translating', [
            'label' => __('Provisional status while translating post', 'wpct-i18n'),
            'public' => false,
            'internal' => true
        ]);
    }
}

add_action('plugins_loaded', function () {
    $plugin = Wpct_i18n::get_instance();
}, 10);

register_activation_hook(__FILE__, function () {
    Wpct_i18n::activate();
});

register_deactivation_hook(__FILE__, function () {
    Wpct_i18n::deactivate();
});

endif;