"""cubicweb-editorjs application package

Add editorjs format for RichString
"""

import copy

from logilab.common.decorators import monkeypatch

from cubicweb import cwconfig, entity
from cubicweb.web import formfields, formwidgets as fw
from cubicweb.web.views import forms

from yams import constraints

NEW_PERSISTENT_OPTIONS = []
for option in cwconfig.PERSISTENT_OPTIONS:
    if option[0] == "default-text-format":
        option = ("default-text-format", copy.deepcopy(option[1]))
        option[1]["choices"] += ("application/vnd.cubicweb.editorjs",)
    NEW_PERSISTENT_OPTIONS.append(option)


formfields.EditableFileField.editable_formats += ("application/vnd.cubicweb.editorjs",)

forms.FieldsForm.needs_js += ("cubes.editorjs.js",)

constraints.FormatConstraint.regular_formats += ("application/vnd.cubicweb.editorjs",)


def use_editorjs(rich_text_field, form):
    """return True if editor.js should be used to edit entity's attribute named
    `attr`
    """
    return rich_text_field.format(form) == "application/vnd.cubicweb.editorjs"


class EditorJS(fw.TextArea):
    """EditorJS enabled <textarea>, will return a unicode string containing
    HTML formated text.
    """

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.attrs["cubicweb:type"] = "editorjs"

    def _render(self, form, field, renderer):
        return super()._render(form, field, renderer)


old_get_widget = formfields.RichTextField.get_widget


@monkeypatch(formfields.RichTextField)
def get_widget(self, form):
    if self.widget is None:
        if use_editorjs(self, form):
            return EditorJS()
    return old_get_widget(self, form)


old_get_format_field = formfields.RichTextField.get_format_field


@monkeypatch(formfields.RichTextField)
def get_format_field(self, form):
    if self.format_field:
        return self.format_field
    # we have to cache generated field since it's use as key in the
    # context dictionary
    req = form._cw
    try:
        return req.data[self]
    except KeyError:
        fkwargs = {"eidparam": self.eidparam, "role": self.role}
        if use_editorjs(self, form):
            fkwargs["widget"] = fw.HiddenInput()
            fkwargs["value"] = "application/vnd.cubicweb.editorjs"
            fkwargs["eidparam"] = self.eidparam
            field = formfields.StringField(name=self.name + "_format", **fkwargs)
            req.data[self] = field
            return field
        else:
            return old_get_format_field(self, form)


old_printable_value = entity.Entity.printable_value


@monkeypatch(entity.Entity)
def printable_value(
    self,
    attr,
    value=entity._marker,
    attrtype=None,
    format="text/html",
    displaytime=True,
):  # XXX cw_printable_value
    """return a displayable value (i.e. unicode string) which may contains
    html tags
    """
    attr = str(attr)
    if value is entity._marker:
        value = getattr(self, attr)
    if isinstance(value, str):
        value = value.strip()
    if value is None or value == "":  # don't use "not", 0 is an acceptable value
        return ""
    if attrtype is None:
        attrtype = self.e_schema.destination(attr)
    props = self.e_schema.rdef(attr)
    if attrtype == "String":
        # internalinalized *and* formatted string such as schema
        # description...
        if props.internationalizable:
            value = self._cw._(value)
        attrformat = self.cw_attr_metadata(attr, "format")
        if attrformat:
            if attrformat == "application/vnd.cubicweb.editorjs":
                if format == "text/plain":
                    return "EditorJS content"
                self._cw.add_js("cubes.editorjs.js")
                return f'<textarea cubicweb:type="editorjs" cubicweb:mode="read">{value}</textarea>'
    return old_printable_value(self, attr, value, attrtype, format, displaytime)


def includeme(config):
    pass
