/**
 * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
 * For licensing, see LICENSE.md.
 */

// The editor creator to use.
import InlineEditor from "@ckeditor/ckeditor5-editor-inline/src/inlineeditor";
import Alignment from '@ckeditor/ckeditor5-alignment/src/alignment';
import BalloonPanelView from '@ckeditor/ckeditor5-ui/src/panel/balloon/balloonpanelview';
import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';
import Autoformat from '@ckeditor/ckeditor5-autoformat/src/autoformat';
import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
import BlockQuote from '@ckeditor/ckeditor5-block-quote/src/blockquote';
import CKFinder from '@ckeditor/ckeditor5-ckfinder/src/ckfinder';
import Heading from '@ckeditor/ckeditor5-heading/src/heading';
import Image from '@ckeditor/ckeditor5-image/src/image';
import ImageCaption from '@ckeditor/ckeditor5-image/src/imagecaption';
import ImageStyle from '@ckeditor/ckeditor5-image/src/imagestyle';
import ImageToolbar from '@ckeditor/ckeditor5-image/src/imagetoolbar';
import ImageUpload from '@ckeditor/ckeditor5-image/src/imageupload';
import Link from '@ckeditor/ckeditor5-link/src/link';
import List from '@ckeditor/ckeditor5-list/src/list';
import MediaEmbed from '@ckeditor/ckeditor5-media-embed/src/mediaembed';
import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
import PasteFromOffice from '@ckeditor/ckeditor5-paste-from-office/src/pastefromoffice';
import Table from '@ckeditor/ckeditor5-table/src/table';
import TableToolbar from '@ckeditor/ckeditor5-table/src/tabletoolbar';
import WidgetHelper from './widget-helper';
import Filer from './filer/filer';
import UploadAdapter from './filer/adapter';
import Layout from './layouts/layout';

let thisScript = document.currentScript;

const oldGOP = BalloonPanelView._getOptimalPosition;
BalloonPanelView._getOptimalPosition = function ({element, target, positions, limiter, fitInViewport})
{
  let result;
  if(target.nodeType && (target.nodeType === Node.ELEMENT_NODE) && target.matches('body') && target.ownerDocument.defaultView.frameElement)
  {
    target = target.ownerDocument.defaultView.frameElement;
    result = oldGOP({element, target, positions, limiter, fitInViewport});
  }
  else if(target instanceof Range)
  {
    result = oldGOP({element, target, positions, limiter, fitInViewport});
    let w = target.commonAncestorContainer.ownerDocument.defaultView || target.commonAncestorContainer.ownerDocument.parentWindow;
    if(w.frameElement)
    {
      result.top += w.frameElement.offsetTop;
      result.left += w.frameElement.offsetLeft;
    }
  }
  else if(target.ownerDocument)
  {
    result = oldGOP({element, target, positions, limiter, fitInViewport});
    let w = target.ownerDocument.defaultView || target.ownerDocument.parentWindow;
    if(w.frameElement)
    {
      result.top += w.frameElement.offsetTop;
      result.left += w.frameElement.offsetLeft;
    }
  }
  else
  {
    result = oldGOP({element, target, positions, limiter, fitInViewport});
  }
  return result;
};

class QuantumWidgetEditor extends InlineEditor
{
  constructor(sourceElementOrData, config)
  {
    if(config.iframe)
    {
      // create iframe and hide original textarea
      let frameElement = document.createElement('iframe');
      frameElement.className = sourceElementOrData.className;
      sourceElementOrData.parentElement.insertBefore(frameElement, sourceElementOrData);
      sourceElementOrData.style.display = 'none';

      let iframeHead = (frameElement.contentDocument || frameElement.contentWindow.document).head;

      // clearfix
      let ss = document.createElement('style');
      ss.innerHTML = 'body{margin:0;box-sizing:border-box;height:fit-content;padding:10px;overflow-y:hidden;overflow-x:auto}body:after{content: " ";visibility: hidden;display: block;height: 0;clear: both;}';
      iframeHead.appendChild(ss);

      // import ck into iframe
      let sc = document.createElement('script');
      sc.src = thisScript.src;
      iframeHead.appendChild(sc);

      // set frame body
      let iframeBody = (frameElement.contentDocument || frameElement.contentWindow.document).body;
      if(sourceElementOrData instanceof HTMLTextAreaElement)
      {
        iframeBody.innerHTML = sourceElementOrData.value;
      }
      else
      {
        iframeBody.innerHTML = sourceElementOrData.innerHTML;
      }

      // super
      super(iframeBody, config);
      this.frameElement = frameElement;
    }
    else
    {
      if(sourceElementOrData instanceof HTMLTextAreaElement)
      {
        let divElement = document.createElement('div');
        divElement.className = sourceElementOrData.className;
        sourceElementOrData.parentElement.insertBefore(divElement, sourceElementOrData);
        sourceElementOrData.style.display = 'none';

        super(divElement, config);
      }
      else
      {
        super(sourceElementOrData, config);
      }
      this.frameElement = null;
    }
    this.valueElement = sourceElementOrData;
  }

  static create(sourceElementOrData, config)
  {
    config = Object.assign({}, QuantumWidgetEditor.defaultConfig, config);
    let promise = super.create(sourceElementOrData, config);
    promise.then(
      editor =>
      {
        if(editor.frameElement)
        {
          let doResize = function () {setTimeout(resizeIframe, 0);};
          let addResizeEvent = function ()
          {
            removeResizeEvent();
            editor.frameElement.contentWindow.addEventListener('resize', doResize);
          };
          let removeResizeEvent = function ()
          {
            editor.frameElement.contentWindow.removeEventListener('resize', doResize);
          };
          editor.frameElement.contentWindow.addEventListener('resize', doResize);

          let resizeIframe = function ()
          {
            removeResizeEvent();
            let frameDoc = (editor.frameElement.contentDocument || editor.frameElement.contentWindow.document);
            editor.frameElement.style.height = frameDoc.body.offsetHeight + 'px';
            addResizeEvent();
          };

          // resize Iframe when content changes
          doResize();
          editor.model.document.on('change', doResize);
        }

        editor.model.document.on(
          'change',
          () =>
          {
            editor.valueElement.value = editor.getData();
          }
        );

        // ensures that newly configured widgets are rendered correctly
        editor.setData(editor.valueElement.value);
      }
    );
    return promise;
  }

}

// Plugins to include in the build.
QuantumWidgetEditor.builtinPlugins = [
  Alignment,
  Essentials,
  UploadAdapter,
  Autoformat,
  Bold,
  Italic,
  BlockQuote,
  Heading,
  Image,
  ImageCaption,
  ImageStyle,
  ImageToolbar,
  ImageUpload,
  Link,
  List,
  MediaEmbed,
  Paragraph,
  PasteFromOffice,
  Table,
  TableToolbar,
  Filer,
  Layout
];

// Editor configuration.
QuantumWidgetEditor.defaultConfig = {
  iframe: true,
  toolbar: {
    items: [
      'heading',
      '|',
      'alignment',
      'bold',
      'italic',
      'link',
      'bulletedList',
      'numberedList',
      'imageUpload',
      'blockQuote',
      'insertTable',
      'mediaEmbed',
      'undo',
      'redo',
      '|', 'filer',
      '|', 'layout'
    ]
  },
  image: {
    toolbar: [
      'imageStyle:full',
      'imageStyle:side',
      '|',
      'imageTextAlternative'
    ]
  },
  table: {
    contentToolbar: [
      'tableColumn',
      'tableRow',
      'mergeTableCells'
    ]
  },
  // This value must be kept in sync with the language defined in webpack.config.js.
  language: 'en'
};

if(window.CKFinder)
{
  QuantumWidgetEditor.builtinPlugins.push(CKFinder);
  QuantumWidgetEditor.defaultConfig.toolbar.items.push('|', 'ckfinder');
}

export {QuantumWidgetEditor, WidgetHelper};
