import { EMPTY_STRING } from '../../../../mel_metapage/js/lib/constants/constants.js';
import { BnumModules } from '../../../../mel_metapage/js/lib/helpers/dynamic_load_modules.js';
import {
  BnumHtmlIcon,
  BnumHtmlSeparate,
  EWebComponentMode,
  HtmlCustomTag,
} from '../../../../mel_metapage/js/lib/html/JsHtml/CustomAttributes/js_html_base_web_elements.js';
import { PressedButton } from '../../../../mel_metapage/js/lib/html/JsHtml/CustomAttributes/pressed_button_web_element.js';
import { BnumEvent } from '../../../../mel_metapage/js/lib/mel_events.js';
import { MelObject } from '../../../../mel_metapage/js/lib/mel_object.js';
import { WorkspaceData } from '../program/workspaceData.js';
import { WspButton } from './NavbarComponents/button.js';
import { WspNavBarDescription } from './NavbarComponents/components.js';
import { WspPageNavigation } from './NavbarComponents/nav.js';

export { WspNavBar };

/**
 * @enum {Symbol}
 */
const EFileType = {
  script: Symbol(),
  module: Symbol(),
  style: Symbol(),
};

class WspNavBar extends HtmlCustomTag {
  static #actions = [];
  #data = {};
  #pageNavigation = null;

  constructor() {
    super({ mode: EWebComponentMode.div });

    this.onactionclicked = new BnumEvent();
    this.onbuttonclicked = new BnumEvent();
    this.onstatetoggle = new BnumEvent();
    this.onquitbuttonclick = new BnumEvent();
    this.onuserrequested = new BnumEvent();
    this.onuserchanged = new BnumEvent();
  }

  /**
   * @readonly
   */
  get users() {
    return this.onuserrequested.call() || {};
  }

  /**
   * Id de l'espace
   * @type {string}
   * @readonly
   */
  get uid() {
    return this.workspace.uid;
  }

  /**
   * Image de l'espace
   * @type {string}
   */
  get picture() {
    return this.workspace.logo;
  }

  set picture(value) {
    this.workspace.logo = value;

    let src = this.navigator.querySelector('.picture-container img');
    src.setAttribute('src', value);

    src = null;
  }

  /**
   * Description de l'espace
   * @type {string}
   */
  get description() {
    return this.workspace.description;
  }

  set description(value) {
    this.workspace.description = value;

    let newDesc = new WspNavBarDescription({
      description: value,
      parent: this,
    });

    let desc = this.navigator.querySelector('bnum-wsp-nav-description');
    desc.replaceWith(newDesc);

    desc = null;
    newDesc = null;
  }

  /**
   * Titre de l'espace
   * @type {string}
   */
  get title() {
    return this.workspace.title;
  }

  set title(value) {
    this.workspace.title = value;

    let title = this.navigator.querySelector('.wsp-title');
    title.textContent = value;
    title = null;

    title = this.navigator.querySelector('.picture-container div');

    if (title) {
      title.textContent = value.slice(0, 3).toUpperCase();
      title = null;
    }
  }

  get hashtag() {
    return this.workspace.hashtag;
  }

  set hashtag(value) {
    this.workspace.hashtag = value;

    let hashtag = this.navigator.querySelector('.hashtag');
    hashtag.textContent = `#${value}`;
    hashtag.setAttribute('title', `#${value} - Thématique de l'espace`);

    hashtag = null;
  }

  get color() {
    return this.workspace.color;
  }

  set color(value) {
    this.workspace.color = value;

    const querry = this.mainDiv.querySelectorAll('.colored');

    if (querry && querry.length) {
      for (const element of querry) {
        element.style.backgroundColor = value;
      }
    }
  }

  /**
   * Div principale du shadow-dom
   * @type {HTMLDivElement}
   * @readonly
   */
  get mainDiv() {
    return this.shadowRoot.querySelector(`#${this.id}`);
  }

  /**
   * Id de la div principale du shadow-dom
   * @type {string}
   * @readonly
   * @default `wsp-nav-${this.uid}`
   */
  get id() {
    return `wsp-nav-${this.uid}`;
  }

  /**
   * @type {WspPageNavigation}
   */
  get pageNavigation() {
    return this.#pageNavigation || this.querySelector('bnum-wsp-navigation');
  }

  /**
   * @type {WorkspaceData}
   */
  get workspace() {
    if (!this.#data.workspace) {
      const wsp = this.#_get_data('workspace');
      this.#data.workspace = new WorkspaceData(
        JSON.parse(wsp.replaceAll("¤'¤'", '"')),
      );
    }

    return this.#data.workspace;
  }

  /**
   * @type {{task:string, canBeHidden:boolean}[]}
   */
  get settings() {
    return JSON.parse(
      (this.#_get_data('apps-settings') || JSON.stringify([])).replaceAll(
        "¤'¤'",
        '"',
      ),
    );
  }

  _p_main() {
    // this.attachInternals().states.add('can-be-busy');
    this.classList.add('can-be-busy');
    this.data('shadow', true);

    let shadow = this._p_start_construct();
    this.#_setup_styles().#_setup_scripts().#_setup_modules();

    let div = document.createElement('div');
    div.classList.add('nav', 'melv2-card');
    div.setAttribute('id', this.id);
    div.style.display = 'none';

    shadow.append(div);

    this._generate_back_button()
      ._generate_picture()
      ._generate_title()
      ._generate_description()
      ._generate_block();

    let tmp = new WspPageNavigation({ parent: this, apps: this.settings });
    this.mainDiv.appendChild(tmp);
    tmp.onbuttonclicked.push(
      this.onbuttonclicked.call.bind(this.onbuttonclicked),
    );
    tmp.oniconclicked.push((...args) => {
      this.onstatetoggle.call(...args);
    });
    this.#pageNavigation = tmp;
    tmp = null;

    this._generate_minify_button();

    div.style.display = null;
    div = null;
    //style = null;
    shadow = null;
  }

  _generate_back_button() {
    let button = new WspButton(this, {
      text: 'Retour',
      icon: 'arrow_left_alt',
    });
    button.setAttribute('id', 'wsp-quit-button');
    button.setAttribute('data-position', 'left');
    button.style.maxWidth = '80px';
    button.style.marginBottom = '15px';
    button.onclick = this.onquitbuttonclick.call.bind(this.onquitbuttonclick);
    button.classList.add('quit-wsp-button', 'white');

    this.mainDiv.prepend(button);

    button = null;
    return this;
  }

  _generate_minify_button() {
    let button = PressedButton.Create();
    button.setAttribute('id', 'wsp-nav-minify-expand');
    button.classList.add('transparent-bckg');

    button.ontoggle.push((args, caller_any) => {
      const { newState } = args;
      /**
       * @type {PressedButton}
       */
      let caller = caller_any;

      //Si on minifie
      if (newState) {
        this.addClass('minified');
        caller.querySelector(BnumHtmlIcon.TAG).icon =
          'keyboard_double_arrow_right';
        caller.setAttribute(
          'title',
          "Maximiser la barre de navigation de l'espace.",
        );
      } else {
        this.removeClass('minified');
        caller.querySelector(BnumHtmlIcon.TAG).icon =
          'keyboard_double_arrow_left';
        caller.setAttribute(
          'title',
          "Minimiser la barre de navigation de l'espace.",
        );
      }

      caller = null;
    });

    let icon = BnumHtmlIcon.Create({ icon: 'keyboard_double_arrow_left' });
    button.appendChild(icon);

    this.style.position = 'relative';
    this.mainDiv.appendChild(button);
    icon = null;
    button = null;
    return this;
  }

  _generate_picture() {
    let img = document.createElement('img');
    img.classList.add('picture');
    img.onload = () => {
      let picture = this.navigator.querySelector('.picture-container img');
      let text = this.navigator.querySelector('.picture-container div');

      if (text) text.remove();

      picture.style.display = null;

      picture = null;
      text = null;
    };
    img.onerror = () => {
      let picture = this.navigator.querySelector('.picture-container img');
      let text = this.navigator.querySelector('.picture-container div');

      picture.style.display = 'none';

      if (!text) {
        text = this.navigator.querySelector('.picture-container');
        let span = document.createElement('div');
        span.classList.add('no-picture', 'colored');
        span.style.backgroundColor = this.workspace.color;

        //Génération de la couleur du texte
        {
          const rgb_1 = mel_metapage.Functions.colors.kMel_extractRGB(
            this.workspace.color,
          );
          const rgb_2 =
            mel_metapage.Functions.colors.kMel_extractRGB('#000000');

          if (
            mel_metapage.Functions.colors.kMel_LuminanceRatioAAA(rgb_1, rgb_2)
          )
            span.style.color = '#000000';
          else span.style.color = '#FFFFFF';
        }

        span.appendChild(this.createText(this.title.slice(0, 3).toUpperCase()));

        text.appendChild(span);
        span = null;
      }

      picture = null;
      text = null;
    };
    img.src = this.picture;

    let div = document.createElement('div');
    div.classList.add('picture-container');
    div.append(img);

    const plugin = rcmail.triggerEvent('wsp.navbar.picture', {
      image: img,
      container: div,
      navBar: this,
      append: true,
    }) ?? { append: true };

    if (plugin.append) {
      if (plugin.container) div = plugin.container;
      this.mainDiv.append(div);
    }

    img = null;
    div = null;

    return this;
  }

  _generate_title() {
    let div = document.createElement('div');
    let span = document.createElement('h2');

    div.classList.add('wsp-title-container');
    span.classList.add('wsp-title');

    let titleText = document.createElement('span');
    titleText.appendChild(this.createText(this.title));

    span.appendChild(titleText);

    let button = document.createElement('button');
    button.classList.add(
      'transparent-bckg',
      'shadow-mel-button',
      'margin-left-5',
    );
    button.setAttribute('title', "Copier l'url de l'espace");

    button.onclick = MelObject.Empty().copy_to_clipboard.bind(
      MelObject,
      MelObject.Url('workspace', {
        params: {
          _uid: this.workspace.uid,
        },
      }).replace('&_is_from=iframe', EMPTY_STRING),
      { text: "L'url de l'espace a bien été copié !" },
    );

    let icon = new BnumHtmlIcon('content_copy');
    button.append(icon);

    // span.append(button);

    div.append(span);

    const plugin = rcmail.triggerEvent('wsp.navbar.title', {
      buttonCopy: button,
      spanTitle: span,
      container: div,
      navBar: this,
      append: true,
    }) ?? { append: true };

    if (plugin.append) {
      if (plugin.container) div = plugin.container;
      this.mainDiv.appendChild(div);
    }

    span = null;
    div = null;
    icon = null;
    button = null;
    titleText = null;

    return this;
  }

  _generate_description() {
    /**
     * Composant "description" de la barre de navigation
     * @type {WspNavBarDescription}
     * @package
     */
    let description = new WspNavBarDescription({
      parent: this,
    }).setNavBarParent(this);

    const plugin = rcmail.triggerEvent('wsp.navbar.description', {
      description,
      navBar: this,
      append: true,
    }) ?? { append: true };

    if (plugin.append) {
      if (plugin.description) description = plugin.description;
      this.mainDiv.appendChild(description);
    }

    description = null;

    return this;
  }

  _generate_hashtag() {
    if (this.workspace.hashtag || false) {
      let hashtag = document.createElement('span');
      hashtag.classList.add('hashtag');
      hashtag.setAttribute(
        'title',
        `#${this.workspace.hashtag} - Thématique de l'espace`,
      );

      hashtag.appendChild(this.createText(`#${this.workspace.hashtag}`));

      this.shadowRoot.appendChild(hashtag);

      hashtag = null;
    }

    return this;
  }

  _generate_block() {
    let block = document.createElement('div');
    block.style.display = 'flex';
    block.style.flexDirection = 'column';
    block.style.marginTop = '15px';
    block.classList.add('options-containers');

    const plugin = rcmail.triggerEvent('wsp.navbar.button_block', {
      block,
      navBar: this,
      addSeparateAtEnd: true,
      break: false,
    }) ?? { break: false, addSeparateAtEnd: true };

    if (!plugin.break) {
      const items = [
        this._generate_send,
        this._generate_invitation,
        this._generate_join,
        this._generate_start_visio,
        // this._generate_leave,
        //this._generate_params,
        //this._generate_members,
      ];

      /**
       * @type {?WspButton}
       */
      let generated;
      for (const callback of items) {
        generated = callback.call(this);

        if (generated) {
          generated.addEventListener(
            'click',
            this.onactionclicked.call.bind(
              this.onactionclicked,
              generated.getAttribute('data-up-nav'),
            ),
          );

          this.#_try_add(block, generated);
          generated = null;
        }
      }

      if (plugin.addSeparateAtEnd) {
        let separate = new BnumHtmlSeparate({ mode: EWebComponentMode.div });
        separate.style.display = 'block';
        separate.style.opacity = 1;
        separate.style.margin = '20px 30px';

        block.appendChild(separate);
        separate = null;
      }
    }

    if (block) this.mainDiv.appendChild(block);

    block = null;
  }

  #_try_add(node, nodeToAdd) {
    if (nodeToAdd) {
      node.appendChild(nodeToAdd);
      nodeToAdd = null;
    }

    return this;
  }

  _generate_invitation() {
    if (this.workspace.isJoin && this.workspace.isAdmin) {
      let button = new WspButton(this, {
        text: 'Inviter un membre',
        icon: 'person_add',
      });

      button.setAttribute('data-up-nav', 'invitation');

      return button;
    }

    return null;
  }

  _generate_leave() {
    if (
      this.workspace.isJoin &&
      !(this.workspace.isAdmin && this.workspace.isAdminAlone)
    ) {
      let button = new WspButton(this, {
        text: "Quitter l'espace",
        icon: 'logout',
      });

      button.setAttribute('data-up-nav', 'leave');

      return button;
    }

    return null;
  }

  _generate_join() {
    if (!this.workspace.isJoin) {
      let button = new WspButton(this, {
        style: WspButton.Style.white,
        text: "Rejoindre l'espace",
        icon: 'add',
      });

      button.setAttribute('data-up-nav', 'join');

      return button;
    }
  }

  _generate_send() {
    if (this.workspace.isJoin && !this.workspace.isPublic) {
      let button = new WspButton(this, {
        style: WspButton.Style.classic,
        text: 'Ecrire aux participants',
        icon: 'mail',
      });

      button.setAttribute('data-up-nav', 'send');

      if (!this.users?.emails || this.users.emails.length <= 1)
        button.disable();

      return button;
    }
  }

  tryUpdateSendButton() {
    let button = this.mainDiv.querySelector('[data-up-nav="send"]');

    if (button) {
      if (!this.users?.emails || this.users.emails.length <= 1)
        button.disable();
      else button.enable();
    }

    return this;
  }

  _generate_start_visio() {
    if (
      this.workspace.isJoin &&
      ((this.workspace.isPublic && this.workspace.isAdmin) ||
        !this.workspace.isPublic) &&
      rcmail.env.plugin_list_visio === true
    ) {
      let button = new WspButton(this, {
        style: WspButton.Style.white,
        text: 'Visioconférence',
        icon: 'videocam',
      });

      button.setAttribute('data-up-nav', 'visio');

      return button;
    }
  }

  _generate_params() {
    if (this.workspace.isJoin && this.workspace.isAdmin) {
      let button = new WspButton(this, {
        style: WspButton.Style.white,
        text: 'Paramètres',
        icon: 'settings',
      });

      button.setAttribute('data-up-nav', 'settings');

      return button;
    }
  }

  _generate_members() {
    if (this.workspace.isJoin && !this.workspace.isAdmin) {
      let button = new WspButton(this, {
        style: WspButton.Style.white,
        text: 'Voir les membres',
        icon: 'info',
      });

      return button;
    }
  }

  #_get_data(data) {
    if (!this.#data[data]) {
      this.#data[data] =
        this.dataset[data] ?? this.getAttribute(`data-${data}`);
      this.removeAttribute(`data-${data}`);
    }

    return this.#data[data];
  }

  #_generate_script(file, { module = false } = {}) {
    let script = document.createElement('script');

    if (module) file += `?v=${BnumModules.VERSION}`;

    script.src = file;

    if (module) script.setAttribute('type', 'module');

    return script;
  }

  #_generate_css(file) {
    let css = document.createElement('link');
    css.setAttribute('rel', 'stylesheet');
    css.setAttribute('type', 'text/css');
    css.setAttribute('href', file);

    return css;
  }

  #_setup_modules() {
    return this.#_setup_files_type(EFileType.module);
  }

  #_setup_scripts() {
    return this.#_setup_files_type(EFileType.script);
  }

  /**
   *
   * @param {EFileType} type
   */
  #_setup_files_type(type) {
    let dataset = null;

    switch (type) {
      case EFileType.module:
        dataset = 'modules';
        break;

      case EFileType.script:
        dataset = 'scripts';
        break;

      case EFileType.style:
        dataset = 'css';
        break;

      default:
        throw new Error('Type non pris en charge');
    }

    const data = (this.data(dataset) ?? EMPTY_STRING)
      .replaceAll(' ', EMPTY_STRING)
      .split(',');

    this.removeAttribute(`data-${dataset}`);

    if (data.length > 0) {
      let generated;
      for (const element of data) {
        if (element === '' || !element) continue;

        switch (type) {
          case EFileType.module:
            generated = this.#_generate_script(element, { module: true });
            break;

          case EFileType.script:
            generated = this.#_generate_script(element, { module: false });
            break;

          case EFileType.style:
            generated = this.#_generate_css(element);
            break;

          default:
            throw new Error('Type non pris en charge');
        }

        this.shadowRoot.append(generated);
        generated = null;
      }
    }

    return this;
  }

  #_setup_styles() {
    let style = document.createElement('style');
    style.appendChild(this.createText(this.data('css')));
    this.navigator.appendChild(style);
    style = null;
    this.removeAttribute('data-css');
    return this;
  }

  hide() {
    this.style.display = 'none';
  }

  show() {
    this.style.display = EMPTY_STRING;
  }

  select(task, { background = true } = {}) {
    this.pageNavigation.select(task, { background });
    return this;
  }

  unselect({ task = 'all', background = true } = {}) {
    this.pageNavigation.unselect({ task, background });
    return this;
  }

  quit() {
    this.mainDiv.querySelector('#wsp-quit-button').click();
  }

  static AddActions(action) {
    this.#actions.push(action);
  }

  static CreateElement({
    nav = document,
    workspace = null,
    css = null,
    modules = null,
    scripts = null,
    settings = null,
    onuserrequested = null,
    onuserchanged = null,
  } = {}) {
    /**
     * @type {WspNavBar}
     */
    let node = nav.createElement('bnum-wsp-nav');

    if (workspace) {
      if (typeof workspace !== 'string')
        workspace = JSON.stringify(workspace).replaceAll('"', "¤'¤'");

      node.setAttribute('data-workspace', workspace);
    }

    if (css) node.setAttribute('data-css', css);
    if (modules) node.setAttribute('data-modules', modules);
    if (scripts) node.setAttribute('data-scripts', scripts);
    if (settings) node.setAttribute('data-apps-settings', settings);

    if (onuserrequested) node.onuserrequested.push(onuserrequested);
    if (onuserchanged) node.onuserchanged.push(onuserchanged);

    return node;
  }

  static CreateElementFromData(
    uid,
    title,
    description,
    picture,
    { nav = document } = {},
  ) {
    return this.CreateElement({
      nav,
      workspace: { uid, title, description, picture },
    });
  }
}

{
  const TAG = 'bnum-wsp-nav';
  if (!customElements.get(TAG)) customElements.define(TAG, WspNavBar);
}