// import { createApp } from 'vue'
import '../scss/main.scss'

import "splitting/dist/splitting.css";
import "splitting/dist/splitting-cells.css";
import Splitting from "splitting";
import { hyphenateSync } from "hyphen/fr";
import { gsap, Power1 } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
import Lenis from 'lenis';
import 'fslightbox';

gsap.registerPlugin(ScrollTrigger);

// import Content from './vuejs/Content.vue'

// import REST from './api/rest-axios'

// import LocomotiveScroll from 'locomotive-scroll';
// const scroll = new LocomotiveScroll();


// /**
//  * @file
//  * https://www.drupal.org/docs/drupal-apis/javascript-api/javascript-api-overview
//  */
// (function (Drupal) {

//   'use strict';

//   Drupal.behaviors.leshed = {
//     attach: function (context, settings) {
//       console.log('It works!');
//     }
//   };

// } (Drupal));

(function (Drupal, drupalSettings) {
  const LeShedTheme = function () {
    const _is_front = drupalSettings.path.isFront
    console.log('drupalSettings', drupalSettings)

    const scroller = document.querySelector('main[role="main"]');
    const gsap_mm = gsap.matchMedia();
    console.log('gsap_mm', gsap_mm);

    //  ___      _ _
    // |_ _|_ _ (_) |_
    //  | || ' \| |  _|
    // |___|_||_|_|\__|
    function init () {
      console.log('LeShedTheme init()');
      console.log('deploy test to delete');

      initTitles();
      initBurgerMenu();
      initSmoothScroll();
      initHomeColumnScrollSync();
      initFsLightbox();
      initPageFull();
      // initVues()
    }


    function onWindowResize() {
      _cardsForms.forEach(({card, forme, formepos}) => {
        // console.log(`card`, card, 'forme', forme, 'formepos', formepos);
        forme.style.top = `${card.offsetTop + formepos.top}px`;
        forme.style.left = `${card.offsetLeft + formepos.left}px`;
      })
    }

    function randomInt(min, max) {
      return Math.floor(Math.random() * (max - min)) + min;
    }

    // Rendu typographique des titres. Police Epilogue = axe variable `wght`
    // (100–900) uniquement ; l'italique est un fichier séparé (font-style).
    const TITLE_STYLE = {
      // 3 groupes de graisse : thin = majorité (défaut), medium = quelques,
      // bold = les pics. Les fines ne sont pas comptées (c'est le reste).
      wghtThin: { min: 100, max: 200 },   // majorité (défaut)
      wghtMedium: { min: 200, max: 400 }, // quelques
      wghtBold: { min: 800, max: 900 },   // pics
      boldRatio: 0.28,                    // proportion de pics gras par mot
      mediumRatio: 0.12,                  // proportion de medium par mot
      italicOnBold: 0.6,                  // proba d'italique sur un pic
      italicOnMedium: 0.4,                // proba d'italique sur un medium
      italicOnThin: 0.30,                 // proba d'italique sur une fine
    };

    function initTitles() {
      const titles = document.querySelectorAll('#block-leshed-identitedusite>a, article.node-type-projet>header>h2, article.node-type-projet>.cols>.left>h2, article.node-type-projet.view-mode-full h2.node-title');
      for (const txt of titles) {
        txt.classList.add("variable-title");
        const splitted = Splitting({ target: txt, by: 'chars' });
        for (const word of splitted[0].words) {
          const chars = Array.from(word.getElementsByClassName('char'));
          styleWordChars(chars);
          hyphenateWord(chars);
        }
      }

    }

    /**
     * Tire k positions réparties régulièrement dans [0, n[ : le mot est découpé
     * en k cases contiguës, une position au hasard par case (aléa contrôlé, pas
     * de paquets). Les positions déjà prises par un autre groupe sont évitées.
     */
    function spreadPositions(n, k, exclude = new Set()) {
      const set = new Set();
      for (let i = 0; i < k; i++) {
        const start = Math.floor((i * n) / k);
        const end = Math.floor(((i + 1) * n) / k); // borne exclue
        const span = Math.max(1, end - start);
        let pos = randomInt(start, start + span);
        let guard = 0;
        while ((exclude.has(pos) || set.has(pos)) && guard < span) {
          pos = start + ((pos - start + 1) % span);
          guard++;
        }
        set.add(pos);
      }
      return set;
    }

    /**
     * Applique graisse + italique caractère par caractère.
     *
     * Majorité de fines ; quelques medium et quelques pics gras, chacun réparti
     * régulièrement dans le mot. L'italique est corrélé à la graisse.
     */
    function styleWordChars(chars) {
      const n = chars.length;
      if (!n) return;

      // Accents répartis régulièrement : d'abord les pics gras, puis les medium
      // (en évitant les positions déjà grasses). Le reste sera fin.
      const bold = spreadPositions(n, Math.round(n * TITLE_STYLE.boldRatio));
      const medium = spreadPositions(n, Math.round(n * TITLE_STYLE.mediumRatio), bold);

      // 1) Décide graisse + italique pour chaque caractère.
      const decisions = chars.map((char, i) => {
        let range, pItal;
        if (bold.has(i)) {
          range = TITLE_STYLE.wghtBold;
          pItal = TITLE_STYLE.italicOnBold;
        }
        else if (medium.has(i)) {
          range = TITLE_STYLE.wghtMedium;
          pItal = TITLE_STYLE.italicOnMedium;
        }
        else {
          range = TITLE_STYLE.wghtThin;
          pItal = TITLE_STYLE.italicOnThin;
        }
        return {
          char,
          wght: randomInt(range.min, range.max + 1),
          ital: Math.random() < pItal,
        };
      });

      // 2) Au moins une italique par mot : si aucune, on en force une, de
      //    préférence sur un pic gras ou un medium, sinon sur une lettre au hasard.
      if (!decisions.some((d) => d.ital)) {
        const accents = [...bold, ...medium];
        const idx = accents.length ? accents[randomInt(0, accents.length)] : randomInt(0, n);
        decisions[idx].ital = true;
      }

      // 3) Pas plus de 2 italiques consécutives : on casse les séries de 3+.
      let run = 0;
      for (const d of decisions) {
        if (d.ital) {
          run += 1;
          if (run > 2) {
            d.ital = false;
            run = 0;
          }
        }
        else {
          run = 0;
        }
      }

      // 4) Applique.
      for (const { char, wght, ital } of decisions) {
        char.style.fontVariationSettings = `'wght' ${wght}`;
        char.style.fontStyle = ital ? 'italic' : 'normal';
        char.classList.toggle('italic', ital);
        char.classList.toggle('normal', !ital);
      }
    }

    /**
     * Insère des césures logicielles (U+00AD) aux points de coupure valides.
     *
     * Comme chaque lettre est un span (display:inline) sans « run » de texte
     * continu, `hyphens: auto` est inopérant : on calcule donc les points de
     * césure (motifs FR) et on insère un soft hyphen — en nœud texte, entre les
     * lettres concernées — qui n'autorise une coupure (avec tiret) qu'à ces
     * endroits. Les mots trop longs coupent proprement au lieu de casser
     * n'importe où.
     */
    function hyphenateWord(chars) {
      if (chars.length < 5) return;
      const SOFT = '\u00AD';
      const text = chars.map((c) => c.textContent).join('');
      const hyphenated = hyphenateSync(text);
      if (!hyphenated.includes(SOFT)) return;

      let letter = 0;
      for (const ch of hyphenated) {
        if (ch === SOFT) {
          const target = chars[letter];
          if (letter > 0 && target && target.parentNode) {
            target.parentNode.insertBefore(document.createTextNode(SOFT), target);
          }
        }
        else {
          letter++;
        }
      }
    }

    function initBurgerMenu() {
      let header_right = document.getElementById('burger-btn');
      header_right.parentElement.addEventListener('click', function(e){
        // console.log('click header_right', this);
        this.firstElementChild.toggleAttribute('opened');
        this.firstElementChild.nextElementSibling.toggleAttribute('opened');
      })
    }

    /**
     * Scroll lissé (Lenis) sur le conteneur `main` — et non la fenêtre, car
     * c'est `main[role="main"]` qui porte l'overflow. Lenis est branché sur le
     * ticker GSAP (une seule boucle RAF) et pousse ses updates à ScrollTrigger
     * pour que la synchro des colonnes reste calée sur le scroll lissé.
     */
    function initSmoothScroll() {
      const scroller = document.querySelector('main[role="main"]');
      const content = scroller && scroller.querySelector('.layout-content');
      if (!scroller || !content) return;

      const lenis = new Lenis({
        wrapper: scroller,   // conteneur scrollable custom
        content: content,    // contenu réel (le 1er enfant est l'ancre skip-link)
        duration: 1.2,
        smoothWheel: true,
      });

      lenis.on('scroll', ScrollTrigger.update);
      gsap.ticker.add((time) => lenis.raf(time * 1000));
      gsap.ticker.lagSmoothing(0);
    }

    /**
     * Synchronise le scroll des deux colonnes du layout 50/50 : la colonne la
     * plus courte est ralentie (translateY décroissant) pour que son bas soit
     * atteint en même temps que celui de la colonne la plus haute, qui défile
     * nativement (flux normal, pas de pin). Le scroll réel a lieu dans
     * `main[role="main"]`, pas dans la fenêtre : GSAP utilise donc ce conteneur
     * comme `scroller`.
     */
    function initHomeColumnScrollSync() {
      console.log('initHomeColumnScrollSync');

      const firstColumn = document.querySelector('.layout--twocol-section--50-50 .layout__region--first');
      const secondColumn = document.querySelector('.layout--twocol-section--50-50 .layout__region--second');
      console.log(scroller, firstColumn, secondColumn);

      if (!scroller || !firstColumn || !secondColumn) return;


      gsap_mm.add('(min-width: 768px)', () => {
        [firstColumn, secondColumn].forEach((column) => {
          gsap.to(column, {
            // Distance à parcourir pour que le bas de la colonne arrive en
            // bas du viewport en même temps que la colonne la plus haute.
            y: () => {
              const visibleHeight = scroller.clientHeight;
              const scrollRange = scroller.scrollHeight - scroller.clientHeight;
              const columnRevealRange = Math.max(0, column.offsetHeight - visibleHeight);
              return scrollRange - columnRevealRange;
            },
            ease: 'none',
            scrollTrigger: {
              scroller: scroller,
              start: 0,
              end: 'max', // scroll maximum du conteneur (robuste au resize)
              // Valeur numérique = easing : l'animation met ~0.6s à rattraper la
              // position de scroll au lieu de la suivre au pixel près → lisse les
              // à-coups de la colonne lente. Monter la valeur = plus d'inertie.
              scrub: true,
              invalidateOnRefresh: true,
            },
          });
        });

        // Nettoyage automatique des tweens/triggers quand on repasse sous 768px.
        return () => {};
      });

      // Les images chargent après coup et changent la hauteur des colonnes.
      window.addEventListener('load', () => ScrollTrigger.refresh());
    }

    function initPageFull(){
      console.log('initPageFull');

      // PAGE TITLE SCALING DOWN
      const pageTitle = document.querySelector('article.node-type-projet.view-mode-full h2.node-title');
      console.log('pageTitle', pageTitle);

      if (pageTitle) {
        // needs requestAnimationFrame to get the real titleHeight after splitting
        requestAnimationFrame(() => {
          requestAnimationFrame(() => {

            const initTitleH = pageTitle.offsetHeight;
            // console.log(`initTitleH: ${initTitleH}`);
            const titleScaleTarget = 0.4;
            const end = initTitleH - initTitleH * titleScaleTarget;
            // console.log(`end: ${end}`);

            gsap_mm.add('(min-width: 768px)', () => {
                gsap.to(pageTitle, {
                  scale: titleScaleTarget,
                  y: end,
                  ease: 'none',
                  scrollTrigger: {
                    scroller: scroller,
                    start: 0,
                    end: end, // scroll maximum du conteneur (robuste au resize)
                    scrub: true,
                    invalidateOnRefresh: true,
                  },
                });
            })
          });
        });
      }

      // BLOCAGE DE LA COLONNE GAUCHE
      // La gauche défile normalement puis se fige (pin) quand le bas de son
      // contenu atteint le bas du viewport, pendant que la colonne droite (plus
      // haute) continue. Piloté en GSAP plutôt qu'en `position: sticky` (qui ne
      // prend pas dans ce contexte scroller custom + GSAP). `.cols` est en
      // `align-items: flex-start`, donc .col.left a bien la hauteur de son
      // contenu (sinon `bottom bottom` tomberait à la fin du scroll).
      const cols = document.querySelector('article.node-type-projet.view-mode-full .cols');
      const leftColumn = cols && cols.querySelector('.col.left');
      if (cols && leftColumn) {
        // Doit rester identique au scale-down du titre (voir plus haut).
        const titleScaleTarget = 0.4;
        // Seuil de scroll (px) après lequel la colonne gauche se fige :
        // - gauche plus haute que le viewport : quand son bas atteint le bas ;
        // - gauche plus courte : quand le scale-down du titre est terminé, pour
        //   qu'elle remonte AVEC le titre puis s'arrête (sans disparaître en haut).
        const leftFreezeStart = () => {
          const overflow = leftColumn.offsetHeight - scroller.clientHeight;
          if (overflow > 0) return overflow;
          return pageTitle ? pageTitle.offsetHeight * (1 - titleScaleTarget) : 0;
        };

        gsap_mm.add('(min-width: 768px)', () => {
          // On NE pin PAS (le pin sort l'élément du flux et casse le flex .cols).
          // On translate la colonne : défilement natif jusqu'à `leftFreezeStart`,
          // puis contre-translation 1:1 du scroll → elle se fige, tout en restant
          // un flex-item normal (la colonne droite garde sa place).
          gsap.fromTo(leftColumn,
            { y: 0 },
            {
              y: () => (scroller.scrollHeight - scroller.clientHeight) - leftFreezeStart(),
              ease: 'none',
              scrollTrigger: {
                scroller: scroller,
                start: leftFreezeStart, // px de scroll où la gauche se fige
                end: 'max',
                scrub: true,
                invalidateOnRefresh: true,
              },
            }
          );
        });
      }

    }


    function initFsLightbox(){
      console.log('initFsLightbox');
      // console.log(window.FsLightbox);
      let imgs_links = document.querySelectorAll('article.node-type-projet.view-mode-full .field_images.multiple .field-item a');
      for (const link of imgs_links) {
        link.setAttribute("data-fslightbox", "gallery")
      }
      // window.FsLightbox
      window.refreshFsLightbox();
    }

    // function initVues(){
    //   console.log('initVues');

    //   // initVueContent();


    // }

    // function initVueContent(){
    //   createApp(Content).mount('main[role="main"]');

    //   // processEtapeLinks();
    // }


    // function onClickEtapeLink(e){
    //   e.preventDefault();

    //   let a = e.currentTarget;
    //   let nid = a.dataset.nodeNid;
    //   console.log(nid);

    //   getNodeData(nid);

    //   return null;
    // }


    // function processEtapeLinks(){
    //   let etape_link_fields = document.querySelectorAll('#etapes-liste div.views-field-title');
    //   etape_link_fields.forEach((field, index) => {
    //     let nid = null;
    //     let classList = field.classList;
    //     classList.forEach((classe) => {
    //       let reg = /data-node-(\d+)/;
    //       let result = classe.match(reg);
    //       if (result) {
    //         nid = result[1];
    //         console.log(nid);
    //       }
    //     })

    //     if (nid) {
    //       let a = field.querySelector('a');
    //       a.setAttribute('data-node-nid', nid);
    //       a.addEventListener('click', onClickEtapeLink);
    //     }


    //   })
    // }

    // function getNodeData(nid){
    //   const params = {
    //   }
    //   REST.get(`/node/${nid}?_format=json`, params)
    //   .then((data) => {
    //     console.log('user REST getUser data', data)
    //   })
    //   .catch(error => {
    //     console.warn('Issue with getNodedata', error)
    //     Promise.reject(error)
    //   })
    // }

    init()
  } // end LeShedTheme()

  LeShedTheme()
})(Drupal, drupalSettings)
