import { isMobileOrTablet, rand } from '../../common/helper';
import seedrandom from 'seedrandom';

const nameColorPallete = {
  H: [1, 360],
  S: [0, 100],
  L: [50, 80],
};

export class Chat {
  public element = document.createElement('div');
  private _history = document.createElement('div');
  private _wrapper = document.createElement('div');
  private _mobToggle = document.createElement('button');
  private _inpBox = document.createElement('div');
  private _input = document.createElement('input');
  private _visible = true;
  private _rehide = false;
  private _keyhandler = true;

  private _sendFn?: (message: string) => void;

  get visible() {
    return this._visible;
  }

  initialize() {
    this.element.classList.add('chat__wrapper');
    this._wrapper.classList.add('chat');
    this._history.classList.add('chat__history');
    this._inpBox.classList.add('chat__input-wrapper');
    this._input.classList.add('chat__input');
    this._mobToggle.classList.add('chat__toggle');

    this._inpBox.append(this._input);
    this._wrapper.append(this._history, this._inpBox);
    this.element.append(this._mobToggle, this._wrapper);

    this._input.setAttribute(
      'placeholder',
      'Type a message here and press Enter to send...',
    );

    this._input.setAttribute('maxlength', '280');

    this._input.addEventListener('keydown', (e) => {
      e.stopPropagation();
      if (e.key === 'Enter') {
        if (!this._input.value?.trim()) {
          this._input.blur();

          if (this._rehide) {
            this.hide();
            this._rehide = false;
          }

          return;
        }

        if (this._sendFn) {
          this._sendFn(this._input.value);
        }

        this._input.value = '';

        if (this._rehide) {
          this.hide();
          this._rehide = false;
        }
      } else if (e.key === 'Escape') {
        this._input.blur();
        this._input.value = '';

        if (this._rehide) {
          this.hide();
          this._rehide = false;
        }
      }
    });

    this._input.addEventListener('focus', () => {
      this.element.classList.add('focused');
    });

    this._input.addEventListener('blur', () => {
      this.element.classList.remove('focused');
    });

    this._mobToggle.addEventListener('click', () => {
      if (this._visible) {
        this.hide();
      } else {
        this.focus();
      }
    });

    window.addEventListener('keydown', (e) => {
      if (!this._keyhandler) {
        return;
      }

      if (e.key === 'Enter' && (e.target as HTMLElement).tagName !== 'INPUT') {
        this.focus(!this.visible);
      }
    });

    document.body.append(this.element);

    if (!isMobileOrTablet()) {
      this.show();
    } else {
      this.hide();
    }
  }

  public registerSendFunction(fn: (message: string) => void) {
    this._sendFn = fn;
  }

  public show() {
    this._visible = true;
    this.element.classList.add('visible');
    this.element.classList.remove('invisible');
    this.scrollBottom();
  }

  public hide() {
    this._visible = false;
    this.element.classList.remove('visible');
    this.element.classList.add('invisible');
  }

  public focus(rehide = false) {
    if (!this._visible) {
      this.show();
    }
    this._input.focus();
    this._rehide = rehide;
  }

  public addMessage(message: string, sender?: string, meta?: any) {
    const msg = document.createElement('div');
    const msgSender = document.createElement('div');
    const msgTime = document.createElement('div');
    const msgContent = document.createElement('div');

    msg.classList.add('chat__message');
    msgTime.classList.add('chat__message-timestamp');
    msgSender.classList.add('chat__message-sender');
    msgContent.classList.add('chat__message-content');

    msg.append(msgTime);

    const stamp = meta?.time ? new Date(meta.time) : new Date();

    // TODO: timestamp utility
    msgTime.innerText = `${stamp.getHours().toString().padStart(2, '0')}:${stamp
      .getMinutes()
      .toString()
      .padStart(2, '0')}`;
    msgTime.setAttribute('title', stamp.toString());

    // optional sender
    if (sender) {
      msgSender.innerText = sender;
      msgSender.style.setProperty('--name-color', this.getNameColor(sender));
      msg.append(msgSender);
    }

    // optional color for content
    if (meta?.color) {
      msgContent.style.setProperty('--text-color', meta.color);
    }
    msgContent.innerText = message;
    msg.append(msgContent);

    const lFactor = this._history.offsetHeight + this._history.scrollTop;
    const wasAtBottom = lFactor > this._history.scrollHeight - 100;

    this._history.append(msg);

    wasAtBottom && this.scrollBottom();

    setTimeout(() => {
      msg.classList.add('chat__message--old');
    }, 5000);
  }

  public getNameColor(name: string) {
    const randgen = seedrandom(name);
    const h = rand(randgen, nameColorPallete.H[0], nameColorPallete.H[1]);
    const s = rand(randgen, nameColorPallete.S[0], nameColorPallete.S[1]);
    const l = rand(randgen, nameColorPallete.L[0], nameColorPallete.L[1]);
    return 'hsl(' + h + ',' + s + '%,' + l + '%)';
  }

  public setKeyHandlerEnabled(isEnabled: boolean) {
    this._keyhandler = isEnabled;
  }

  public scrollBottom() {
    this._history.scrollTop = this._history.scrollHeight;
  }
}
