import { assetsIcon } from "./icons";
import $ from "jquery";
import { cardsDefaultStyle } from "./components/cards/CardsStyle";
export default (editor, opts = {}) => {
  const cmd = editor.Commands;
  var uploadHeader;
  var uploadFile;
  const { modalTitle, commands, types } = opts;

  cmd.add(commands.button, {
    run(editor, sender, opts = {}) {
      this.editor = editor;

      this.options = opts;
      this.target = opts.target || editor.getSelected();
      const target = this.target;

      if (target && target.get("editable")) {
        this.showCustomButton(target);
      }
    },

    stop(editor) {
      editor.Modal.close();
    },

    showCustomButton(target) {
      const { editor, options } = this;
      const title = options.title || modalTitle;

      const am = editor.AssetManager;
      const content = am.getContainer();
      am.setTarget(target);

      let assets = assetsIcon.filter((asset) => {
        return asset.type == types.button;
      });
      am.render(assets);
      const assetEl = am.getAssetsEl();
      if (assetEl) {
        assetEl.className = "gjs-am-assets gjs-am-assets--button";
      }
      editor.Modal.open({ title, content })
        .getModel()
        .once("change:open", () => editor.stopCommand(this.id));
      uploadHeader = $(content.querySelector(".gjs-am-assets-header"));
      uploadFile = $(content.querySelector(".gjs-am-file-uploader"));
      uploadFile.hide();
      uploadHeader.hide();
    },
  });
  cmd.add(commands.card, {
    run(editor, sender, opts = {}) {
      this.editor = editor;

      this.options = opts;
      this.target = opts.target || editor.getSelected();
      const target = this.target;

      if (target && target.get("editable")) {
        this.showCustomButton(target);
      }
    },

    stop(editor) {
      editor.Modal.close();
    },

    showCustomButton(target) {
      const { editor, options } = this;
      const title = options.title || modalTitle;

      const am = editor.AssetManager;
      const content = am.getContainer();
      am.setTarget(target);

      let assets = assetsIcon.filter((asset) => {
        return asset.type == types.card;
      });
      am.render(assets);
      const assetEl = am.getAssetsEl();
      if (assetEl) {
        assetEl.className = "gjs-am-assets gjs-am-assets--card";
      }
      editor.Modal.open({ title, content })
        .getModel()
        .once("change:open", () => editor.stopCommand(this.id));
      uploadHeader = $(content.querySelector(".gjs-am-assets-header"));
      uploadFile = $(content.querySelector(".gjs-am-file-uploader"));
      uploadFile.hide();
      uploadHeader.hide();
    },
  });

  // Sections Commands
  const {
    sectionsModalTitle,
    codeViewOptions,
    commandDrapCodeSectionsSectionCode,
    refs,
    sectionsPlaceholderContent,
    sections,
  } = opts;
  const { keyDrapCodeSectionsCustomCode, drapcodeSectionRef } = refs;

  const appendToContent = (target, content) => {
    if (content instanceof HTMLElement) {
      target.appendChild(content);
    } else if (content) {
      target.insertAdjacentHTML("beforeend", content);
    }
  };

  let drapcodeSectionsSelectList = [];

  cmd.add(commands.drapcode_sections_custom_code, {
    keyDrapCodeSectionsCustomCode,

    run(editor, sender, opts = {}) {
      this.editor = editor;
      this.options = opts;
      this.target = opts.target || editor.getSelected();
      const target = this.target;

      if (target && target.get("editable")) {
        this.showDrapcodeSectionsCode(target);
      }
    },

    stop(editor) {
      editor.Modal.close();
    },

    async showDrapcodeSectionsCode(target) {
      const { editor, options } = this;
      const title = options.title || sectionsModalTitle;

      drapcodeSectionsSelectList = sections;
      const content = this.getContent();
      const code = target.get(keyDrapCodeSectionsCustomCode) || "";
      editor.Modal.open({ title, content })
        .getModel()
        .once("change:open", () => editor.stopCommand(this.id));
      this.getCodeViewer().setContent(code);
    },
    getPreContent() {},
    getPostContent() {},
    getBreakPoint() {
      const contentBreak = document.createElement("br");
      return contentBreak;
    },

    getContent() {
      const { editor } = this;
      const content = document.createElement("div");
      const galleryDiv = document.createElement("div");

      const codeViewer = this.getCodeViewer();
      const pfx = editor.getConfig("stylePrefix");

      content.className = `${pfx}drapcode-sections`;
      galleryDiv.className = `${pfx}drapcode-sections-gallery-div`;
      galleryDiv.id = `${pfx}drapcode-sections-gallery-div`;

      appendToContent(content, this.getPreContent());
      appendToContent(galleryDiv, this.getPreContent());

      this.loadSectionList(drapcodeSectionsSelectList, galleryDiv);

      let childComponents = [galleryDiv, codeViewer.getElement()];
      this.appendChildComponentsToContent(content, childComponents);

      appendToContent(galleryDiv, this.getPostContent());
      appendToContent(content, this.getPostContent());
      codeViewer.refresh();
      setTimeout(() => codeViewer.focus(), 0);
      return content;
    },

    appendChildComponentsToContent(content, childrens) {
      childrens.forEach((child) => {
        if (child.id === "" || child.id === undefined) {
          child.style = `display: none; visibility: hidden; height: 0vh;`;
          content.appendChild(child);
        } else {
          content.appendChild(child);

          if (!child.className.includes("no-break")) {
            content.appendChild(this.getBreakPoint());
          }
          if (child.className.includes("two-break")) {
            content.appendChild(this.getBreakPoint());
          }
        }
      });
    },

    handleSave() {
      const { editor, target } = this;
      if (this.getCodeViewer().getContent() === "") {
        //Set Default Section When No Section is Selected.
        this.getCodeViewer().setContent(sectionsPlaceholderContent);
      }
      const code = this.getCodeViewer().getContent();
      target.set(keyDrapCodeSectionsCustomCode, code);
      editor.Modal.close();
    },

    async loadSectionList(drapcodeSectionsSelectList, galleryDiv) {
      const { editor, options } = this;
      const pfx = editor.getConfig("stylePrefix");

      galleryDiv.innerHTML = "";
      drapcodeSectionsSelectList.forEach((element) => {
        let attrTitle = document.createAttribute("title");
        attrTitle.value = `Click to add Section ${element.label} to Canvas`;

        let componentImage = document.createElement("div");
        componentImage.id = `${pfx}drapcode-sections-${element.value}`;
        componentImage.className = `${pfx}drapcode-sections`;
        componentImage.setAttributeNode(attrTitle);
        componentImage.innerHTML = `

        <div class="preview-drapcode-sections">
          <span class="inner-html">
            <div class="mkp-components">
            ${element.view}
            </div>
          </span>
          <span class="label text-center">${element.label}</span>
        </div>

        `;
        //Added Double Click Event to Add Selected Section on Canvas
        componentImage.onclick = () => {
          this.handleClick(element, drapcodeSectionsSelectList, galleryDiv);
          this.handleSave();
        };

        galleryDiv.appendChild(componentImage);
      });
    },

    async handleClick(
      selectedSectionSection,
      drapcodeSectionsSelectList,
      galleryDiv
    ) {
      const { editor, options } = this;
      const pfx = editor.getConfig("stylePrefix");
      const sectionComponents = document.querySelectorAll(
        `div.${pfx}drapcode-sections`
      );
      const selectedSectionComponent = document.querySelector(
        `div[id=${pfx}drapcode-sections-${selectedSectionSection.value}]`
      );
      const selectCompContainer =
        selectedSectionComponent.querySelector(`.inner-html`);

      sectionComponents.forEach((sectionComp) => {
        let sectionCompLabelBtn = sectionComp.querySelector(`.inner-html`);
        sectionCompLabelBtn.classList.remove("selected-drapcode-section-comp");
      });
      selectCompContainer.classList.add("selected-drapcode-section-comp");

      if (selectedSectionComponent) {
        let mixedContent = selectedSectionSection.code;
        this.getCodeViewer().setContent(mixedContent);
      } else {
        this.getCodeViewer().setContent(sectionsPlaceholderContent);
      }
    },

    getCodeViewer() {
      const { editor } = this;

      if (!this.codeViewer) {
        this.codeViewer = editor.CodeManager.createViewer({
          codeName: "htmlmixed",
          theme: "hopscotch",
          readOnly: 0,
          ...codeViewOptions,
        });
      }

      return this.codeViewer;
    },

    ...commandDrapCodeSectionsSectionCode,
  });

  // Carousels Commands
  const {
    carouselsModalTitle,
    carouselsCodeViewOptions,
    commandDrapCodeCarouselsCarouselCode,
    carouselsPlaceholderContent,
    carousels,
  } = opts;
  const { keyDrapCodeCarouselsCustomCode, drapcodeCarouselRef } = refs;

  let drapcodeCarouselsSelectList = [];

  cmd.add(commands.drapcode_carousels_custom_code, {
    keyDrapCodeCarouselsCustomCode,

    run(editor, sender, opts = {}) {
      this.editor = editor;
      this.options = opts;
      this.target = opts.target || editor.getSelected();
      const target = this.target;

      if (target && target.get("editable")) {
        this.showDrapcodeCarouselsCode(target);
      }
    },

    stop(editor) {
      editor.Modal.close();
    },

    async showDrapcodeCarouselsCode(target) {
      const { editor, options } = this;
      const title = options.title || carouselsModalTitle;

      drapcodeCarouselsSelectList = carousels;
      const content = this.getContent();
      const code = target.get(keyDrapCodeCarouselsCustomCode) || "";
      editor.Modal.open({ title, content })
        .getModel()
        .once("change:open", () => editor.stopCommand(this.id));
      this.getCodeViewerForCarousel().setContent(code);
    },
    getPreContent() {},
    getPostContent() {},
    getBreakPoint() {
      const contentBreak = document.createElement("br");
      return contentBreak;
    },

    getContent() {
      const { editor } = this;
      const content = document.createElement("div");
      const galleryDiv = document.createElement("div");

      const codeViewer = this.getCodeViewerForCarousel();
      const pfx = editor.getConfig("stylePrefix");

      content.className = `${pfx}drapcode-carousels`;
      galleryDiv.className = `${pfx}drapcode-carousels-gallery-div`;
      galleryDiv.id = `${pfx}drapcode-carousels-gallery-div`;

      appendToContent(content, this.getPreContent());
      appendToContent(galleryDiv, this.getPreContent());

      this.loadCarouselList(drapcodeCarouselsSelectList, galleryDiv);

      let childComponents = [galleryDiv, codeViewer.getElement()];
      this.appendChildComponentsToContent(content, childComponents);

      appendToContent(galleryDiv, this.getPostContent());
      appendToContent(content, this.getPostContent());
      codeViewer.refresh();
      setTimeout(() => codeViewer.focus(), 0);
      return content;
    },

    appendChildComponentsToContent(content, childrens) {
      childrens.forEach((child) => {
        if (child.id === "" || child.id === undefined) {
          child.style = `display: none; visibility: hidden; height: 0vh;`;
          content.appendChild(child);
        } else {
          content.appendChild(child);

          if (!child.className.includes("no-break")) {
            content.appendChild(this.getBreakPoint());
          }
          if (child.className.includes("two-break")) {
            content.appendChild(this.getBreakPoint());
          }
        }
      });
    },

    handleSaveForCarousel() {
      const { editor, target } = this;
      if (this.getCodeViewerForCarousel().getContent() === "") {
        //Set Default Carousel When No Carousel is Selected.
        this.getCodeViewerForCarousel().setContent(carouselsPlaceholderContent);
      }
      const code = this.getCodeViewerForCarousel().getContent();
      target.set(keyDrapCodeCarouselsCustomCode, code);
      editor.Modal.close();
    },

    async loadCarouselList(drapcodeCarouselsSelectList, galleryDiv) {
      const { editor, options } = this;
      const pfx = editor.getConfig("stylePrefix");

      galleryDiv.innerHTML = "";
      drapcodeCarouselsSelectList.forEach((element) => {
        let attrTitle = document.createAttribute("title");
        attrTitle.value = `Click to add ${element.label} to Canvas`;

        let componentImage = document.createElement("div");
        componentImage.id = `${pfx}drapcode-carousels-${element.value}`;
        componentImage.className = `${pfx}drapcode-carousels`;
        componentImage.setAttributeNode(attrTitle);
        componentImage.innerHTML = `
  
          <div class="preview-drapcode-carousels">
            <span class="inner-html">
              <div class="mkp-components">
              ${element.view}
              </div>
            </span>
            <span class="label text-center">${element.label}</span>
          </div>
  
          `;
        //Added Double Click Event to Add Selected Carousel on Canvas
        componentImage.onclick = () => {
          this.handleClickForCarousel(
            element,
            drapcodeCarouselsSelectList,
            galleryDiv
          );
          this.handleSaveForCarousel();
        };

        galleryDiv.appendChild(componentImage);
      });
    },

    async handleClickForCarousel(
      selectedCarouselCarousel,
      drapcodeCarouselsSelectList,
      galleryDiv
    ) {
      const { editor, options } = this;
      const pfx = editor.getConfig("stylePrefix");
      const carouselComponents = document.querySelectorAll(
        `div.${pfx}drapcode-carousels`
      );
      const selectedCarouselComponent = document.querySelector(
        `div[id=${pfx}drapcode-carousels-${selectedCarouselCarousel.value}]`
      );
      const selectCompContainer =
        selectedCarouselComponent.querySelector(`.inner-html`);

      carouselComponents.forEach((carouselComp) => {
        let carouselCompLabelBtn = carouselComp.querySelector(`.inner-html`);
        carouselCompLabelBtn.classList.remove(
          "selected-drapcode-carousel-comp"
        );
      });
      selectCompContainer.classList.add("selected-drapcode-carousel-comp");

      if (selectedCarouselComponent) {
        let mixedContent = selectedCarouselCarousel.code;
        this.getCodeViewerForCarousel().setContent(mixedContent);
      } else {
        this.getCodeViewerForCarousel().setContent(carouselsPlaceholderContent);
      }
    },

    getCodeViewerForCarousel() {
      const { editor } = this;

      if (!this.codeViewer) {
        this.codeViewer = editor.CodeManager.createViewer({
          codeName: "htmlmixed",
          theme: "hopscotch",
          readOnly: 0,
          ...carouselsCodeViewOptions,
        });
      }

      return this.codeViewer;
    },

    ...commandDrapCodeCarouselsCarouselCode,
  });

  // Cards Commands
  const {
    cardsModalTitle,
    cardsCodeViewOptions,
    commandDrapCodeCardsCardCode,
    cardsPlaceholderContent,
    cards,
  } = opts;
  const { keyDrapCodeCardsCustomCode, drapcodeCardRef } = refs;

  let drapcodeCardsSelectList = [];

  cmd.add(commands.drapcode_cards_custom_code, {
    keyDrapCodeCardsCustomCode,

    run(editor, sender, opts = {}) {
      this.editor = editor;
      this.options = opts;
      this.target = opts.target || editor.getSelected();
      const target = this.target;

      if (target && target.get("editable")) {
        this.showDrapcodeCardsCode(target);
      }
    },

    stop(editor) {
      editor.Modal.close();
    },

    async showDrapcodeCardsCode(target) {
      const { editor, options } = this;
      const title = options.title || cardsModalTitle;

      drapcodeCardsSelectList = cards;
      const content = this.getContent();
      const code = target.get(keyDrapCodeCardsCustomCode) || "";
      editor.Modal.open({ title, content })
        .getModel()
        .once("change:open", () => editor.stopCommand(this.id));
      this.getCodeViewerForCard().setContent(code);
    },
    getPreContent() {},
    getPostContent() {},
    getBreakPoint() {
      const contentBreak = document.createElement("br");
      return contentBreak;
    },

    getContent() {
      const { editor } = this;
      const content = document.createElement("div");
      const galleryDiv = document.createElement("div");

      const codeViewer = this.getCodeViewerForCard();
      const pfx = editor.getConfig("stylePrefix");

      content.className = `${pfx}drapcode-cards`;
      galleryDiv.className = `${pfx}drapcode-cards-gallery-div`;
      galleryDiv.id = `${pfx}drapcode-cards-gallery-div`;

      appendToContent(content, this.getPreContent());
      appendToContent(galleryDiv, this.getPreContent());

      this.loadCardList(drapcodeCardsSelectList, galleryDiv);

      let childComponents = [galleryDiv, codeViewer.getElement()];
      this.appendChildComponentsToContent(content, childComponents);

      appendToContent(galleryDiv, this.getPostContent());
      appendToContent(content, this.getPostContent());
      codeViewer.refresh();
      setTimeout(() => codeViewer.focus(), 0);
      return content;
    },

    appendChildComponentsToContent(content, childrens) {
      childrens.forEach((child) => {
        if (child.id === "" || child.id === undefined) {
          child.style = `display: none; visibility: hidden; height: 0vh;`;
          content.appendChild(child);
        } else {
          content.appendChild(child);

          if (!child.className.includes("no-break")) {
            content.appendChild(this.getBreakPoint());
          }
          if (child.className.includes("two-break")) {
            content.appendChild(this.getBreakPoint());
          }
        }
      });
    },

    handleSaveForCard() {
      const { editor, target } = this;
      if (this.getCodeViewerForCard().getContent() === "") {
        //Set Default Card When No Card is Selected.
        this.getCodeViewerForCard().setContent(cardsPlaceholderContent);
      }
      const code = this.getCodeViewerForCard().getContent();
      //?INFO: Uncomment the line below to wrap a component container around the code
      // target.set(keyDrapCodeCardsCustomCode, code);
      target.replaceWith(code);
      editor.Modal.close();
    },

    async loadCardList(drapcodeCardsSelectList, galleryDiv) {
      const { editor, options } = this;
      const pfx = editor.getConfig("stylePrefix");

      galleryDiv.innerHTML = "";
      drapcodeCardsSelectList.forEach((element) => {
        let attrTitle = document.createAttribute("title");
        attrTitle.value = `Click to add ${element.label} to Canvas`;

        let componentImage = document.createElement("div");
        componentImage.id = `${pfx}drapcode-cards-${element.value}`;
        componentImage.className = `${pfx}drapcode-cards-gallery-img`;
        componentImage.setAttributeNode(attrTitle);
        componentImage.innerHTML = `
  
          <div class="preview-drapcode-cards">
            <span class="inner-html">
              <div class="mkp-components">
              ${element.view}
              </div>
            </span>
            <!-- <span class="label text-center">${element.label}</span> -->
          </div>
  
          `;
        //Added Double Click Event to Add Selected Card on Canvas
        componentImage.onclick = () => {
          this.handleClickForCard(element, drapcodeCardsSelectList, galleryDiv);
          this.handleSaveForCard();
        };

        galleryDiv.appendChild(componentImage);
      });
    },

    async handleClickForCard(
      selectedCardCard,
      drapcodeCardsSelectList,
      galleryDiv
    ) {
      const { editor, options } = this;
      const pfx = editor.getConfig("stylePrefix");
      const cardComponents = document.querySelectorAll(
        `div.${pfx}drapcode-cards`
      );
      const selectedCardComponent = document.querySelector(
        `div[id=${pfx}drapcode-cards-${selectedCardCard.value}]`
      );
      const selectCompContainer =
        selectedCardComponent.querySelector(`.inner-html`);

      cardComponents.forEach((cardComp) => {
        let cardCompLabelBtn = cardComp.querySelector(`.inner-html`);
        cardCompLabelBtn.classList.remove("selected-drapcode-card-comp");
      });
      selectCompContainer.classList.add("selected-drapcode-card-comp");

      if (selectedCardComponent) {
        let mixedContent = selectedCardCard.code + cardsDefaultStyle;
        this.getCodeViewerForCard().setContent(mixedContent);
      } else {
        this.getCodeViewerForCard().setContent(
          cardsPlaceholderContent + cardsDefaultStyle
        );
      }
    },

    getCodeViewerForCard() {
      const { editor } = this;

      if (!this.codeViewer) {
        this.codeViewer = editor.CodeManager.createViewer({
          codeName: "htmlmixed",
          theme: "hopscotch",
          readOnly: 0,
          ...cardsCodeViewOptions,
        });
      }

      return this.codeViewer;
    },

    ...commandDrapCodeCardsCardCode,
  });
};
