text: import Component from '@ember/component';
  import formatMarkdown from 'ghost-admin/utils/format-markdown';
  import layout from '../templates/components/koenig-card-markdown';
  import {computed} from '@ember/object';
  import {countTextLength} from '../lib/dnd/utils';
  import {utils as ghostHelperUtils} from '@tryghost/helpers';
  import {htmlSafe} from '@ember/string';
  import {isBlank} from '@ember/utils';
  import {run} from '@ember/runloop';
  import {set} from '@ember/object';
  import {task, timeout} from 'ember-concurrency';
  
  const {countImages} = ghostHelperUtils;
  const MIN_HEIGHT = 130;
  
  export default Component.extend({
      layout,
  
      // attrs
      payload: null,
      isSelected: false,
      isEditing: false,
      headerOffset: 0,
  
      // internal attrs
      bottomOffset: 0,
      preventClick: false,
  
      // closure actions
      editCard() {},
      saveCard() {},
      selectCard() {},
      deselectCard() {},
      deleteCard() {},
      registerComponent() {},
  
      counts: computed('renderedMarkdown', function () {
          return {
              wordCount: countTextLength(this.renderedMarkdown),
              imageCount: countImages(this.renderedMarkdown)
          };
      }),
  
      renderedMarkdown: computed('payload.markdown', function () {
          return htmlSafe(formatMarkdown(this.payload.markdown));
      }),
  
      toolbar: computed('isEditing', function () {
          if (this.isEditing) {
              return false;
          }
  
          return {
              items: [{
                  buttonClass: 'fw4 flex items-center white',
                  icon: 'koenig/kg-edit',
                  iconClass: 'fill-white',
                  title: 'Edit',
                  text: '',
                  action: run.bind(this, this.editCard)
              }]
          };
      }),
  
      init() {
          this._super(...arguments);
  
          if (!this.payload) {
              this.set('payload', {});
          }
  
          // subtract toolbar height from MIN_HEIGHT so the trigger happens at
          // the expected position without forcing the min height to be too small
          this.set('bottomOffset', -MIN_HEIGHT - 49);
  
          this.registerComponent(this);
      },
  
      willDestroyElement() {
          this._super(...arguments);
          this._teardownResizeHandler();
      },
  
      actions: {
          enterEditMode() {
              this._preventAccidentalClick.perform();
          },
  
          leaveEditMode() {
              if (isBlank(this.payload.markdown)) {
                  // afterRender is required to avoid double modification of `isSelected`
                  // TODO: see if there's a way to avoid afterRender
                  run.scheduleOnce('afterRender', this, function () {
                      this.deleteCard();
                  });
              }
          },
  
          updateMarkdown(markdown) {
              let payload = this.payload;
              let save = this.saveCard;
  
              set(payload, 'markdown', markdown);
  
              // update the mobiledoc and stay in edit mode
              save(payload, false);
          },
  
          // fires if top comes into view 0 px from viewport top
          // fires if top comes into view MIN_HEIGHTpx above viewport bottom
          topEntered() {
              this._isTopVisible = true;
              run.scheduleOnce('actions', this, this._applyToolbarStyles);
          },
  
          // fires if top leaves viewport 0 px from viewport top
          // fires if top leaves viewport MIN_HEIGHTpx above viewport bottom
          topExited() {
              let top = this._topElement.getBoundingClientRect().top;
              this._isTopVisible = false;
              this._isTopAbove = top < 0;
              run.scheduleOnce('actions', this, this._applyToolbarStyles);
          },
  
          bottomEntered() {
              this._isBottomVisible = true;
              run.scheduleOnce('actions', this, this._applyToolbarStyles);
          },
  
          bottomExited() {
              let top = this._bottomElement.getBoundingClientRect().top;
              this._isBottomVisible = false;
              this._isBottomBelow = top > window.innerHeight;
              run.scheduleOnce('actions', this, this._applyToolbarStyles);
          },
  
          registerTop(element) {
              this._topElement = element;
          },
  
          registerBottom(element) {
              this._bottomElement = element;
          }
      },
  
      _applyToolbarStyles() {
          let toolbar = this.element.querySelector('.editor-toolbar');
  
          if (!toolbar) {
              return;
          }
  
          let {left, width} = this._containerDimensions();
  
          let style = '';
          let stuckTop = `top: ${MIN_HEIGHT}px; bottom: auto`;
          let fixedBottom = `position: fixed; left: ${left + 1}px; width: ${width - 2}px`;
          let stuckBottom = '';
  
          if (this._isTopVisible && this._isBottomVisible) {
              style = stuckBottom;
          }
  
          if (this._isTopVisible && !this._isBottomVisible) {
              style = fixedBottom;
          }
  
          if (!this._isTopVisible && !this._isTopAbove) {
              style = stuckTop;
          }
  
          if (!this._isTopVisible && this._isBottomVisible) {
              style = stuckBottom;
          }
  
          if (!this._isTopVisible && !this._isBottomVisible && this._isTopAbove && this._isBottomBelow) {
              style = fixedBottom;
          }
  
          // set up resize watchers if in fixed position because we have to
          // recalculate left position and width
          if (!this._resizeHandler && style === fixedBottom) {
              this._setupResizeHandler();
          } else if (this._resizeHandler && style !== fixedBottom) {
              this._teardownResizeHandler();
          }
  
          // account for the mobile nav bar when in fixed position
          if (style === fixedBottom) {
              let mobileNav = document.querySelector('.gh-mobile-nav-bar');
  
              if (mobileNav.offsetHeight) {
                  style = `${style}; bottom: ${mobileNav.offsetHeight}px`;
              }
          }
  
          toolbar.setAttribute('style', style);
      },
  
      _containerDimensions() {
          return this.element.querySelector('.kg-card-selected').getBoundingClientRect();
      },
  
      _setupResizeHandler() {
          if (this._resizeHandler) {
              return;
          }
  
          this._resizeHandler = run.bind(this, this._applyToolbarStyles);
          window.addEventListener('resize', this._resizeHandler);
      },
  
      _teardownResizeHandler() {
          window.removeEventListener('resize', this._resizeHandler);
          this._resizeHandler = null;
      },
  
      // when entering edit mode it can be easy to accidentally click where the
      // toolbar is inserted. Setting `preventClick` to true adds an overlay, so
      // we set that for half a second to stop double-clicks hitting the toolbar
      _preventAccidentalClick: task(function* () {
          this.set('preventClick', true);
          yield timeout(500);
          this.set('preventClick', false);
      })
  
  });
  