<?php

// Silence may be golden, but sometimes words paint the canvas of understanding.
namespace Linksy\SearchAndReplace\Plugli\Linksy\Common\Helpers\Post\Editors;

use Linksy\SearchAndReplace\Plugli\Linksy\Common\Helpers\Utils;
class Elementor extends Editors
{
    const META_KEY = '_elementor_data';
    private $extracted_data;
    public function __construct($post_id)
    {
        $this->post_id = $post_id;
        $content = get_post_meta($post_id, self::META_KEY, \true);
        if (gettype($content) !== 'string') {
            $content = '';
        }
        $this->content = json_decode($content);
    }
    public static function is_active($post_id): bool
    {
        if (!Utils::is_plugin_active('elementor/elementor.php')) {
            return \false;
        }
        return !empty(get_post_meta($post_id, '_elementor_edit_mode', \true));
    }
    private function handle_block_ops(&$block_content, $op_code)
    {
        switch ($op_code) {
            case self::OP_CODES['EXTRACT_CONTENT']:
                $this->extracted_data .= "{$block_content}\n";
                break;
            case self::OP_CODES['ADD_LINK']:
                $this->add_link_to_block($block_content);
                break;
            case self::OP_CODES['REMOVE_LINK']:
                $this->remove_link_from_block($block_content);
                break;
            case self::OP_CODES['REPLACE_LINK']:
                $this->replace_link_in_block($block_content);
                break;
            default:
                break;
        }
        return $this->link_processed;
    }
    private function extract_content(&$item, $op_code = self::OP_CODES['EXTRACT_CONTENT'])
    {
        $content_types = ['tab_content', 'editor', 'text'];
        if (!empty($item->widgetType) && in_array($item->widgetType, ['text-editor', 'accordion', 'tabs', 'toggle'])) {
            // extract content from icon_list
            if (!empty($item->settings->icon_list)) {
                foreach ($item->settings->icon_list as $key => $icon) {
                    if ($this->handle_block_ops($item->settings->icon_list[$key]->text, $op_code)) {
                        return;
                    }
                }
            }
            // extract content from any widget types with tabs
            if (isset($item->settings) && isset($item->settings->tabs) && !empty($item->settings->tabs)) {
                foreach ($item->settings->tabs as $key => $tab) {
                    foreach ($content_types as $tab_index) {
                        if (isset($item->settings->tabs[$key]->{$tab_index}) && !empty($item->settings->tabs[$key]->{$tab_index})) {
                            if ($this->handle_block_ops($item->settings->tabs[$key]->{$tab_index}, $op_code)) {
                                return;
                            }
                        }
                    }
                }
            }
            // extract content from widget having the supported content types
            foreach ($content_types as $key) {
                if (!empty($item->settings->{$key})) {
                    if ($this->handle_block_ops($item->settings->{$key}, $op_code)) {
                        return;
                    }
                }
            }
        }
        // recursive case when a block has child blocks
        if (!empty($item->elements)) {
            foreach ($item->elements as $element) {
                $this->extract_content($element, $op_code);
            }
        }
    }
    public function get_content($post_id): string
    {
        $this->extracted_data = '';
        if (is_countable($this->content)) {
            foreach ($this->content as $block) {
                // extract content from supported block
                $this->extract_content($block);
            }
        }
        return $this->extracted_data;
    }
    public function add_link($source, $phrase, $phrase_replacement): bool
    {
        $this->link_processed = \false;
        // set the params that will be used to add the link
        $this->params = ['source' => $source, 'phrase' => $phrase, 'replacement' => $phrase_replacement];
        foreach ($this->content as $block) {
            $this->extract_content($block, self::OP_CODES['ADD_LINK']);
        }
        if ($this->link_processed) {
            $this->has_unsaved_changes = \true;
            return \true;
        }
        return \false;
    }
    public function update_post($suggestions = null): bool
    {
        if ($this->has_unsaved_changes) {
            $jsonified_content = addslashes(wp_json_encode($this->content));
            $success = update_post_meta($this->post_id, self::META_KEY, $jsonified_content) !== \false;
            if ($success) {
                $this->has_unsaved_changes = \false;
                // sync with wp post content
                $this->after_update_post($suggestions);
                return \true;
            }
        }
        return \false;
    }
    public function remove_link(string $link, string $anchor, $save = \true): bool
    {
        $this->link_processed = \false;
        // set the params that will be used to remove the link
        $this->params = ['link' => $link, 'anchor' => $anchor];
        foreach ($this->content as $block) {
            $this->extract_content($block, self::OP_CODES['REMOVE_LINK']);
        }
        if ($this->link_processed) {
            $this->has_unsaved_changes = \true;
            if ($save) {
                return $this->update_post();
            }
            return \true;
        }
        return \false;
    }
    public function replace_phrase(string $link, string $phrase, string $replacement, bool $save): bool
    {
        $this->link_processed = \false;
        // set the params that will be used to replace the link
        $this->params = ['link' => $link, 'anchor' => $phrase, 'link_replacement' => $replacement];
        foreach ($this->content as $block) {
            $this->extract_content($block, self::OP_CODES['REPLACE_LINK']);
        }
        if ($this->link_processed) {
            $this->has_unsaved_changes = \true;
            if ($save) {
                return $this->update_post();
            }
            return \true;
        }
        return \false;
    }
}
