import {Schema} from "prosemirror-model";
import {splitListItem} from "prosemirror-schema-list";
import {
  paragraph, blockquote, hr as horizontal_rule, heading, pre as code_block, br as hard_break, icon
} from "./schema/core.mjs";
import {ol as ordered_list, ul as bullet_list, li as list_item} from "./schema/lists.mjs";
import {builtInTableNodes} from "./schema/tables.mjs";
import {selection} from "./schema/inserts.mjs";
import {
  dl, dl_group, dt, dd, fieldset, legend, picture, audio, video, track, source, object, figure, figcaption, small, ruby,
  rp, rt, iframe
} from "./schema/other.mjs";
import {
  superscript, subscript, span, font, size, color, cite, em, strong, underline, strikethrough, code
} from "./schema/marks.mjs";
import ImageNode from "./schema/image-node.mjs";
import LinkMark from "./schema/link-mark.mjs";
import ImageLinkNode from "./schema/image-link-node.mjs";
import SecretNode from "./schema/secret-node.mjs";
import AttributeCapture from "./schema/attribute-capture.mjs";
import DisclosureWidget from "./schema/disclosure.mjs";

const doc = {
  content: "block+"
};

const text = {
  group: "inline"
};

const secret = SecretNode.make();
const link = LinkMark.make();
const image = ImageNode.make();
const imageLink = ImageLinkNode.make();

export const nodes = {
  // Core Nodes.
  doc, text, paragraph, blockquote, secret, horizontal_rule, heading, code_block, image_link: imageLink, image, icon,
  hard_break,

  // Lists.
  ordered_list, bullet_list, list_item,

  // Disclosure
  ...DisclosureWidget.nodes,

  // Tables
  ...builtInTableNodes,

  // Inserts
  selection,

  // Misc.
  dl, dl_group, dt, dd, fieldset, legend, picture, audio, video, track, source, object, figure,
  figcaption, small, ruby, rp, rt, iframe
};

export const marks = {
  superscript, subscript, span, font, size, color, cite, link, em, strong, underline, strikethrough, code
};

// Auto-generated specifications for HTML preservation.
["header", "main", "section", "article", "aside", "nav", "footer", "div", "address"].forEach(tag => {
  nodes[tag] = {
    content: "block*",
    group: "block",
    defining: true,
    parseDOM: [{tag}],
    toDOM: () => [tag, 0]
  };
});

["abbr", "mark", "q", "time", "ins"].forEach(tag => {
  marks[tag] = {
    parseDOM: [{tag}],
    toDOM: () => [tag, 0]
  };
});

const all = Object.values(nodes).concat(Object.values(marks));
const capture = new AttributeCapture();
all.forEach(capture.attributeCapture.bind(capture));

export const schema = new Schema({nodes, marks});

/* -------------------------------------------- */
/*  Handlers                                    */
/* -------------------------------------------- */

schema.nodes.list_item.split = splitListItem(schema.nodes.list_item);
schema.nodes.secret.split = SecretNode.split;
schema.marks.link.onClick = LinkMark.onClick;
schema.nodes.image_link.onClick = ImageLinkNode.onClick;
