import { Utility } from '../../core/utility';
import { StorageManager, LOCATION } from '../../lib/storage-manager/storage-manager';
import { EventManager, EventWrapper, EVENT_TYPE } from '../../lib/event-manager/event-manager';
import './show-hide.sass';

const SHOW_HIDE_LOCAL_STORAGE_KEY = 'SHOW_HIDE';
const SHOW_HIDE_INITIALIZED_CLASS = 'show-hide--initialized';
const SHOW_HIDE_COLLAPSED_CLASS = 'show-hide--collapsed';
const SHOW_HIDE_TOGGLE_CLASS = 'show-hide__toggle';
const SHOW_HIDE_TOGGLE_RIGHT_CLASS = 'show-hide__toggle--right';

@Utility({
  selector: '[uw-show-hide]',
})
export class ShowHide {

  _showHideId;
  _element;

  _eventManager;
  _storageManager = new StorageManager(SHOW_HIDE_LOCAL_STORAGE_KEY, '1.0.0', { location: LOCATION.LOCAL });

  constructor(element) {
    if (!element) {
      throw new Error('ShowHide utility cannot be setup without an element!');
    }

    this._element = element;
    this._eventManager = new EventManager();

    if (this._element.classList.contains(SHOW_HIDE_INITIALIZED_CLASS)) {
      return false;
    }

    // register click listener
    const clickEv = new EventWrapper(EVENT_TYPE.CLICK, this._clickHandler.bind(this), this._element);
    this._eventManager.registerNewListener(clickEv);

    // param showHideId
    if (this._element.dataset.showHideId) {
      this._showHideId = this._element.dataset.showHideId;
    }

    // param showHideCollapsed
    let collapsed = false;
    if (this._element.dataset.showHideCollapsed !== undefined) {
      collapsed = true;
    }

    if (this._showHideId) {
      let storageCollapsed = this._storageManager.load(this._showHideId);
      if (typeof storageCollapsed !== 'undefined') {
        collapsed = storageCollapsed;
      }
    }
    this._element.parentElement.classList.toggle(SHOW_HIDE_COLLAPSED_CLASS, collapsed);

    // param showHideAlign
    const alignment = this._element.dataset.showHideAlign;
    if (alignment === 'right') {
      this._element.classList.add(SHOW_HIDE_TOGGLE_RIGHT_CLASS);
    }

    this._checkHash();
    const hashChangeEv = new EventWrapper(EVENT_TYPE.HASH_CHANGE, this._checkHash.bind(this), window);
    this._eventManager.registerNewListener(hashChangeEv);

    // mark as initialized
    this._element.classList.add(SHOW_HIDE_INITIALIZED_CLASS, SHOW_HIDE_TOGGLE_CLASS);
  }

  destroy() {
    this._eventManager.cleanUp();
    if (this._element.parentElement.classList.contains(SHOW_HIDE_COLLAPSED_CLASS))
      this._element.parentElement.classList.remove(SHOW_HIDE_COLLAPSED_CLASS);
    this._element.classList.remove(SHOW_HIDE_INITIALIZED_CLASS, SHOW_HIDE_TOGGLE_CLASS);
  }

  _show() {
    this._element.parentElement.classList.remove(SHOW_HIDE_COLLAPSED_CLASS); 
  }

  _toggle() {
    return this._element.parentElement.classList.toggle(SHOW_HIDE_COLLAPSED_CLASS); 
  }

  _clickHandler(event) {
    if (event.target.closest('a') && event.target.closest('a') !== this._element)
      return;
    if (event.target.matches('a') && event.target !== this._element)
      return;
    
    const newState = this._toggle();

    if (this._showHideId) {
      this._storageManager.save(this._showHideId, newState);
    }
  }

  _checkHash() {
    if (this._element.id && '#' + this._element.id === location.hash) {
      this._show();
    }
  }
}
