<template>
  <div
    :class="{ fullscreen: fullscreen }"
    class="tinymce-container"
    :style="{ width: containerWidth }"
  >
    <TinymceEditor :id="id" v-model="tinymceContent" :init="initOptions" />
    <div class="text-right mt-5">
      {{ tinymceContent ? tinymceContent.toString().length : 0 }}
      {{ $t("general.characterLength") }}
    </div>

    <div class="editor-custom-btn-container" v-if="!readonly">
      <EditorImageUpload
        :color="uploadButtonColor"
        class="editor-upload-btn"
        @pcUpload="onPc"
        @damsUpload="onDams"
      />
    </div>

    <el-dialog
      :title="$t('dams.pcUpload')"
      width="80%"
      :visible.sync="showUploadPc"
      :modal-append-to-body="false"
      :destroy-on-close="true"
      :close-on-click-modal="false"
    >
      <DamsUpload :accept="''" :multiple="true" @uploaded="uploaded" />
    </el-dialog>

    <el-dialog
      :title="$t('dams.pcDams')"
      width="80%"
      class="dams-dialog"
      :visible.sync="showUploadDams"
      :modal-append-to-body="false"
      :destroy-on-close="true"
    >
      <DamsStructure ref="damsUploadRef" :edit="false" />
      <span slot="footer" class="dialog-footer">
        <el-button
          type="primary"
          :disabled="getChooseDisabled"
          @click="onChooseDamsItem"
        >
          {{ $t("general.choose") }}
        </el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script lang="ts">
// Docs: https://www.tiny.cloud/docs/advanced/usage-with-module-loaders/
// Import TinyMCE
import "tinymce/tinymce";
// Default icons are required for TinyMCE 5.3 or above
import "tinymce/icons/default";
// Import themes
import "tinymce/themes/silver";
import "tinymce/themes/mobile";
// Any plugins you want to use has to be imported
import "tinymce/plugins/advlist";
import "tinymce/plugins/anchor";
import "tinymce/plugins/autoresize";
import "tinymce/plugins/autolink";
import "tinymce/plugins/autosave";
import "tinymce/plugins/charmap";
import "tinymce/plugins/code";
import "tinymce/plugins/codesample";
import "tinymce/plugins/directionality";
import "tinymce/plugins/emoticons";
import "tinymce/plugins/fullpage";
import "tinymce/plugins/fullscreen";
import "tinymce/plugins/help";
import "tinymce/plugins/hr";
import "tinymce/plugins/image";
import "tinymce/plugins/imagetools";
import "tinymce/plugins/insertdatetime";
import "tinymce/plugins/link";
import "tinymce/plugins/lists";
import "tinymce/plugins/media";
import "tinymce/plugins/nonbreaking";
import "tinymce/plugins/noneditable";
import "tinymce/plugins/pagebreak";
import "tinymce/plugins/paste";
import "tinymce/plugins/preview";
import "tinymce/plugins/print";
import "tinymce/plugins/save";
import "tinymce/plugins/searchreplace";
import "tinymce/plugins/spellchecker";
import "tinymce/plugins/tabfocus";
import "tinymce/plugins/table";
import "tinymce/plugins/template";
import "tinymce/plugins/textpattern";
import "tinymce/plugins/visualblocks";
import "tinymce/plugins/visualchars";
import "tinymce/plugins/wordcount";
import TinymceEditor from "@tinymce/tinymce-vue"; // TinyMCE vue wrapper
import { Component, Prop, Vue, Watch } from "vue-property-decorator";
import { AppModule } from "../../store/modules/app";

import EditorImageUpload from "./components/EditorImage.vue";
import { plugins, toolbar } from "./config";
import DamsUpload from "../../components/Dams/dams-upload.vue";
import DamsStructure from "../../components/Dams/dams-structure.vue";
import { DamsItem } from "../../model/dams/dams-item.model";
import { Subscription } from "rxjs";
import { DamsSubscription } from "../../subscription/dams";
import { damsItemSelect } from "../../utils/dams-output";
import { uploadAsset } from "../../api/dams";

const defaultId = () =>
  "vue-tinymce-" + +new Date() + ((Math.random() * 1000).toFixed(0) + "");

declare const tinymce: any;

@Component({
  name: "Tinymce",
  components: {
    EditorImageUpload,
    TinymceEditor,
    DamsUpload,
    DamsStructure,
  },
})
export default class extends Vue {
  @Prop({ required: true }) private value!: string;
  @Prop({ default: defaultId }) private id!: string;
  @Prop({ default: false }) private readonly!: boolean;
  @Prop({ default: () => [] }) private toolbar!: string[];
  @Prop({ default: "file edit insert view format table" })
  private menubar!: string;

  @Prop({ default: "360px" }) private height!: string | number;
  @Prop({ default: "auto" }) private width!: string | number;
  private hasChange = false;
  private hasInit = false;
  private fullscreen = false;
  // https://www.tiny.cloud/docs/configure/localization/#language
  // when adding a new language, please also add the corresponding lang file under public/tinymce/langs folder
  private languageTypeList: { [key: string]: string } = {
    en: "en",
    zh: "zh_CN",
    es: "es",
    ja: "ja",
    ko: "ko_KR",
    it: "it",
  };

  // FIle Upload
  showUploadDams = false;
  showUploadPc = false;

  selectedFiles: DamsItem[] = [];
  private onSelectFolderSub: Subscription = new Subscription();

  get language() {
    return this.languageTypeList[AppModule.language];
  }

  get tinymceContent() {
    return this.value;
  }

  set tinymceContent(value) {
    this.$emit("input", value);
  }

  get containerWidth() {
    const width = this.width;
    // Test matches `100`, `'100'`
    if (/^[\d]+(\.[\d]+)?$/.test(width.toString())) {
      return `${width}px`;
    }
    return width;
  }

  get initOptions() {
    return {
      selector: `#${this.id}`,
      height: this.height,
      body_class: "panel-body",
      object_resizing: true,
      toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,
      menubar: this.menubar,
      plugins: plugins,
      media_dimensions: false,
      language: this.language,
      language_url:
        this.language === "en"
          ? ""
          : `${process.env.BASE_URL}tinymce/langs/${this.language}.js`,
      skin_url: `${process.env.BASE_URL}tinymce/skins`,
      emoticons_database_url: `${process.env.BASE_URL}tinymce/emojis.min.js`,
      end_container_on_empty_block: true,
      powerpaste_word_import: "clean",
      code_dialog_height: 450,
      code_dialog_width: 1000,
      advlist_bullet_styles: "square",
      advlist_number_styles: "default",
      imagetools_cors_hosts: ["www.tinymce.com", "codepen.io"],
      default_link_target: "_blank",
      link_title: false,
      // inserting nonbreaking space &nbsp; need Nonbreaking Space Plugin
      nonbreaking_force_tab: true,
      // https://www.tiny.cloud/docs-3x/reference/configuration/Configuration3x@convert_urls/
      // https://stackoverflow.com/questions/5196205/disable-tinymce-absolute-to-relative-url-conversions
      convert_urls: false,
      init_instance_callback: (editor: any) => {
        if (this.value) {
          editor.setContent(this.value);
        }
        this.hasInit = true;
        editor.on("NodeChange Change KeyUp SetContent", () => {
          this.hasChange = true;
          this.$emit("input", editor.getContent());
        });
      },
      images_upload_handler: async function (
        fileHere: any,
        success: any,
        fail: any
      ) {
        const fileInfo = new FormData();
        fileInfo.append("file", fileHere.blob());
        fileInfo.append("folder_id", "0");

        const apiCall = await uploadAsset(fileInfo, false);
        if (apiCall.asset_details && apiCall.asset_details.length) {
          success(apiCall.asset_details[0].url);
        } else {
          fail("error");
        }
      },
      file_picker_callback: (callback: any, _value: any, meta: any) => {
        if (meta.filetype === "image") {
          const input: any = document.createElement("input");
          input.setAttribute("type", "file");
          input.setAttribute("accept", "image/*");

          input.onchange = function () {
            const file = input.files[0];
            const reader: any = new FileReader();
            reader.onload = function () {
              const id = "blobid" + new Date().getTime();
              const blobCache = tinymce.activeEditor.editorUpload.blobCache;
              const base64 = reader.result.split(",")[1];
              const blobInfo = blobCache.create(id, file, base64);
              blobCache.add(blobInfo);
              callback(blobInfo.blobUri(), { title: file.name });
            };
            reader.readAsDataURL(file);
          };
          input.click();
        }
      },
      setup: (editor: any) => {
        editor.on("FullscreenStateChanged", (e: any) => {
          this.fullscreen = e.state;
        });
        if (this.readonly) {
          editor.settings.readonly = true;
        }

        editor.on("Blur", function () {
          // Remove &nbsp; spacing paragraph margin
          const content = editor.getContent();
          const newContent = content.replaceAll(
            "<p>&nbsp;</p>",
            '<p class="m-0">&nbsp;</p>'
          );
          editor.setContent(newContent);
        });
      },
    };
  }

  @Watch("language")
  private onLanguageChange() {
    const tinymceManager = (window as any).tinymce;
    const tinymceInstance = tinymceManager.get(this.id);
    if (this.fullscreen) {
      tinymceInstance.execCommand("mceFullScreen");
    }
    if (tinymceInstance) {
      tinymceInstance.destroy();
    }
    this.$nextTick(() => tinymceManager.init(this.initOptions));
  }

  private imageSuccessCBK(data: DamsItem[]) {
    const _tinymce = (window as any).tinymce.get(this.id);
    if (_tinymce) {
      for (const item of data) {
        if (item.file_type === "IMAGE") {
          _tinymce.insertContent(`<img class="wscnph" src="${item.url}" />`);
        } else if (item.file_type === "VIDEO") {
          _tinymce.insertContent(
            `<video class="wscnph" src="${item.url}" controls></video>`
          );
        } else {
          _tinymce.insertContent(
            `<iframe src="${item.url}#toolbar=0" width="400"
              height="600" title="" style="border:0;"></iframe>`
          );
        }
      }
    }
  }

  created() {
    this.onSelectFolderSub = DamsSubscription.getDamsState().subscribe(
      (result: any) => {
        this.selectedFiles = damsItemSelect(result, this.selectedFiles, false);
      }
    );
  }

  beforeDestroy() {
    if (this.onSelectFolderSub) {
      this.onSelectFolderSub.unsubscribe();
    }
  }

  onPc() {
    this.showUploadPc = true;
  }

  onDams() {
    this.showUploadDams = true;
    setTimeout(() => {
      this.getDamsUploadRef("init");
    });
  }

  getDamsUploadRef(type: "reset" | "init") {
    const damsUploadRef: any = this.$refs.damsUploadRef;
    if (damsUploadRef) {
      if (type === "reset") {
        damsUploadRef.reset();
      } else if (type === "init") {
        damsUploadRef.init();
      }
    }
  }

  uploaded(data: DamsItem[]) {
    this.imageSuccessCBK(data);
    this.showUploadPc = false;
  }

  get getChooseDisabled() {
    let show = false;

    let count = 0;
    for (const folder of this.selectedFiles) {
      if (folder.type === "FILE") {
        count++;
      }
    }
    if (count === this.selectedFiles.length) {
      show = true;
    }

    if (!this.selectedFiles.length) {
      show = false;
    }

    return !show;
  }

  onChooseDamsItem() {
    this.getDamsUploadRef("reset");
    this.showUploadDams = false;
    this.imageSuccessCBK(this.selectedFiles);
    this.selectedFiles = [];
  }
}
</script>

<style lang="scss" scoped>
.tinymce-container {
  position: relative;
  line-height: normal;

  .mce-fullscreen {
    z-index: 10000;
  }
}

.editor-custom-btn-container {
  position: absolute;
  right: 6px;
  top: 3px;
  z-index: 7;

  // @media only screen and (max-width: 768px) {
  //   top: 5px !important;
  // }
}

.fullscreen .editor-custom-btn-container {
  z-index: 10000;
  position: fixed;
}

.editor-upload-btn {
  display: inline-block;
}

textarea {
  visibility: hidden;
  z-index: -1;
}
</style>
