<?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 Breakdance extends Editors
{
    const META_KEY = '_breakdance_data';
    const CONTENT_TYPES = ['Section', 'Text', 'RichText', 'BasicList', 'ImageBox', 'IconBox', 'CheckmarkList', 'FrequentlyAskedQuestions', 'IconList', 'Tabs', 'AdvancedTabs', 'TabContent', 'ImageAccordion'];
    const CHILDREN_TYPES = [];
    private $extracted_data;
    public function __construct($post_id)
    {
        $this->post_id = $post_id;
        $content = get_post_meta($post_id, self::META_KEY, \true);
        $new_content = json_decode($content, \true);
        if (gettype($new_content) === 'string') {
            $this->content = '';
        } else {
            $this->content = json_decode($new_content['tree_json_string']);
        }
    }
    public static function is_active($post_id): bool
    {
        if (!Utils::is_plugin_active('breakdance/plugin.php')) {
            return \false;
        }
        return !empty(get_post_meta($post_id, self::META_KEY, \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'])
    {
        $type = basename(str_replace('\\', '/', $item->data->type));
        if (!empty($item->data->type) && in_array($type, self::CONTENT_TYPES)) {
            if (isset($item->data->properties->content->content->text) && !empty($item->data->properties->content->content->text)) {
                if ($this->handle_block_ops($item->data->properties->content->content->text, $op_code)) {
                    return;
                }
            } elseif (isset($item->data->properties->content->content->items) && count($item->data->properties->content->content->items) > 0) {
                foreach ($item->data->properties->content->content->items as $list) {
                    if (isset($list->text) && !empty($list->text)) {
                        if ($this->handle_block_ops($list->text, $op_code)) {
                            return;
                        }
                    }
                }
            } elseif (isset($item->data->properties->content->content->list) && count($item->data->properties->content->content->list) > 0) {
                foreach ($item->data->properties->content->content->list as $list) {
                    if (isset($list->text) && !empty($list->text)) {
                        if ($this->handle_block_ops($list->text, $op_code)) {
                            return;
                        }
                    }
                }
            } elseif (isset($item->data->properties->content->content->tabs) && count($item->data->properties->content->content->tabs) > 0) {
                foreach ($item->data->properties->content->content->tabs as $tab) {
                    if (isset($tab->content) && !empty($tab->content)) {
                        if ($this->handle_block_ops($tab->content, $op_code)) {
                            return;
                        }
                    }
                }
            } elseif (isset($item->data->properties->content->content->images) && count($item->data->properties->content->content->images) > 0) {
                foreach ($item->data->properties->content->content->images as $img) {
                    if (isset($img->text) && !empty($img->text)) {
                        if ($this->handle_block_ops($img->text, $op_code)) {
                            return;
                        }
                    }
                }
            }
            // Process EssentialElements\FrequentlyAskedQuestions
            if (isset($item->data->properties->content->settings->questions) && is_array($item->data->properties->content->settings->questions)) {
                foreach ($item->data->properties->content->settings->questions as $question) {
                    if (isset($question->answer) && !empty($question->answer)) {
                        if ($this->handle_block_ops($question->answer, $op_code)) {
                            return;
                        }
                    }
                }
            }
            if (isset($item->data->properties->content->settings->items) && is_array($item->data->properties->content->settings->items)) {
                foreach ($item->data->properties->content->settings->items as $item_setting) {
                    if (isset($item_setting->answer) && !empty($item_setting->answer)) {
                        if ($this->handle_block_ops($item_setting->answer, $op_code)) {
                            return;
                        }
                    }
                }
            }
        }
        if (!empty($item->children)) {
            foreach ($item->children as $child) {
                $this->extract_content($child, $op_code);
            }
        }
    }
    public function get_content($post_id): string
    {
        $this->extracted_data = '';
        $root_children = $this->content->root->children;
        if (is_countable($root_children)) {
            foreach ($root_children as $block) {
                // extract content from supported block
                $this->extract_content($block);
            }
        }
        return $this->extracted_data;
    }
    public function update_post($suggestions = null): bool
    {
        if ($this->has_unsaved_changes) {
            $escapedJson = json_encode($this->content, \JSON_UNESCAPED_UNICODE);
            // If additional escape for specific characters required for WordPress postmeta
            // $escapedJson = str_replace(
            //     ['&'], 
            //     ['\u0026'], 
            //     $escapedJson
            // );
            $updated_meta_data = json_encode(['tree_json_string' => $escapedJson]);
            $success = update_post_meta($this->post_id, self::META_KEY, wp_slash($updated_meta_data)) !== \false;
            if ($success) {
                $this->has_unsaved_changes = \false;
                wp_update_post(['ID' => $this->post_id]);
                return \true;
            }
        }
        return \false;
    }
    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];
        $root_children = $this->content->root->children;
        if (is_countable($root_children)) {
            foreach ($root_children 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 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];
        $root_children = $this->content->root->children;
        if (is_countable($root_children)) {
            foreach ($root_children as $block) {
                $this->extract_content($block, self::OP_CODES['REMOVE_LINK']);
            }
        }
        if ($this->link_processed) {
            $this->has_unsaved_changes = \true;
            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];
        $root_children = $this->content->root->children;
        if (is_countable($root_children)) {
            foreach ($root_children as $block) {
                $this->extract_content($block, self::OP_CODES['REPLACE_LINK']);
            }
        }
        if ($this->link_processed) {
            $this->has_unsaved_changes = \true;
            return \true;
        }
        return \false;
    }
}
