text: import $ from 'dom7';
  import { window } from 'ssr-window';
  import Utils from '../../utils/utils';
  import Framework7Class from '../../utils/class';
  import pickerColumn from './picker-column';
  
  class Picker extends Framework7Class {
    constructor(app, params = {}) {
      super(params, [app]);
      const picker = this;
      picker.params = Utils.extend({}, app.params.picker, params);
  
      let $containerEl;
      if (picker.params.containerEl) {
        $containerEl = $(picker.params.containerEl);
        if ($containerEl.length === 0) return picker;
      }
  
      let $inputEl;
      if (picker.params.inputEl) {
        $inputEl = $(picker.params.inputEl);
      }
  
      let view;
      if ($inputEl) {
        view = $inputEl.parents('.view').length && $inputEl.parents('.view')[0].f7View;
      }
      if (!view) view = app.views.main;
  
      Utils.extend(picker, {
        app,
        $containerEl,
        containerEl: $containerEl && $containerEl[0],
        inline: $containerEl && $containerEl.length > 0,
        needsOriginFix: app.device.ios || ((window.navigator.userAgent.toLowerCase().indexOf('safari') >= 0 && window.navigator.userAgent.toLowerCase().indexOf('chrome') < 0) && !app.device.android),
        cols: [],
        $inputEl,
        inputEl: $inputEl && $inputEl[0],
        initialized: false,
        opened: false,
        url: picker.params.url,
        view,
      });
  
      function onResize() {
        picker.resizeCols();
      }
      function onInputClick() {
        picker.open();
      }
      function onInputFocus(e) {
        e.preventDefault();
      }
      function onHtmlClick(e) {
        const $targetEl = $(e.target);
        if (picker.isPopover()) return;
        if (!picker.opened || picker.closing) return;
        if ($targetEl.closest('[class*="backdrop"]').length) return;
        if ($inputEl && $inputEl.length > 0) {
          if ($targetEl[0] !== $inputEl[0] && $targetEl.closest('.sheet-modal').length === 0) {
            picker.close();
          }
        } else if ($(e.target).closest('.sheet-modal').length === 0) {
          picker.close();
        }
      }
  
      // Events
      Utils.extend(picker, {
        attachResizeEvent() {
          app.on('resize', onResize);
        },
        detachResizeEvent() {
          app.off('resize', onResize);
        },
        attachInputEvents() {
          picker.$inputEl.on('click', onInputClick);
          if (picker.params.inputReadOnly) {
            picker.$inputEl.on('focus mousedown', onInputFocus);
          }
        },
        detachInputEvents() {
          picker.$inputEl.off('click', onInputClick);
          if (picker.params.inputReadOnly) {
            picker.$inputEl.off('focus mousedown', onInputFocus);
          }
        },
        attachHtmlEvents() {
          app.on('click', onHtmlClick);
        },
        detachHtmlEvents() {
          app.off('click', onHtmlClick);
        },
      });
  
      picker.init();
  
      return picker;
    }
  
    initInput() {
      const picker = this;
      if (!picker.$inputEl) return;
      if (picker.params.inputReadOnly) picker.$inputEl.prop('readOnly', true);
    }
  
    resizeCols() {
      const picker = this;
      if (!picker.opened) return;
      for (let i = 0; i < picker.cols.length; i += 1) {
        if (!picker.cols[i].divider) {
          picker.cols[i].calcSize();
          picker.cols[i].setValue(picker.cols[i].value, 0, false);
        }
      }
    }
  
    isPopover() {
      const picker = this;
      const { app, modal, params } = picker;
      if (params.openIn === 'sheet') return false;
      if (modal && modal.type !== 'popover') return false;
  
      if (!picker.inline && picker.inputEl) {
        if (params.openIn === 'popover') return true;
        if (app.device.ios) {
          return !!app.device.ipad;
        }
        if (app.width >= 768) {
          return true;
        }
        if (app.device.desktop && app.theme === 'aurora') {
          return true;
        }
      }
      return false;
    }
  
    formatValue() {
      const picker = this;
      const { value, displayValue } = picker;
      if (picker.params.formatValue) {
        return picker.params.formatValue.call(picker, value, displayValue);
      }
      return value.join(' ');
    }
  
    setValue(values, transition) {
      const picker = this;
      let valueIndex = 0;
      if (picker.cols.length === 0) {
        picker.value = values;
        picker.updateValue(values);
        return;
      }
      for (let i = 0; i < picker.cols.length; i += 1) {
        if (picker.cols[i] && !picker.cols[i].divider) {
          picker.cols[i].setValue(values[valueIndex], transition);
          valueIndex += 1;
        }
      }
    }
  
    getValue() {
      const picker = this;
      return picker.value;
    }
  
    updateValue(forceValues) {
      const picker = this;
      const newValue = forceValues || [];
      const newDisplayValue = [];
      let column;
      if (picker.cols.length === 0) {
        const noDividerColumns = picker.params.cols.filter(c => !c.divider);
        for (let i = 0; i < noDividerColumns.length; i += 1) {
          column = noDividerColumns[i];
          if (column.displayValues !== undefined && column.values !== undefined && column.values.indexOf(newValue[i]) !== -1) {
            newDisplayValue.push(column.displayValues[column.values.indexOf(newValue[i])]);
          } else {
            newDisplayValue.push(newValue[i]);
          }
        }
      } else {
        for (let i = 0; i < picker.cols.length; i += 1) {
          if (!picker.cols[i].divider) {
            newValue.push(picker.cols[i].value);
            newDisplayValue.push(picker.cols[i].displayValue);
          }
        }
      }
  
      if (newValue.indexOf(undefined) >= 0) {
        return;
      }
      picker.value = newValue;
      picker.displayValue = newDisplayValue;
      picker.emit('local::change pickerChange', picker, picker.value, picker.displayValue);
      if (picker.inputEl) {
        picker.$inputEl.val(picker.formatValue());
        picker.$inputEl.trigger('change');
      }
    }
  
    initColumn(colEl, updateItems) {
      const picker = this;
      pickerColumn.call(picker, colEl, updateItems);
    }
    // eslint-disable-next-line
    destroyColumn(colEl) {
      const picker = this;
      const $colEl = $(colEl);
      const index = $colEl.index();
      if (picker.cols[index] && picker.cols[index].destroy) {
        picker.cols[index].destroy();
      }
    }
  
    renderToolbar() {
      const picker = this;
      if (picker.params.renderToolbar) return picker.params.renderToolbar.call(picker, picker);
      return `
        <div class="toolbar toolbar-top no-shadow">
          <div class="toolbar-inner">
            <div class="left"></div>
            <div class="right">
              <a class="link sheet-close popover-close">${picker.params.toolbarCloseText}</a>
            </div>
          </div>
        </div>
      `.trim();
    }
    // eslint-disable-next-line
    renderColumn(col, onlyItems) {
      const colClasses = `picker-column ${col.textAlign ? `picker-column-${col.textAlign}` : ''} ${col.cssClass || ''}`;
      let columnHtml;
      let columnItemsHtml;
  
      if (col.divider) {
        columnHtml = `
          <div class="${colClasses} picker-column-divider">${col.content}</div>
        `;
      } else {
        columnItemsHtml = col.values.map((value, index) => `
          <div class="picker-item" data-picker-value="${value}">
            <span>${col.displayValues ? col.displayValues[index] : value}</span>
          </div>
        `).join('');
        columnHtml = `
          <div class="${colClasses}">
            <div class="picker-items">${columnItemsHtml}</div>
          </div>
        `;
      }
  
      return onlyItems ? columnItemsHtml.trim() : columnHtml.trim();
    }
  
    renderInline() {
      const picker = this;
      const { rotateEffect, cssClass, toolbar } = picker.params;
      const inlineHtml = `
        <div class="picker picker-inline ${rotateEffect ? 'picker-3d' : ''} ${cssClass || ''}">
          ${toolbar ? picker.renderToolbar() : ''}
          <div class="picker-columns">
            ${picker.cols.map(col => picker.renderColumn(col)).join('')}
            <div class="picker-center-highlight"></div>
          </div>
        </div>
      `.trim();
  
      return inlineHtml;
    }
  
    renderSheet() {
      const picker = this;
      const { rotateEffect, cssClass, toolbar } = picker.params;
      const sheetHtml = `
        <div class="sheet-modal picker picker-sheet ${rotateEffect ? 'picker-3d' : ''} ${cssClass || ''}">
          ${toolbar ? picker.renderToolbar() : ''}
          <div class="sheet-modal-inner picker-columns">
            ${picker.cols.map(col => picker.renderColumn(col)).join('')}
            <div class="picker-center-highlight"></div>
          </div>
        </div>
      `.trim();
  
      return sheetHtml;
    }
  
    renderPopover() {
      const picker = this;
      const { rotateEffect, cssClass, toolbar } = picker.params;
      const popoverHtml = `
        <div class="popover picker-popover">
          <div class="popover-inner">
            <div class="picker ${rotateEffect ? 'picker-3d' : ''} ${cssClass || ''}">
              ${toolbar ? picker.renderToolbar() : ''}
              <div class="picker-columns">
                ${picker.cols.map(col => picker.renderColumn(col)).join('')}
                <div class="picker-center-highlight"></div>
              </div>
            </div>
          </div>
        </div>
      `.trim();
  
      return popoverHtml;
    }
  
    render() {
      const picker = this;
      if (picker.params.render) return picker.params.render.call(picker);
      if (!picker.inline) {
        if (picker.isPopover()) return picker.renderPopover();
        return picker.renderSheet();
      }
      return picker.renderInline();
    }
  
    onOpen() {
      const picker = this;
      const { initialized, $el, app, $inputEl, inline, value, params } = picker;
      picker.opened = true;
      picker.closing = false;
      picker.opening = true;
  
      // Init main events
      picker.attachResizeEvent();
  
      // Init cols
      $el.find('.picker-column').each((index, colEl) => {
        let updateItems = true;
        if (
          (!initialized && params.value)
          || (initialized && value)
        ) {
          updateItems = false;
        }
        picker.initColumn(colEl, updateItems);
      });
  
      // Set value
      if (!initialized) {
        if (value) picker.setValue(value, 0);
        else if (params.value) {
          picker.setValue(params.value, 0);
        }
      } else if (value) {
        picker.setValue(value, 0);
      }
  
      // Extra focus
      if (!inline && $inputEl && $inputEl.length && app.theme === 'md') {
        $inputEl.trigger('focus');
      }
  
      picker.initialized = true;
  
      // Trigger events
      if ($el) {
        $el.trigger('picker:open', picker);
      }
      if ($inputEl) {
        $inputEl.trigger('picker:open', picker);
      }
      picker.emit('local::open pickerOpen', picker);
    }
  
    onOpened() {
      const picker = this;
      picker.opening = false;
  
      if (picker.$el) {
        picker.$el.trigger('picker:opened', picker);
      }
      if (picker.$inputEl) {
        picker.$inputEl.trigger('picker:opened', picker);
      }
      picker.emit('local::opened pickerOpened', picker);
    }
  
    onClose() {
      const picker = this;
      const app = picker.app;
      picker.opening = false;
      picker.closing = true;
  
      // Detach events
      picker.detachResizeEvent();
  
      picker.cols.forEach((col) => {
        if (col.destroy) col.destroy();
      });
      if (picker.$inputEl && app.theme === 'md') {
        picker.$inputEl.trigger('blur');
      }
  
      if (picker.$el) {
        picker.$el.trigger('picker:close', picker);
      }
      if (picker.$inputEl) {
        picker.$inputEl.trigger('picker:close', picker);
      }
      picker.emit('local::close pickerClose', picker);
    }
  
    onClosed() {
      const picker = this;
      picker.opened = false;
      picker.closing = false;
  
      if (!picker.inline) {
        Utils.nextTick(() => {
          if (picker.modal && picker.modal.el && picker.modal.destroy) {
            if (!picker.params.routableModals) {
              picker.modal.destroy();
            }
          }
          delete picker.modal;
        });
      }
  
      if (picker.$el) {
        picker.$el.trigger('picker:closed', picker);
      }
      if (picker.$inputEl) {
        picker.$inputEl.trigger('picker:closed', picker);
      }
      picker.emit('local::closed pickerClosed', picker);
    }
  
    open() {
      const picker = this;
      const { app, opened, inline, $inputEl } = picker;
      if (opened) return;
      if (picker.cols.length === 0 && picker.params.cols.length) {
        picker.params.cols.forEach((col) => {
          picker.cols.push(col);
        });
      }
      if (inline) {
        picker.$el = $(picker.render());
        picker.$el[0].f7Picker = picker;
        picker.$containerEl.append(picker.$el);
        picker.onOpen();
        picker.onOpened();
        return;
      }
      const isPopover = picker.isPopover();
      const modalType = isPopover ? 'popover' : 'sheet';
      const modalParams = {
        targetEl: $inputEl,
        scrollToEl: picker.params.scrollToInput ? $inputEl : undefined,
        content: picker.render(),
        backdrop: isPopover,
        on: {
          open() {
            const modal = this;
            picker.modal = modal;
            picker.$el = isPopover ? modal.$el.find('.picker') : modal.$el;
            picker.$el[0].f7Picker = picker;
            picker.onOpen();
          },
          opened() { picker.onOpened(); },
          close() { picker.onClose(); },
          closed() { picker.onClosed(); },
        },
      };
      if (picker.params.routableModals) {
        picker.view.router.navigate({
          url: picker.url,
          route: {
            path: picker.url,
            [modalType]: modalParams,
          },
        });
      } else {
        picker.modal = app[modalType].create(modalParams);
        picker.modal.open();
      }
    }
  
    close() {
      const picker = this;
      const { opened, inline } = picker;
      if (!opened) return;
      if (inline) {
        picker.onClose();
        picker.onClosed();
        return;
      }
      if (picker.params.routableModals) {
        picker.view.router.back();
      } else {
        picker.modal.close();
      }
    }
  
    init() {
      const picker = this;
  
      picker.initInput();
  
      if (picker.inline) {
        picker.open();
        picker.emit('local::init pickerInit', picker);
        return;
      }
  
      if (!picker.initialized && picker.params.value) {
        picker.setValue(picker.params.value);
      }
  
      // Attach input Events
      if (picker.$inputEl) {
        picker.attachInputEvents();
      }
      if (picker.params.closeByOutsideClick) {
        picker.attachHtmlEvents();
      }
      picker.emit('local::init pickerInit', picker);
    }
  
    destroy() {
      const picker = this;
      if (picker.destroyed) return;
      const { $el } = picker;
      picker.emit('local::beforeDestroy pickerBeforeDestroy', picker);
      if ($el) $el.trigger('picker:beforedestroy', picker);
  
      picker.close();
  
      // Detach Events
      if (picker.$inputEl) {
        picker.detachInputEvents();
      }
      if (picker.params.closeByOutsideClick) {
        picker.detachHtmlEvents();
      }
  
      if ($el && $el.length) delete picker.$el[0].f7Picker;
      Utils.deleteProps(picker);
      picker.destroyed = true;
    }
  }
  
  export default Picker;
  