import "jest";
import { DOMParser, DOMSerializer, Node } from "prosemirror-model";
import { compose } from "../../compose";
import { RefsNode, schema } from "../../schema";
import * as dom from "../../util/dom";
import { el } from "../../util/dom";
import "../../__specs__/expect.toMatchNode";
import { AttachmentAttrs, domDataAttrAttrs, domDataAttrType } from "../schema";

const serializer = DOMSerializer.fromSchema(schema);
const parser = DOMParser.fromSchema(schema);
const { p, at } = compose;
const atRaw = (attrs: AttachmentAttrs) => schema.nodes.at.createChecked(attrs);

function domParse(domNode: dom.Node): Node {
  return parser.parse(el("div", domNode)).child(0);
}

function domEncode(node: Node): dom.Node {
  return serializer.serializeNode(node);
}

function roundtrip(node: Node): Node {
  return domParse(domEncode(node));
}

/**
 * Test that a ProseMirror node can be round-tripped to DOM and back
 * losslessly.
 */
function testDomRoundtrip({ node }: RefsNode) {
  expect(roundtrip(node)).toMatchNode(node);
}

describe("DOM roundtrip", () => {
  it("ignores invalid attrs JSON", () => {
    const elem = el("div");
    elem.setAttribute(domDataAttrType, "at");
    elem.setAttribute(domDataAttrAttrs, "this-is-not-json");
    expect(domParse(elem)).toMatchNode(p().node);
  });

  describe("attrs", () => {
    describe("id", () => {
      it("valid", () => testDomRoundtrip(at({ id: "0000" })));
      it("ignores if missing id", () => {
        const elem = el("div");
        elem.setAttribute(domDataAttrType, "at");
        elem.setAttribute(domDataAttrAttrs, JSON.stringify({}));
        expect(domParse(elem)).toMatchNode(p().node);
      });
    });

    describe("naturalSize", () => {
      it("valid", () => testDomRoundtrip(at({ id: "0000", naturalSize: { width: 10, height: 20 } })));
      it("missing", () => testDomRoundtrip(at({ id: "0000" })));
      it("ignores if missing height", () => {
        expect(roundtrip(atRaw({ id: "0000", nw: 10 }))).toMatchNode(at({ id: "0000" }).node);
      });
    });

    describe("name", () => {
      it("valid", () => testDomRoundtrip(at({ id: "0000", name: "image.jpg" })));
      it("missing", () => testDomRoundtrip(at({ id: "0000" })));
    });

    describe("type", () => {
      it("IMAGE", () => testDomRoundtrip(at({ id: "0000", type: "image/jpg" })));
      it("missing", () => testDomRoundtrip(at({ id: "0000" })));
    });

    describe("hidePreview", () => {
      it("true", () => testDomRoundtrip(at({ id: "0000", hidePreview: true })));
      it("false", () => testDomRoundtrip(at({ id: "0000", hidePreview: false })));
      it("missing", () => testDomRoundtrip(at({ id: "0000" })));
    });
  });
});
