#!/bin/bash
# Script de manipulation des containers en masse
# init /versions / restart ...
#

KAZ_ROOT=$(cd "$(dirname $0)"/..; pwd)
. $KAZ_ROOT/bin/.commonFunctions.sh
setKazVars
. $DOCKERS_ENV
. $KAZ_ROOT/secret/env-kaz

PRG=$(basename $0)

#######################################
# tout est dans le env_kaz
# NAS_VOL="/mnt/disk-nas1/docker/volumes/"

# OPERATE_ON_MAIN=                 # par defaut NON on ne traite que des orgas
# OPERATE_ON_NAS_ORGA="OUI"        # par defaut oui, on va aussi sur les orgas du NAS
# OPERATE_LOCAL_ORGA="OUI"         # par defaut oui

# TEMPO_ACTION_STOP=2              # Lors de redémarrage avec tempo, on attend après le stop
# TEMPO_ACTION_START=60            # Lors de redémarrage avec tempo, avant de reload le proxy

# DEFAULTCONTAINERS="cloud agora wp wiki office paheko castopod spip"

# APPLIS_PAR_DEFAUT="tasks calendar contacts bookmarks mail richdocuments external drawio snappymail ransomware_protection" #rainloop richdocumentscode 

# QUIET="1"                    # redirection des echo

###################################################################################################################

#GLOBAL VARS

availableOrga=($(getList "${KAZ_CONF_DIR}/container-orga.list"))
AVAILABLE_ORGAS=${availableOrga[*]//-orga/}

availableContainersCommuns=( $(getList "${KAZ_CONF_DIR}/container-withMail.list")  $(getList "${KAZ_CONF_DIR}/container-withoutMail.list"))

CONTAINERS_TYPES=


declare -A DockerServNames          # le nom des containers correspondant
DockerServNames=( [cloud]="${nextcloudServName}" [agora]="${mattermostServName}" [wiki]="${dokuwikiServName}" [wp]="${wordpressServName}" [office]="${officeServName}" [paheko]="${pahekoServName}" [castopod]="${castopodServName}" [spip]="${spipServName}" [webdav]="${webdavServName}" )

declare -A FilterLsVolume      # Pour trouver quel volume appartient à quel container
FilterLsVolume=( [cloud]="cloudMain" [agora]="matterConfig" [wiki]="wikiConf" [wp]="wordpress" [castopod]="castopodMedia" [spip]="spip")

declare -A composeDirs       # Le nom du repertoire compose pour le commun
composeDirs=( [cloud]="cloud" [agora]="mattermost" [wiki]="dokuwiki" [office]="collabora" [paheko]="paheko" [castopod]="castopod" [spip]="spip")

declare -A serviceNames       # Le nom du du service dans le dockerfile d'orga 
serviceNames=( [cloud]="cloud" [agora]="agora" [wiki]="dokuwiki" [wp]="wordpress" [office]="collabora" [castopod]="castopod" [spip]="spip")

declare -A subScripts
subScripts=( [cloud]="manageCloud.sh" [agora]="manageAgora.sh" [wiki]="manageWiki.sh" [wp]="manageWp.sh" [castopod]="manageCastopod.sh" )

declare -A OrgasOnNAS
declare -A OrgasLocales
declare -A NbOrgas
declare -A RunningOrgas
declare -A Posts


OCCCOMANDS=()
MMCTLCOMANDS=()
EXECCOMANDS=()



usage() {
echo "${PRG} [OPTION] [CONTAINERS_TYPES] [COMMANDES] [ORGAS]
Ce script regroupe l'ensemble des opérations que l'on souhaite automatiser sur plusieurs containers
Par defaut, sur les orgas, mais on peut aussi ajouter les communs

OPTIONS 
 -h|--help          Cette aide :-)
 -n|--simu          SIMULATION
 -q|--quiet         On ne parle pas (utile avec le -n pour avoir que les commandes)
 -m|--main          Traite aussi le container commun (cloud commun / agora commun / wiki commun)
 -M                 Ne traite que le container commun, et pas les orgas
 --nas              Ne traite QUE les orgas sur le NAS
 --local            Ne traite pas les orgas sur le NAS
 -v|--version       Donne la version des containers et signale les MàJ
 -l|--list          Liste des containers (up / down, local ou nas) de cette machine

CONTAINERS_TYPES
 -cloud             Pour agir sur les clouds
 -agora             Pour agir sur les agoras
 -wp                Les wp
 -wiki              Les wiki
 -office            Les collabora
 -paheko	    Le paheko
 -castopod          Les castopod
 -spip             Les spip

COMMANDES (on peut en mettre plusieurs dans l'ordre souhaité)
 -I|--install       L'initialisation du container
 -t                 Redémarre avec tempo (docker-compose down puis sleep ${TEMPO_ACTION_STOP} puis up puis sleep ${TEMPO_ACTION_START})
 -r                 Redémarre sans tempo (docker restart)
 -exec \"command\"    Envoie une commande docker exec

 --optim            Lance la procédure Nextcloud pour optimiser les performances          **               **
 -occ \"command\"     Envoie une commande via occ                                           **               **
 -u                 Mets à jour les applis                                                **  SPECIFIQUES  **
 -i                 Install des applis                                                    **      CLOUD    **
 -a \"app1 app2 ...\"  Choix des appli à installer ou mettre à jour (entre guillemets)      **               **
 -U|--upgrade       Upgrade des clouds                                                    **               **

 -mmctl \"command\"   Envoie une commande via mmctl                                         **  SPECIFIQUES  **
 -p|--post \"team\" \"message\"  Poste un message dans une team agora                         **      AGORA    **

ORGAS
 [orga1 orga2 ... ] on peut filtrer parmi : ${AVAILABLE_ORGAS}


Exemples : 
${PRG} -office -m -r             restart de tous les collaboras (libére RAM)
${PRG} -cloud -u -r -q -n        Affiche toutes les commandes (-n -q ) pour mettre à jour toutes les applis des clouds + restart (-u -r)
${PRG} -p \"monorga:town-square\" \"Hello\" monorga              # envoie Hello sur le centreville de l'orga monorga sur son mattermost dédié

Valeurs par défaut :

Tempo de Stop    : ${TEMPO_ACTION_STOP}
Tempo de restart : ${TEMPO_ACTION_START}
"
}


####################################################
################ fonctions clefs ###################
####################################################

_populate_lists(){
    # récupère les listes d'orga à traiter
    # on rempli les tableaux OrgasOnNAS / OrgasLocales / NbOrgas ... par type de container

    if [ -z "${CONTAINERS_TYPES}" ]; then 
        # wow, on traite tout le monde d'un coup...
        CONTAINERS_TYPES=${DEFAULTCONTAINERS}
    fi

    for TYPE in ${CONTAINERS_TYPES}; do
        if [ -n "${FilterLsVolume[$TYPE]}" ] ; then # on regarde dans les volumes 
            [ -n "$OPERATE_ON_NAS_ORGA" ] && OrgasOnNAS["$TYPE"]=$( _getListOrgas ${NAS_VOL} ${FilterLsVolume[$TYPE]} )
            [ -n "$OPERATE_LOCAL_ORGA" ] && OrgasLocales["$TYPE"]=$( _getListOrgas ${DOCK_VOL} ${FilterLsVolume[$TYPE]} "SANSLN")
        else # un docker ps s'il n'y a pas de volumes
            [ -n "$OPERATE_LOCAL_ORGA" ] && OrgasLocales["$TYPE"]=$(docker ps --format '{{.Names}}' | grep ${DockerServNames[$TYPE]} | sed -e "s/-*${DockerServNames[$TYPE]}//")
        fi 
        NbOrgas["$TYPE"]=$(($(echo ${OrgasOnNAS["$TYPE"]} | wc -w) + $(echo ${OrgasLocales["$TYPE"]} | wc -w)))
        RunningOrgas["$TYPE"]=$(docker ps --format '{{.Names}}' | grep ${DockerServNames[$TYPE]} | sed -e "s/-*${DockerServNames[$TYPE]}//")
    done
}

_getListOrgas(){
    # retrouve les orgas à partir des volume présents
    # $1 where to lookup
    # $2 filter
    # $3 removeSymbolicLinks
    [ ! -d $1 ] || [ -z "$2" ] && return 1 # si le repertoire n'existe pas on skip
    LIST=$(ls  "${1}" | grep -i orga | grep -i "$2" | sed -e "s/-${2}$//g" | sed -e 's/^orga_//') 
    [ -n "$3" ] && LIST=$(ls -F "${1}" | grep '/' | grep -i orga | grep -i "$2" | sed -e "s/-${2}\/$//g" | sed -e 's/^orga_//') 
    LIST=$(comm -12 <(printf '%s\n' ${LIST} | sort) <(printf '%s\n' ${AVAILABLE_ORGAS} | sort))
    echo "$LIST"
}

_executeFunctionForAll(){
    # Parcours des container et lancement des commandes
    # Les commandes ont en derniers paramètres le type et l'orga et une string parmi KAZ/ORGANAS/ORGALOCAL pour savoir sur quoi on opère
    # $1 function
    # $2 nom de la commande
    # $3 quel types de containers
    # $4 params : quels paramètres à passer à la commande (les clefs sont #ORGA# #DOCKERSERVNAME# #SURNAS# #ISMAIN# #TYPE# #COMPOSEDIR# )
    for TYPE in ${3}; do
        if [ -n "$OPERATE_ON_MAIN" ]; then 
            if [[ -n "${composeDirs[$TYPE]}" && "${availableContainersCommuns[*]}" =~ "${composeDirs[$TYPE]}" ]]; then  # pas de cloud / agora / wp / wiki sur cette instance
                Dockername=${DockerServNames[$TYPE]}
                PARAMS=$(echo $4 | sed -e "s/#ORGA#//g;s/#DOCKERSERVNAME#/$Dockername/g;s/#ISMAIN#/OUI/g;s/#SURNAS#/NON/g;s/#TYPE#/$TYPE/g;s%#COMPOSEDIR#%${KAZ_COMP_DIR}/${composeDirs[$TYPE]}%g" )
                echo "-------- $2 $TYPE COMMUN ----------------------------" >& $QUIET
                eval "$1" $PARAMS
            fi
        fi
        if [[ ${NbOrgas[$TYPE]} -gt 0 ]]; then
            echo "-------- $2 des $TYPE des ORGAS ----------------------------" >& $QUIET
            COMPTEUR=1
            if [ -n "$OPERATE_LOCAL_ORGA" ]; then
                for ORGA in ${OrgasLocales[$TYPE]}; do
                    Dockername=${ORGA}-${DockerServNames[$TYPE]}
                    PARAMS=$(echo $4 | sed -e "s/#ORGA#/${ORGA}/g;s/#DOCKERSERVNAME#/$Dockername/g;s/#ISMAIN#/NON/g;s/#SURNAS#/NON/g;s/#TYPE#/$TYPE/g;s%#COMPOSEDIR#%${KAZ_COMP_DIR}/${ORGA}-orga%g" )
                    echo "${RED} ${ORGA}-orga ${NC}($COMPTEUR/${NbOrgas[$TYPE]})" >& $QUIET
                    eval "$1" $PARAMS
                    COMPTEUR=$((COMPTEUR + 1)) 
                done
            fi
            if [ -n "$OPERATE_ON_NAS_ORGA" ]; then
                for ORGA in ${OrgasOnNAS[$TYPE]}; do
                    Dockername=${ORGA}-${DockerServNames[$TYPE]}
                    PARAMS=$(echo $4 | sed -e "s/#ORGA#/${ORGA}/g;s/#DOCKERSERVNAME#/$Dockername/g;s/#ISMAIN#/NON/g;s/#SURNAS#/OUI/g;s/#TYPE#/$TYPE/g;s%#COMPOSEDIR#%${KAZ_COMP_DIR}/${ORGA}-orga%g" )
                    echo "${RED} ${ORGA}-orga ${NC}($COMPTEUR/${NbOrgas[$TYPE]})" >& $QUIET
                    eval "$1" $PARAMS
                    COMPTEUR=$((COMPTEUR + 1))
                done
            fi
        fi
    done
}


##############################################
################ COMMANDES ###################
##############################################
Init(){
    # Initialisation des containers
    echo "${NC}--------------------------------------------------------" >& $QUIET
    echo "Initialisation" >& $QUIET
    echo "--------------------------------------------------------" >& $QUIET

   _executeFunctionForAll "_initContainer" "Initialisation" "${CONTAINERS_TYPES[@]}" "#TYPE# #ISMAIN# #SURNAS# #ORGA# "
}

restart-compose() {
    # Parcours les containers et redémarre avec tempo
    echo "${NC}--------------------------------------------------------" >& $QUIET
    echo "DOCKER-COMPOSE DOWN puis sleep ${TEMPO_ACTION_STOP}" >& $QUIET
    echo "DOCKER-COMPOSE UP puis sleep ${TEMPO_ACTION_START}"  >& $QUIET
    echo "de ${CONTAINERS_TYPES} pour $NB_ORGAS_STR" >& $QUIET
    echo "--------------------------------------------------------" >& $QUIET

    _executeFunctionForAll "_restartContainerAvecTempo" "Restart" "${CONTAINERS_TYPES[@]}" "#TYPE# #ISMAIN# #COMPOSEDIR#"
    
    ${SIMU} sleep ${TEMPO_ACTION_START}
    _reloadProxy
    echo "--------------------------------------------------------" >& $QUIET
    echo "${GREEN}FIN${NC}  " >& $QUIET
    echo "--------------------------------------------------------" >& $QUIET
}

restart() {
    # Parcours les containers et redémarre
    echo "${NC}--------------------------------------------------------" >& $QUIET
    echo "DOCKER RESTART des ${CONTAINERS_TYPES} pour $NB_ORGAS_STR" >& $QUIET
    echo "--------------------------------------------------------" >& $QUIET

    _executeFunctionForAll "_restartContainer" "Restart" "${CONTAINERS_TYPES[@]}" "#DOCKERSERVNAME#"

    _reloadProxy
    echo "--------------------------------------------------------" >& $QUIET
    echo "${GREEN}FIN${NC}  " >& $QUIET
    echo "--------------------------------------------------------" >& $QUIET
}

version(){
    # Parcours les containers et affiche leurs versions
    echo "${NC}--------------------------------------------------------" >& $QUIET
    echo "VERSIONS" >& $QUIET
    echo "--------------------------------------------------------" >& $QUIET
    _executeFunctionForAll "_versionContainer" "Version" "${CONTAINERS_TYPES[@]}" "#TYPE# #ISMAIN# #ORGA#"
}


listContainers(){
    echo "${NC}--------------------------------------------------------"
    echo "LISTES"
    echo "------------------------------------------------------------"
    for TYPE in ${CONTAINERS_TYPES}; do
        echo "****************** $TYPE ****************"
        _listContainer "$TYPE"
    done
}



######################## Fonctions génériques #######################

_initContainer(){
    # $1 type
    # $2 COMMUN
    # $3 ON NAS
    # $4 orgas
    if [ -n "${subScripts[$1]}" ] ; then
        evalStr="${KAZ_BIN_DIR}/${subScripts[$1]} --install"
        if [ "$3" = "OUI" ]; then evalStr="${evalStr} -nas" ; fi
        if [ ! "$QUIET" = "1" ]; then evalStr="${evalStr} -q" ; fi
        if [ -n "$SIMU" ]; then evalStr="${evalStr} -n" ; fi
        if [ ! "$2" = "OUI" ]; then evalStr="${evalStr} $4" ; fi
        eval $evalStr
    fi
}

_restartContainer(){
    # $1 Dockername
    echo -n "${NC}Redemarrage ... " >& $QUIET
    ${SIMU} 
    ${SIMU} docker restart $1
    echo "${GREEN}OK${NC}" >& $QUIET
}

_restartContainerAvecTempo(){
    # $1 type
    # $2 main container
    # $2 composeDir
    dir=$3
    if [ -z $dir ]; then return 1; fi   # le compose n'existe pas ... par exemple wordpress commun
    cd "$dir"
    echo -n "${NC}Arrêt ... " >& $QUIET
    ${SIMU}
    if [ "$2" = "OUI" ]; then ${SIMU} docker-compose stop ;
    else ${SIMU} docker-compose stop "${serviceNames[$1]}"
    fi 
    ${SIMU} sleep ${TEMPO_ACTION_STOP}
    echo "${GREEN}OK${NC}" >& $QUIET
    echo -n "${NC}Démarrage ... " >& $QUIET
    if [ "$2" = "OUI" ]; then ${SIMU} docker-compose up -d ;
    else ${SIMU} docker-compose up -d "${serviceNames[$1]}"
    fi 
    ${SIMU} sleep ${TEMPO_ACTION_START}
    echo "${GREEN}OK${NC}" >& $QUIET
}


_reloadProxy() {
    availableProxyComposes=($(getList "${KAZ_CONF_DIR}/container-proxy.list"))

    for item in "${availableProxyComposes[@]}"; do
        [ "${item}" = "proxy" ] && ${SIMU} ${KAZ_COMP_DIR}/${item}/reload.sh
    done
}

_versionContainer() {
    # Affiche la version d'un container donné
    # $1 type
    # $2 COMMUN
    # $3 orgas
    if [ -n "${subScripts[$1]}" ] ; then
        evalStr="${KAZ_BIN_DIR}/${subScripts[$1]} --version"
        if [ ! "$2" = "OUI" ]; then evalStr="${evalStr} $3" ; fi
        eval $evalStr
    fi
}


_listContainer(){
    # pour un type donné (cloud / agora / wiki / wp), fait une synthèse de qui est up et down / nas ou local
    # $1 type
    RUNNING_FROM_NAS=$(comm -12 <(printf '%s\n' ${OrgasOnNAS[$1]} | sort) <(printf '%s\n' ${RunningOrgas[$1]} | sort) | sed -e ':a;N;$!ba;s/\n/ /g')
    RUNNING_LOCAL=$(comm -12 <(printf '%s\n' ${OrgasLocales[$1]} | sort) <(printf '%s\n' ${RunningOrgas[$1]} | sort) | sed -e ':a;N;$!ba;s/\n/ /g')
    # tu l'a vu la belle commande pour faire une exclusion de liste
    DOWN_ON_NAS=$(comm -23 <(printf '%s\n' ${OrgasOnNAS[$1]} | sort) <(printf '%s\n' ${RunningOrgas[$1]} | sort) | sed -e ':a;N;$!ba;s/\n/ /g')
    DOWN_LOCAL=$(comm -23 <(printf '%s\n' ${OrgasLocales[$1]} | sort) <(printf '%s\n' ${RunningOrgas[$1]} | sort)| sed -e ':a;N;$!ba;s/\n/ /g')
    NB_SUR_NAS=$(echo ${OrgasOnNAS[$1]} | wc -w)
    NB_LOCAUX=$(echo ${OrgasLocales[$1]} | wc -w)
    NB_RUNNING_SUR_NAS=$(echo $RUNNING_FROM_NAS | wc -w)
    NB_RUNNING_LOCALLY=$(echo $RUNNING_LOCAL | wc -w)
    MAIN_RUNNING="${RED}DOWN${NC}"
    if docker ps | grep -q " ${DockerServNames[$1]}"
    then
      MAIN_RUNNING="${GREEN}UP${NC}"
    fi

    [ -n "${composeDirs[${1}]}" ] && echo "${NC}Le ${1} commun est $MAIN_RUNNING"
    if [[ ${NbOrgas[$1]} -gt 0 ]]; then
        ENLOCALSTR=
        if [[ ${NB_RUNNING_SUR_NAS[$1]} -gt 0 ]]; then ENLOCALSTR=" en local" ; fi
        echo "Orgas : $NB_RUNNING_LOCALLY / $NB_LOCAUX running ${1}$ENLOCALSTR"
        echo "${NC}UP : ${GREEN}${RUNNING_LOCAL}"
        echo "${NC}DOWN : ${RED}$DOWN_LOCAL${NC}"
        if [[ ${NB_RUNNING_SUR_NAS[$1]} -gt 0 ]]; then
            echo "${NC}Orgas : $NB_RUNNING_SUR_NAS / $NB_SUR_NAS running depuis le NAS :"
            echo "${NC}UP : ${GREEN}${RUNNING_FROM_NAS}"
            echo "${NC}DOWN : ${RED}$DOWN_ON_NAS${NC}"
        fi
    fi
}


#########################################################
############# FONCTIONS SPECIFIQUES #####################
#########################################################

##################################
############### CLOUD ############
##################################

UpgradeClouds() {
    echo "${NC}--------------------------------------------------------" >& $QUIET
    echo "UPGRADE des cloud" >& $QUIET
    echo "--------------------------------------------------------" >& $QUIET
    RunOCCCommand "upgrade"
}

OptimiseClouds() {
    echo "${NC}--------------------------------------------------------" >& $QUIET
    echo "Optimisation des cloud" >& $QUIET
    echo "--------------------------------------------------------" >& $QUIET
    RunOCCCommand "db:add-missing-indices" "db:convert-filecache-bigint --no-interaction"
}

InstallApps(){
    echo "${NC}--------------------------------------------------------" >& $QUIET
    echo "INSTALL DES APPLIS sur les clouds : ${LISTE_APPS}" >& $QUIET
    echo "-------------------------------------------------------------" >& $QUIET
    if [ -z "${LISTE_APPS}" ]; then
        echo "Aucune appli n'est précisée, j'installe les applis par défaut : ${APPLIS_PAR_DEFAUT}" >& $QUIET
        LISTE_APPS="${APPLIS_PAR_DEFAUT}"
    fi
    PARAMS="-a \"$LISTE_APPS\""
    if [ ! "$QUIET" = "1" ]; then PARAMS="${PARAMS} -q" ; fi
    if [ -n "$SIMU" ]; then PARAMS="${PARAMS} -n" ; fi
    _executeFunctionForAll "${KAZ_BIN_DIR}/${subScripts["cloud"]} -i $PARAMS" "Install des applis" "cloud" "#ORGA#"
}

UpdateApplis() {
    echo "${NC}--------------------------------------------------------" >& $QUIET
    echo "UPDATE DES APPLIS des cloud : ${LISTE_APPS}" >& $QUIET
    echo "--------------------------------------------------------" >& $QUIET
    PARAMS="-a ${LISTE_APPS}"
    if [ -z "${LISTE_APPS}" ]; then
        echo "Aucune appli n'est précisée, je les met toutes à jour! " >& $QUIET
        PARAMS=
    fi
    if [ ! "$QUIET" = "1" ]; then PARAMS="${PARAMS} -q" ; fi
    if [ -n "$SIMU" ]; then PARAMS="${PARAMS} -n" ; fi
    _executeFunctionForAll "${KAZ_BIN_DIR}/${subScripts["cloud"]} -u $PARAMS" "Maj des applis" "cloud" "#ORGA#"
}


##################################
############### AGORA ############
##################################


PostMessages(){
    echo "${NC}--------------------------------------------------------" >& $QUIET
    echo "Envoi de messages sur mattermost" >& $QUIET
    echo "--------------------------------------------------------" >& $QUIET

    for TEAM in "${!Posts[@]}"
        do
            MSG=${Posts[$TEAM]/\"/\\\"}
            PARAMS="-p \"$TEAM\" \"$MSG\""
            if [ ! "$QUIET" = "1" ]; then PARAMS="${PARAMS} -q" ; fi
            if [ -n "$SIMU" ]; then PARAMS="${PARAMS} -n" ; fi
            _executeFunctionForAll "${KAZ_BIN_DIR}/${subScripts["agora"]} $PARAMS" "Post vers $TEAM sur l'agora" "agora" "#ORGA#"
    done
}


########## LANCEMENT COMMANDES OCC / MMCTL ############

RunCommands() {
    echo "${NC}--------------------------------------------------------" >& $QUIET
    echo "Envoi de commandes en direct" >& $QUIET
    echo "--------------------------------------------------------" >& $QUIET
    # $1 OCC / MMCTL / EXEC
    # $ suivants : les commandes
    for command in "${@:2}"
    do
        if [ $1 = "OCC" ]; then RunOCCCommand "$command" ; fi
        if [ $1 = "MMCTL" ]; then RunMMCTLCommand "$command" ; fi
        if [ $1 = "EXEC" ]; then RunEXECCommand "$command" ; fi
    done
}

_runSingleOccCommand(){
    # $1 Command
    # $2 Dockername
    ${SIMU} docker exec -u 33 $2 /var/www/html/occ $1
}

_runSingleMmctlCommand(){
    # $1 Command
    # $2 Dockername
    ${SIMU} docker exec $2 bin/mmctl $1
}

_runSingleExecCommand(){
    # $1 Command
    # $2 Dockername
    ${SIMU} docker exec $2 $1
}

RunOCCCommand() {
    # $1 Command
    _executeFunctionForAll "_runSingleOccCommand \"${1}\"" "OCC $1" "cloud" "#DOCKERSERVNAME#"
}

RunMMCTLCommand() {
    # $1 Command
    _executeFunctionForAll "_runSingleMmctlCommand \"${1}\"" "MMCTL $1" "agora" "#DOCKERSERVNAME#"
}

RunEXECCommand() {
    # $1 Command
    _executeFunctionForAll "_runSingleExecCommand \"${1}\"" "docker exec $1" "${CONTAINERS_TYPES[@]}" "#DOCKERSERVNAME#"
}



########## Main #################
for ARG in "$@"; do
    if [ -n "${GETOCCCOMAND}" ]; then # après un -occ
        OCCCOMANDS+=("${ARG}")
        GETOCCCOMAND=
    elif [ -n "${GETEXECCOMAND}" ]; then # après un -exec
        EXECCOMANDS+=("${ARG}")
        GETEXECCOMAND=
    elif [ -n  "${GETAPPS}" ]; then  # après un -a
        LISTE_APPS="${LISTE_APPS} ${ARG}"
        GETAPPS=""
    elif [ -n  "${GETMMCTLCOMAND}" ]; then # après un -mmctl
        MMCTLCOMANDS+=("${ARG}")
        GETMMCTLCOMAND=
    elif [ -n  "${GETTEAM}" ]; then # après un --post
        GETMESSAGE="now"
        GETTEAM=""
        TEAM="${ARG}"
    elif [ -n  "${GETMESSAGE}" ]; then # après un --post "team:channel"
        if [[ $TEAM == "-*" && ${#TEAM} -le 5 ]]; then echo "J'envoie mon message à \"${TEAM}\" ?? Arf, ça me plait pas j'ai l'impression que tu t'es planté sur la commande."; usage ; exit 1 ; fi
        if [[ $ARG == "-*" && ${#ARG} -le 5 ]]; then echo "J'envoie le message \"${ARG}\" ?? Arf, ça me plait pas j'ai l'impression que tu t'es planté sur la commande."; usage ; exit 1 ; fi
        if [[ ! $TEAM =~ .*:.+ ]]; then  echo "Il faut mettre un destinataire sous la forme team:channel. Recommence !"; usage ; exit 1 ; fi
        Posts+=( ["${TEAM}"]="$ARG" )
        GETMESSAGE=""
        TEAM=""
    else 
        case "${ARG}" in
            '-h' | '--help' )
            usage && exit ;;
            '-n' | '--simu')
            SIMU="echo" ;;
            '-q' )
            QUIET="/dev/null" ;;
            '-m' | '--main' )
            OPERATE_ON_MAIN="OUI-OUI" ;;
            '-M' )
            AVAILABLE_ORGAS= && OPERATE_ON_MAIN="OUI-OUI" ;; #pas d'orgas
            '--nas' | '-nas' )
            OPERATE_LOCAL_ORGA= ;;       # pas les locales
            '--local' | '-local' )
            OPERATE_ON_NAS_ORGA= ;;      # pas celles sur NAS
            '-cloud'|'--cloud')
            CONTAINERS_TYPES="${CONTAINERS_TYPES} cloud" ;; 
            '-agora'|'--agora'|'-mm'|'--mm'|'-matter'*|'--matter'*)
            CONTAINERS_TYPES="${CONTAINERS_TYPES} agora" ;;
            '-wiki'|'--wiki')
            CONTAINERS_TYPES="${CONTAINERS_TYPES} wiki" ;;
            '-wp'|'--wp')
            CONTAINERS_TYPES="${CONTAINERS_TYPES} wp" ;;
            '-office'|'--office'|'-collab'*|'--collab'*)
            CONTAINERS_TYPES="${CONTAINERS_TYPES} office" ;;
            '-paheko'|'--paheko')
            CONTAINERS_TYPES="${CONTAINERS_TYPES} paheko" ;;
            '-pod'|'--pod'|'-castopod'|'--castopod')
            CONTAINERS_TYPES="${CONTAINERS_TYPES} castopod" ;;
            '-spip')
            CONTAINERS_TYPES="${CONTAINERS_TYPES} spip" ;;
            '-t' )
            COMMANDS="${COMMANDS} RESTART-COMPOSE" ;;
            '-r' )
            COMMANDS="${COMMANDS} RESTART-DOCKER" ;;
            '-l' | '--list' )
            COMMANDS="$(echo "${COMMANDS} LIST" | sed "s/\s/\n/g" | sort | uniq)" ;; 
            '-v' | '--version')
            COMMANDS="$(echo "${COMMANDS} VERSION" | sed "s/\s/\n/g" | sort | uniq)" ;; 
            '-I' | '--install' )
            COMMANDS="$(echo "${COMMANDS} INIT" | sed "s/\s/\n/g" | sort | uniq)" ;; # le sed sort uniq, c'est pour pas l'avoir en double
            '-U' | '--upgrade')
            COMMANDS="$(echo "${COMMANDS} UPGRADE" | sed "s/\s/\n/g" | sort | uniq)" ;; 
            '--optim' )
            COMMANDS="$(echo "${COMMANDS} OPTIMISE-CLOUD" | sed "s/\s/\n/g" | sort | uniq)" ;;
            '-u' )
            COMMANDS="$(echo "${COMMANDS} UPDATE-CLOUD-APP" | sed "s/\s/\n/g" | sort | uniq)" ;;
            '-i' )
            COMMANDS="$(echo "${COMMANDS} INSTALL-CLOUD-APP" | sed "s/\s/\n/g" | sort | uniq)" ;;
            '-a' )
            GETAPPS="now" ;;
            '-occ' )
            COMMANDS="$(echo "${COMMANDS} RUN-CLOUD-OCC" | sed "s/\s/\n/g" | sort | uniq)"
            GETOCCCOMAND="now" ;;
            '-mmctl' )
            COMMANDS="$(echo "${COMMANDS} RUN-AGORA-MMCTL" | sed "s/\s/\n/g" | sort | uniq)"
            GETMMCTLCOMAND="now" ;;
            '-exec' )
            COMMANDS="$(echo "${COMMANDS} RUN-DOCKER-EXEC" | sed "s/\s/\n/g" | sort | uniq)"
            GETEXECCOMAND="now" ;;
            '-p' | '--post' )
            COMMANDS="$(echo "${COMMANDS} POST-AGORA" | sed "s/\s/\n/g" | sort | uniq)"
            GETTEAM="now" ;;
            '-*' ) # ignore
            ;; 
            *)
            GIVEN_ORGA="${GIVEN_ORGA} ${ARG%-orga}"
            ;;
        esac
    fi
done


if [[ "${COMMANDS[*]}" =~ "RESTART-COMPOSE" && "${COMMANDS[*]}" =~ "RESTART-TYPE" ]]; then
    echo "Je restarte via docker-compose ou via docker mais pas les deux !"
    usage
    exit 1
fi
if [ -z "${COMMANDS}" ]; then 
    usage && exit 
fi
if [ -n "${GIVEN_ORGA}" ]; then 
    # intersection des 2 listes : quelle commande de ouf !!
    AVAILABLE_ORGAS=$(comm -12 <(printf '%s\n' ${AVAILABLE_ORGAS} | sort) <(printf '%s\n' ${GIVEN_ORGA} | sort))
fi

NB_ORGAS=$(echo "${AVAILABLE_ORGAS}" | wc -w )

if [[ $NB_ORGAS = 0 && -z "${OPERATE_ON_MAIN}" ]]; then
    echo "Aucune orga trouvée."
    exit 1
fi

NB_ORGAS_STR="$NB_ORGAS orgas"
[ -n "${OPERATE_ON_MAIN}" ] && NB_ORGAS_STR="$NB_ORGAS_STR + les communs"

_populate_lists # on récupère les clouds / agora / wiki / wp correspondants aux orga

if [[  $NB_ORGAS -gt 2 && "${COMMANDS[*]}" =~ 'INIT' ]]; then
    ETLECLOUDCOMMUN=
    [ -n "${OPERATE_ON_MAIN}" ] && ETLECLOUDCOMMUN=" ainsi que les containers commun"
    echo "On s'apprête à initialiser les ${CONTAINERS_TYPES} suivants : ${AVAILABLE_ORGAS}${ETLECLOUDCOMMUN}"
    checkContinue
fi

for COMMAND in ${COMMANDS}; do
    case "${COMMAND}" in
        'LIST' )
        listContainers && exit ;;
        'VERSION' )
        version && exit ;;
        'OPTIMISE-CLOUD' )
         OptimiseClouds ;;
        'RESTART-COMPOSE' )
         restart-compose ;;
        'RESTART-DOCKER' )
         restart ;;
        'UPDATE-CLOUD-APP' )
         UpdateApplis ;;
        'UPGRADE' )
         UpgradeClouds ;;
        'INIT' )
         Init ;;
        'INSTALL-CLOUD-APP' )
         InstallApps ;;
        'RUN-CLOUD-OCC' )
         RunCommands "OCC" "${OCCCOMANDS[@]}" ;;
        'RUN-AGORA-MMCTL' )
         RunCommands "MMCTL" "${MMCTLCOMANDS[@]}" ;;
        'RUN-DOCKER-EXEC' )
         RunCommands "EXEC" "${EXECCOMANDS[@]}" ;;
        'POST-AGORA' )
         PostMessages ${Posts} ;;
    esac
done
