<?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 Oxygen extends Editors
{
    const META_KEY = 'ct_builder_json';
    private $extracted_data;
    private static $supported_blocks = ['ct_content' => ['oxy_rich_text', 'ct_text_block']];
    private static $unsupported_classes = ["oxel_accordion__row__label", "oxel_dashboard_tabs", "oxel_flipbox", "oxel_reviewbox"];
    public function __construct($post_id)
    {
        $this->post_id = $post_id;
        $content = get_post_meta($this->post_id, self::META_KEY, \true);
        if (gettype($content) !== 'string') {
            $content = '';
        }
        $this->content = json_decode($content);
    }
    public static function is_active($post_id): bool
    {
        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']:
                if (!str_contains($this->extracted_data, $block_content)) {
                    if (!preg_match('/^<(\w+)[^>]*>.*<\/\1>$/', $block_content)) {
                        $this->extracted_data .= "<div>{$block_content}</div>";
                    } else {
                        $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(&$block, $op_code = self::OP_CODES['EXTRACT_CONTENT'])
    {
        // stop further block processing if $add is true and link has already been added
        if ($op_code !== self::OP_CODES['EXTRACT_CONTENT'] && $this->link_processed) {
            return;
        }
        if (is_object($block)) {
            // Ignore unsupported block types and classes
            if (in_array($block->name, ['oxy_tab', 'ct_slider'])) {
                return;
            }
            if (!empty($block->options) && !empty($block->options->classes)) {
                if (count(array_intersect(self::$unsupported_classes, $block->options->classes)) > 0) {
                    return;
                }
            }
            $content_key = null;
            // set the content key based on the block name supported or not
            foreach (self::$supported_blocks as $key => $sb) {
                if (in_array($block->name, $sb)) {
                    $content_key = $key;
                    break;
                }
            }
            if ($content_key) {
                // get content from "options" property
                if (!empty($block->options) && !empty($block->options->{$content_key})) {
                    $this->handle_block_ops($block->options->{$content_key}, $op_code);
                }
            }
            if (!empty($block->children)) {
                foreach ($block->children as $child) {
                    $this->extract_content($child, $op_code);
                }
            }
        }
    }
    public function get_content($post_id): string
    {
        $this->extracted_data = '';
        // extract the content from supported blocks
        $this->extract_content($this->content);
        return $this->extracted_data;
    }
    public function add_link($source, $phrase, $phrase_replacement): bool
    {
        $this->params = ['source' => $source, 'phrase' => $phrase, 'replacement' => $phrase_replacement];
        $this->link_processed = \false;
        // add link to content
        $this->extract_content($this->content, 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
    {
        $success = \false;
        if ($this->has_unsaved_changes) {
            $oxygen_data = addslashes(wp_json_encode($this->content));
            $success = update_post_meta($this->post_id, self::META_KEY, $oxygen_data) !== \false;
            if ($success) {
                $this->has_unsaved_changes = \false;
                // sync with wp post content
                $this->after_update_post($suggestions);
            }
        }
        return $success;
    }
    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];
        // remove link from content
        $this->extract_content($this->content, 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];
        $this->extract_content($this->content, self::OP_CODES['REPLACE_LINK']);
        if ($this->link_processed) {
            $this->has_unsaved_changes = \true;
            if ($save) {
                return $this->update_post();
            }
            return \true;
        }
        return \false;
    }
}
