text: /**
   * GROWI agent for HackMD
   *
   * This file will be transpiled as a single JS
   *  and should be load from HackMD head via 'routes/hackmd.js' route
   *
   * USAGE:
   *  <script src="${hostname of GROWI}/_hackmd/load-agent"></script>
   *
   * @author Yuki Takei <yuki@weseek.co.jp>
   */
  import Penpal from 'penpal';
  // Penpal.debug = true;
  
  import { debounce } from 'throttle-debounce';
  
  /* eslint-disable no-console  */
  
  const allowedOrigin = '{{origin}}'; // will be replaced by swig
  
  
  /**
   * return the value of CodeMirror
   */
  function getValueOfCodemirror() {
    // get CodeMirror instance
    const editor = window.editor;
    return editor.doc.getValue();
  }
  
  /**
   * set the specified document to CodeMirror
   * @param {string} value
   */
  function setValueToCodemirror(value) {
    // get CodeMirror instance
    const editor = window.editor;
    editor.doc.setValue(value);
  }
  
  /**
   * set the specified document to CodeMirror on window loaded
   * @param {string} value
   */
  function setValueToCodemirrorOnInit(newValue) {
    if (window.cmClient != null) {
      setValueToCodemirror(newValue);
      return;
    }
  
    const intervalId = setInterval(() => {
      if (window.cmClient != null) {
        clearInterval(intervalId);
        setValueToCodemirror(newValue);
      }
    }, 250);
  
  }
  
  /**
   * postMessage to GROWI to notify body changes
   * @param {string} body
   */
  function postParentToNotifyBodyChanges(body) {
    window.growi.notifyBodyChanges(body);
  }
  // generate debounced function
  const debouncedPostParentToNotifyBodyChanges = debounce(800, postParentToNotifyBodyChanges);
  
  /**
   * postMessage to GROWI to save with shortcut
   * @param {string} document
   */
  function postParentToSaveWithShortcut(document) {
    window.growi.saveWithShortcut(document);
  }
  
  function addEventListenersToCodemirror() {
    // get CodeMirror instance
    const codemirror = window.CodeMirror;
    // get CodeMirror editor instance
    const editor = window.editor;
  
    // e.g. 404 not found
    if (codemirror == null || editor == null) {
      return;
    }
  
    // == change event
    editor.on('change', (cm, change) => {
      if (change.origin === 'ignoreHistory') {
        // do nothing because this operation triggered by other user
        return;
      }
      debouncedPostParentToNotifyBodyChanges(cm.doc.getValue());
    });
  
    // == save event
    // Reset save commands and Cmd-S/Ctrl-S shortcuts that initialized by HackMD
    codemirror.commands.save = function(cm) {
      postParentToSaveWithShortcut(cm.doc.getValue());
    };
    delete editor.options.extraKeys['Cmd-S'];
    delete editor.options.extraKeys['Ctrl-S'];
  }
  
  function connectToParentWithPenpal() {
    const connection = Penpal.connectToParent({
      parentOrigin: allowedOrigin,
      // Methods child is exposing to parent
      methods: {
        getValue() {
          return getValueOfCodemirror();
        },
        setValue(newValue) {
          setValueToCodemirror(newValue);
        },
        setValueOnInit(newValue) {
          setValueToCodemirrorOnInit(newValue);
        },
      },
    });
    connection.promise
      .then((parent) => {
        window.growi = parent;
      })
      .catch((err) => {
        console.log(err);
      });
  }
  
  /**
   * main
   */
  (function() {
    // check HackMD is in iframe
    if (window === window.parent) {
      console.log('[GROWI] Loading agent for HackMD is not processed because currently not in iframe');
      return;
    }
  
    console.log('[HackMD] Loading GROWI agent for HackMD...');
  
    window.addEventListener('load', (event) => {
      console.log('loaded');
      addEventListenersToCodemirror();
    });
  
    connectToParentWithPenpal();
  
    console.log('[HackMD] GROWI agent for HackMD has successfully loaded.');
  }());
  