import { Button } from '@SharePoint/rencredit_uikit';
import React, { useEffect, useState } from "react";

function MenuApp ()
{
  //Приложения и процессы Magic для отображения в меню
  const [menuApps, setMenuApps] = useState<{
    'proccesses': object,
    'scripts': object
  }>({
    'proccesses': {},
    'scripts': {}
  });
  //TODO
  //ВНЕДРИ В КОНТРОЛЛЕРЕ ПРОВЕРКУ ДОСТУПОВ, А НЕ ВОЗВРАЩАЙ ВСЕ ПОДРЯД ПРИЛОЖЕНИЯ
  //Избранные приложения пользователя
  const [favApps, setFavApps] = useState<string[]>([]);
  //Массив избраннных процессов, в приложениях которых есть хотя бы одно избранное
  const [favProcs, setFavProcs] = useState<string[]>([]);
  //Состояния видимости скрипта
  const [hideScriptClass, setHideScriptClass] = useState('');
  //const [sanctumToken, setSanctumToken] = useState('');

  const sanctumToken = () => {
    const metaTag = document.getElementById('sanctum_token_block') as HTMLMetaElement;
    return metaTag.dataset.token;
  }

  //Получаем при рендере страницы все приложения Magic и все избранные приложения пользователя
  useEffect( () => {
    Promise.all(
      [
        fetch('api/magic_apps').then(menuAppsRes => menuAppsRes.json()),
        //TODO
        //СЮДА ПОТЯГИВАЙ ЛОГИН ПОЛЬЗОВАТЕЛЯ, А НЕ DGAVRILOV
        fetch('api/user_fav_app/dgavrilov').then(favAppsRes => favAppsRes.json())
      ]
    ).then(
      ([
        responseMenuApp,
        responseFavApp
      ]) => {
        setMenuApps(responseMenuApp);
        setFavApps(responseFavApp);
      }
    )
  }, []);


  //Обновление видимости процесса (собрания приложений) в зависимости от того находится ли в избранном хотя бы одно приложение
  useEffect( () => {
    if (menuApps === null) { return }
    //Массив с процессами, в которых есть хотя бы одно избранное приложение
    const favProcsArr:string[] = [];
    //Мы собираем все избранные приложения в массив-состояние, чтобы при изменении состояния каждого приложения (например при переключении switcher) проверять входит ли это приложение в избранные. Если входит - его родительский процесс не прячем, так как в его дочерних приложениях есть избранные
    Object.entries(menuApps.proccesses).forEach( (procData) => {
      //Флаг - есть ли в приложениях процесса хотя бы 1 избранное
      const hasFavorite: boolean = procData[1].tabs.split(';').some( (tab: string) => {
        return favApps.includes(tab);
      })
      if (hideScriptClass !== 'script-hide' || hasFavorite) {
        favProcsArr.push(procData[0]);
      }
    })
    setFavProcs(favProcsArr);
  }, [hideScriptClass, menuApps, favApps]);

  //console.log(sanctumToken())

  //ГАВРИЛОВ
  //ПОЧЕМУ КОД НИЖЕ ИСПОЛНЯЕТСЯ ПОСТОЯННО ПОКА НЕ БУДЕТ ПОЛУЧЕН КОНТЕНТ ДЛЯ СТРАНИЦЫ ИЗ ПРОМИСОВ ВЫШЕ, А НЕ ОТРАБАТЫВАЕТ ТОЛЬКО ПРИ РЕНДЕРИНГЕ СТРАНИЦЫ
  //Уместно ли отслеживать состояние до получения запросов fetch в подобном виде?
  if (menuApps === null || favApps === null) {
    return <span>прелоадер</span>
  } else {
    return (
      <div id = 'menu-container'>
        <div id = 'menu__left-block'>
          <div className = 'menu__left-block__call-app'>
            <i className = 'fa fa-th-large'></i>
            <div className = 'mleft-block__call-app__title'>Приложения</div>
          </div>
        </div>
        <div id = 'menu__app-container'>
          <Button text='Текст' />
          <div id = 'menu__app-container__app-block'>
            {/* {console.log(menuApps.scripts)} */}
              {Object.entries(menuApps.proccesses).map( (proc_val, proc_index) => (
                <div className = "apps-block__proc" key = { proc_index } data-proc = {proc_val[0]}>
                  {/* В зависимости от того входит процесс в массив избранных делаем его видимым или скрываем */}
                  <div className = {`proc__title ${favProcs.includes(proc_val[0]) ? 'proc-visible' : 'proc-hide'}`}>{proc_val[1].title}</div>
                  <div className = "proc__script-list">
                    {proc_val[1].tabs.split(';').map( (app_el, app_index) => (
                      <AppElem 
                        appIndex = { app_index }
                        appName = { app_el }
                        appTitle = { menuApps.scripts[app_el]?.title || "Неизвестный скрипт - " + app_el }
                        appUrl = { menuApps.scripts[app_el]?.url }
                        favIconClassName = { favApps.includes(app_el) ? 'favorite' : 'not_favorite' }
                        hideAppClass = { hideScriptClass }
                        //Функция обновления актуальный список избранных приложений
                        setUpdateFavApps = { (newFavApp) => setFavApps(newFavApp) }
                      />
                    ))}
                  </div>
                </div>
              )) }
          </div>
          <Switcher 
            toggleAppsVisible = { setHideScriptClass }
            switcherId = "switcher-menu"
          />
        </div>
      </div>
    )
  }
}


//Гаврилов
//ПЕРЕПИСАТЬ АРГУМЕНТЫ ПОД ОБЪЕКТ СО СВОЙСТВАМИ, ИСПОЛЬЗОВАТЬ ...obj
/**
 * 
 * @param {int} appIndex ключ для экземлпяра компонента 
 * @param {string} appName уникальное имя скрипта 
 * @param {string} appTitle название скрипта в меню 
 * @param {string} favIconClassName класс для иконки избранного
 * @param {string} hideAppClass класс для видимости приложения
 * @param {string} setUpdateFavApps функция для обновления состояния избранны приложений (при снятия, установки признака избранности)
 * @returns 
 */
function AppElem({ 
  appIndex, 
  appName, 
  appTitle, 
  appUrl, 
  favIconClassName, 
  hideAppClass, 
  setUpdateFavApps 
} : {
  appIndex: string, 
  appName: string, 
  appTitle: string, 
  appUrl: string, 
  favIconClassName: string, 
  hideAppClass: string, 
  setUpdateFavApps: string
}) {
  const [appElemClass, changeFav] = useState(favIconClassName);
  const callChangeFav = ( changeAppName: string ) => {
    fetch('api/user_fav_app', {
        method: 'post',
        body: JSON.stringify({ appName: changeAppName }),
        headers: {
          'content-type': 'application/json'
        }
      }
    )
    .then( (response) => response.json() )
    .then( (response) => {
      //Если скрипт был избранным - удаляем из избранного и наоборот
      appElemClass == 'favorite' ? changeFav('not_favorite') : changeFav('favorite');
      //Возвращаем обновленный список избранных приложений пользователя
      setUpdateFavApps(response?.fav_apps?.split( ';' ) || [])
    } )
  }
  
  return (
    //Если приложение в избранном - оно всегда должно быть "видимо", даже если переключатель в положении Скрыть неизбранные приложения
    <div key = { appIndex } className = {`script-list__el ${appElemClass == 'favorite' ? '' : hideAppClass}`} data-scriptname = { appName }>
      <div className = "script-list__el__script-name"><a target="_blank" href={ appUrl }>{ appTitle }</a></div>
      {/* Анонимная функция нужна для создания функции смены состояния для каждого компонента в отдельности, в противном случае вызов функции в одном экземпляре компонента вызывает функцию изменения для каждого экземпляра компонента */}
      <i className = {`${(appElemClass == 'favorite' ? 'fas' : 'far')} fa-star ${appElemClass}`} onClick = { () => callChangeFav(appName) }></i>
    </div>
  )
}


//TODO
//ВЫНЕСИ В ПАПКУ COMPONENTS/MAIN
/**
 * Компонент переключателя В ДАННОМ СЛУЧАЕ видимости скриптов (видны только избранные или все)
 * @param {string} switcherId идентификатор переключателя (для стилей css), так как в будущем, на странице можно будет размещать несколько переключателей
 * @param {function} toggleAppsVisible функция обновления состояния hideScriptClass
 * @returns 
 */
function Switcher({ switcherId, toggleAppsVisible }) {
  const [favSwitcherClass, setFavSwitcherClass] = useState('showAll');

  //Переключение состояния переключателя после рендеринга страницы
  useEffect( () => {
    //Получаем из локал сторадж состояние переключателя
    const savedState = localStorage.getItem('magicMenuFavSwitcher');
    if (savedState) {
      setFavSwitcherClass(savedState);
    }
  }, []);

  //При изменении состояния Переключателя изменяется состояние всех приложени (переключается их видимость в зависимости от состояния переключателя - только избранные или все)
  useEffect( () => {
    //Синхронизируем зависимые компоненты
    toggleAppsVisible(favSwitcherClass === 'showFav' ? 'script-hide' : '');
  }, [favSwitcherClass] );

  const callToggleFavSwitcher = () => {
    let switcherState = (favSwitcherClass === 'showFav' ? 'showAll' : 'showFav');
    //favSwitcherClass => favSwitcherClass = ... - функциональное обновление. Здесь оно не особо нужно, но чтобы не забыть
    //Меняем класс switcher, а также меняем состояние видимости всех приложений (в зависимости от того избранные они или нет)
    setFavSwitcherClass( favSwitcherClass => {
      if (favSwitcherClass === 'showFav') {
        toggleAppsVisible('script-hide')
      } else {
        toggleAppsVisible('')
      }
      localStorage.setItem('magicMenuFavSwitcher', switcherState)

      return switcherState;
    } )
  }

  return (
    <div id = { switcherId } className = "switcher-container">
      <label className = "switch">
        <input type = "checkbox" className = {`switcher__favorite-app ${favSwitcherClass}`} onChange = { callToggleFavSwitcher }/>
        <span className = "slider round"></span>
      </label>
    </div>
  )
}

export default MenuApp;
