<?php

/**
 * @package     Dotclear
 *
 * @copyright   Olivier Meunier & Association Dotclear
 * @copyright   AGPL-3.0
 */
declare(strict_types=1);

namespace Dotclear\Plugin\dcCKEditor;

use Dotclear\App;
use Dotclear\Helper\Html\Form\Button;
use Dotclear\Helper\Html\Form\Checkbox;
use Dotclear\Helper\Html\Form\Fieldset;
use Dotclear\Helper\Html\Form\Form;
use Dotclear\Helper\Html\Form\Input;
use Dotclear\Helper\Html\Form\Label;
use Dotclear\Helper\Html\Form\Legend;
use Dotclear\Helper\Html\Form\Note;
use Dotclear\Helper\Html\Form\Number;
use Dotclear\Helper\Html\Form\Para;
use Dotclear\Helper\Html\Form\Submit;
use Dotclear\Helper\Html\Form\Text;
use Dotclear\Helper\Html\Form\Textarea;
use Dotclear\Helper\Html\Html;
use Dotclear\Helper\Process\TraitProcess;
use Exception;

/**
 * @brief   The module manage process.
 * @ingroup dcCKEditor
 */
class Manage
{
    use TraitProcess;

    protected static bool $editor_is_admin;

    protected static bool $editor_cke_active;

    protected static bool $editor_cke_was_actived;

    public static bool $cmd_alignment_buttons;

    public static bool $cmd_list_buttons;

    public static bool $cmd_textcolor_button;

    public static bool $cmd_background_textcolor_button;

    public static string $cmd_custom_color_list;

    public static int $cmd_colors_per_row;

    public static bool $cmd_cancollapse_button;

    public static bool $cmd_format_select;

    public static string $cmd_format_tags;

    public static bool $cmd_table_button;

    public static bool $cmd_clipboard_buttons;

    public static bool $cmd_action_buttons;

    public static bool $cmd_disable_native_spellchecker;

    public static function init(): bool
    {
        // Menu is only accessible if admin/superadmin
        self::$editor_is_admin = My::checkContext(My::MENU);

        if (!self::status(My::checkContext(My::MANAGE))) {
            return false;
        }

        self::$editor_cke_active               = My::settings()->getBool('active', false);
        self::$cmd_alignment_buttons           = My::settings()->getBool('alignment_buttons', false);
        self::$cmd_list_buttons                = My::settings()->getBool('list_buttons', false);
        self::$cmd_textcolor_button            = My::settings()->getBool('textcolor_button', false);
        self::$cmd_background_textcolor_button = My::settings()->getBool('background_textcolor_button', false);
        self::$cmd_custom_color_list           = My::settings()->getStr('custom_color_list', false);
        self::$cmd_colors_per_row              = My::settings()->getInt('colors_per_row', false);
        self::$cmd_cancollapse_button          = My::settings()->getBool('cancollapse_button', false);
        self::$cmd_format_select               = My::settings()->getBool('format_select', false);
        self::$cmd_format_tags                 = My::settings()->getStr('format_tags', false);
        self::$cmd_table_button                = My::settings()->getBool('table_button', false);
        self::$cmd_clipboard_buttons           = My::settings()->getBool('clipboard_buttons', false);
        self::$cmd_action_buttons              = My::settings()->getBool('action_buttons', false);
        self::$cmd_disable_native_spellchecker = My::settings()->getBool('disable_native_spellchecker', false);

        if (!empty($_GET['config'])) {
            // text/javascript response stop stream just after including file
            ManagePostConfig::load();
            dotclear_exit();
        }

        if (!self::$editor_is_admin) {
            // Avoid any further process if not admin/superadmin
            return false;
        }

        self::$editor_cke_was_actived = self::$editor_cke_active;

        return self::status(true);
    }

    public static function process(): bool
    {
        if (!self::status()) {
            return false;
        }

        if (!empty($_POST['saveconfig'])) {
            try {
                self::$editor_cke_active = !empty($_POST['dcckeditor_active']);
                My::settings()->put('active', self::$editor_cke_active, App::blogWorkspace()::NS_BOOL);

                // change other settings only if they were in HTML page
                if (self::$editor_cke_was_actived) {
                    self::$cmd_alignment_buttons = !empty($_POST['dcckeditor_alignment_buttons']);
                    My::settings()->put('alignment_buttons', self::$cmd_alignment_buttons, App::blogWorkspace()::NS_BOOL);

                    self::$cmd_list_buttons = !empty($_POST['dcckeditor_list_buttons']);
                    My::settings()->put('list_buttons', self::$cmd_list_buttons, App::blogWorkspace()::NS_BOOL);

                    self::$cmd_textcolor_button = !empty($_POST['dcckeditor_textcolor_button']);
                    My::settings()->put('textcolor_button', self::$cmd_textcolor_button, App::blogWorkspace()::NS_BOOL);

                    self::$cmd_background_textcolor_button = !empty($_POST['dcckeditor_background_textcolor_button']);
                    My::settings()->put('background_textcolor_button', self::$cmd_background_textcolor_button, App::blogWorkspace()::NS_BOOL);

                    $custom_color_list = is_string($custom_color_list = $_POST['dcckeditor_custom_color_list']) ? $custom_color_list : '';

                    self::$cmd_custom_color_list = str_replace(['#', ' '], '', $custom_color_list);
                    My::settings()->put('custom_color_list', self::$cmd_custom_color_list, App::blogWorkspace()::NS_STRING);

                    $colors_per_row = is_numeric($colors_per_row = $_POST['dcckeditor_colors_per_row']) ? (int) $colors_per_row : 6;

                    self::$cmd_colors_per_row = abs($colors_per_row);
                    My::settings()->put('colors_per_row', self::$cmd_colors_per_row, App::blogWorkspace()::NS_INT);

                    self::$cmd_cancollapse_button = !empty($_POST['dcckeditor_cancollapse_button']);
                    My::settings()->put('cancollapse_button', self::$cmd_cancollapse_button, App::blogWorkspace()::NS_BOOL);

                    self::$cmd_format_select = !empty($_POST['dcckeditor_format_select']);
                    My::settings()->put('format_select', self::$cmd_format_select, App::blogWorkspace()::NS_BOOL);

                    // default tags : p;h1;h2;h3;h4;h5;h6;pre;address
                    self::$cmd_format_tags = 'p;h1;h2;h3;h4;h5;h6;pre;address';
                    $allowed_tags          = explode(';', self::$cmd_format_tags);

                    $format_tags = isset($_POST['dcckeditor_format_tags']) && is_string($format_tags = $_POST['dcckeditor_format_tags']) ? $format_tags : '';
                    if ($format_tags !== '') {
                        $tags     = explode(';', $format_tags);
                        $new_tags = true;
                        foreach ($tags as $tag) {
                            if (!in_array($tag, $allowed_tags, true)) {
                                $new_tags = false;

                                break;
                            }
                        }

                        if ($new_tags) {
                            self::$cmd_format_tags = $format_tags;
                        }
                    }

                    My::settings()->put('format_tags', self::$cmd_format_tags, App::blogWorkspace()::NS_STRING);

                    self::$cmd_table_button = !empty($_POST['dcckeditor_table_button']);
                    My::settings()->put('table_button', self::$cmd_table_button, App::blogWorkspace()::NS_BOOL);

                    self::$cmd_clipboard_buttons = !empty($_POST['dcckeditor_clipboard_buttons']);
                    My::settings()->put('clipboard_buttons', self::$cmd_clipboard_buttons, App::blogWorkspace()::NS_BOOL);

                    self::$cmd_action_buttons = !empty($_POST['dcckeditor_action_buttons']);
                    My::settings()->put('action_buttons', self::$cmd_action_buttons, App::blogWorkspace()::NS_BOOL);

                    self::$cmd_disable_native_spellchecker = !empty($_POST['dcckeditor_disable_native_spellchecker']);
                    My::settings()->put('disable_native_spellchecker', self::$cmd_disable_native_spellchecker, App::blogWorkspace()::NS_BOOL);
                }

                App::backend()->notices()->addSuccessNotice(__('The configuration has been updated.'));
                My::redirect();
            } catch (Exception $e) {
                App::error()->add($e->getMessage());
            }
        }

        return true;
    }

    public static function render(): void
    {
        if (!self::status()) {
            return;
        }

        App::backend()->page()->openModule(My::name());

        echo
        App::backend()->page()->breadcrumb([
            __('Plugins')  => '',
            __('CKEditor') => '',
        ]) .
        App::backend()->notices()->getNotices();

        if (self::$editor_is_admin) {
            $fields = [];

            $active = self::$editor_cke_active;

            // Activation
            $fields[] = (new Fieldset())
                ->legend(new Legend(__('Plugin activation')))
                ->fields([
                    (new Para())
                        ->items([
                            (new Checkbox('dcckeditor_active', $active))
                                ->value(1)
                                ->label((new Label(__('Enable CKEditor plugin'), Label::INSIDE_TEXT_AFTER))),
                        ]),
                ]);

            if ($active) {
                $alignment      = self::$cmd_alignment_buttons;
                $list           = self::$cmd_list_buttons;
                $color          = self::$cmd_textcolor_button;
                $background     = self::$cmd_background_textcolor_button;
                $colors         = self::$cmd_custom_color_list;
                $colors_per_row = self::$cmd_colors_per_row ?: 6;
                $collapse       = self::$cmd_cancollapse_button;
                $format         = self::$cmd_format_select;
                $format_tags    = self::$cmd_format_tags;
                $table          = self::$cmd_table_button;
                $clipboard      = self::$cmd_clipboard_buttons;
                $action         = self::$cmd_action_buttons;
                $nospellchecker = self::$cmd_disable_native_spellchecker;

                // Settings
                $fields[] = (new Fieldset())
                    ->legend(new Legend(__('Options')))
                    ->fields([
                        (new Para())
                            ->items([
                                (new Checkbox('dcckeditor_alignment_buttons', $alignment))
                                    ->value(1)
                                    ->label((new Label(__('Add alignment buttons'), Label::INSIDE_TEXT_AFTER))),
                            ]),
                        (new Para())
                            ->items([
                                (new Checkbox('dcckeditor_list_buttons', $list))
                                    ->value(1)
                                    ->label((new Label(__('Add lists buttons'), Label::INSIDE_TEXT_AFTER))),
                            ]),
                        (new Para())
                            ->items([
                                (new Checkbox('dcckeditor_textcolor_button', $color))
                                    ->value(1)
                                    ->label((new Label(__('Add text color button'), Label::INSIDE_TEXT_AFTER))),
                            ]),
                        (new Para())
                            ->items([
                                (new Checkbox('dcckeditor_background_textcolor_button', $background))
                                    ->value(1)
                                    ->label((new Label(__('Add background text color button'), Label::INSIDE_TEXT_AFTER))),
                            ]),
                        (new Fieldset())
                            ->legend((new Legend(__('Custom colors list:')))->id('dcckeditor_custom_color_list_label'))
                            ->fields([
                                (new Para())
                                    ->class('area')
                                    ->items([
                                        (new Textarea('dcckeditor_custom_color_list', Html::escapeHTML($colors)))
                                        ->ariaLabelledby('dcckeditor_custom_color_list_label')
                                            ->cols(60)
                                            ->rows(5),
                                    ]),
                                (new Note())
                                    ->class('form-note')
                                    ->items([
                                        (new Text(null, __('Add colors without # separated by a comma.'))),
                                    ]),
                                (new Note())
                                    ->class('form-note')
                                    ->items([
                                        (new Text(null, __('Leave empty to use the default palette:'))),
                                        (new Text('blockquote', '<pre><code>1abc9c,2ecc71,3498db,9b59b6,4e5f70,f1c40f,16a085,27ae60,2980b9,8e44ad,2c3e50,f39c12,e67e22,e74c3c,ecf0f1,95a5a6,dddddd,ffffff,d35400,c0392b,bdc3c7,7f8c8d,999999,000000</code></pre>')),
                                    ]),
                                (new Note())
                                    ->class('form-note')
                                    ->items([
                                        (new Text(null, __('Example of custom color list:'))),
                                        (new Text('blockquote', '<pre><code>000,800000,8b4513,2f4f4f,008080,000080,4b0082,696969,b22222,a52a2a,daa520,006400,40e0d0,0000cd,800080,808080,f00,ff8c00,ffd700,008000,0ff,00f,ee82ee,a9a9a9,ffa07a,ffa500,ffff00,00ff00,afeeee,add8e6,dda0dd,d3d3d3,fff0f5,faebd7,ffffe0,f0fff0,f0ffff,f0f8ff,e6e6fa,fff</code></pre>')),
                                    ]),
                            ]),
                        (new Para())
                            ->items([
                                (new Number('dcckeditor_colors_per_row', 4, 16, $colors_per_row))
                                    ->default(6)
                                    ->label((new Label(__('Colors per row in palette:'), Label::INSIDE_TEXT_BEFORE))),
                            ]),
                        (new Note())
                            ->class('form-note')
                            ->text(__('Valid range: 4 to 16')),
                        (new Para())
                            ->items([
                                (new Checkbox('dcckeditor_cancollapse_button', $collapse))
                                    ->value(1)
                                    ->label((new Label(__('Add collapse button'), Label::INSIDE_TEXT_AFTER))),
                            ]),
                        (new Para())
                            ->items([
                                (new Checkbox('dcckeditor_format_select', $format))
                                    ->value(1)
                                    ->label((new Label(__('Add format selection'), Label::INSIDE_TEXT_AFTER))),
                            ]),
                        (new Fieldset())
                            ->legend((new Legend(__('Custom formats')))->id('dcckeditor_format_tags_label'))
                            ->fields([
                                (new Para())
                                    ->items([
                                        (new Input('dcckeditor_format_tags'))
                                            ->ariaLabelledby('dcckeditor_format_tags_label')
                                            ->size(100)
                                            ->maxlength(255)
                                            ->value(Html::escapeHTML($format_tags))
                                            ->placeholder('p;h1;h2;h3;h4;h5;h6;pre;address'),
                                    ]),
                                (new Note())
                                    ->class('form-note')
                                    ->text(__('Default formats are: <code>p;h1;h2;h3;h4;h5;h6;pre;address</code>.')),
                            ]),
                        (new Para())
                            ->items([
                                (new Checkbox('dcckeditor_table_button', $table))
                                    ->value(1)
                                    ->label((new Label(__('Add table button'), Label::INSIDE_TEXT_AFTER))),
                            ]),
                        (new Para())
                            ->items([
                                (new Checkbox('dcckeditor_clipboard_buttons', $clipboard))
                                    ->value(1)
                                    ->label((new Label(__('Add clipboard buttons'), Label::INSIDE_TEXT_AFTER))),
                            ]),
                        (new Note())
                            ->class('form-note')
                            ->text(__('Copy, Paste, Paste Text, Paste from Word')),
                        (new Para())
                            ->items([
                                (new Checkbox('dcckeditor_action_buttons', $action))
                                    ->value(1)
                                    ->label((new Label(__('Add undo/redo buttons'), Label::INSIDE_TEXT_AFTER))),
                            ]),
                        (new Para())
                            ->items([
                                (new Checkbox('dcckeditor_disable_native_spellchecker', $nospellchecker))
                                    ->value(1)
                                    ->label((new Label(__('Disables the built-in spell checker if the browser provides one'), Label::INSIDE_TEXT_AFTER))),
                            ]),
                    ]);
            }

            // Buttons
            $fields[] = (new Para())
                ->class('form-buttons')
                ->items([
                    ...My::hiddenFields(),
                    (new Submit(['saveconfig'], __('Save configuration'))),
                    (new Button(['back'], __('Back')))
                        ->class(['go-back', 'reset', 'hidden-if-no-js']),
                ]);

            // Render form
            echo (new Form('dcckeditor_form'))
                ->method('post')
                ->action(App::backend()->getPageURL())
                ->fields($fields)
            ->render();
        }

        App::backend()->page()->helpBlock(My::id());

        App::backend()->page()->closeModule();
    }
}
