/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

import { createRoot, createSignal, createState, createEffect } from 'solid-js';

function createLocalState(initState) {
  const [state, setState] = createState(initState);
  if (localStorage.odoodockerssh) { setState(JSON.parse(localStorage.odoodockerssh)); }
  createEffect(() => localStorage.odoodockerssh = JSON.stringify(state));
  return [state, setState];
}

const initialState = {
  address: '', port: '', username: '', key: '', database: '',
  databases: [], modules: '', serverlog: '', connected: false, stop: false
};
const [isConnected, setIsConnected] = createSignal(false);

const OdooDockerSshAdminConfig = () => {
  const [state, setState] = createLocalState(initialState);
  const [passphrase, setPassphrase] = createSignal('');
  const valueSet = ({target}) => setState(target.name, target.value);

  let cantConnect = !(state.address && state.username && state.key && state.port);

  const connect = () => {
    fetch('/connect',
      {method: 'POST',
        body: JSON.stringify({
          address: state.address,
          port: state.port,
          username: state.username,
          key: state.key,
          password: passphrase()
        }),
        headers:{ 'Content-Type': 'application/json'}})
      .then(response => {
        setIsConnected(response.status == 200);
        return response.json();
      })
      .then(body => humane.log(body))
  };
  const disconnect = () => {
    fetch ('/disconnect')
      .then(response => {
        setIsConnected(!(response.status == 200));
        return response.json();
      })
      .then(body => humane.log(body))
  };

  return <div>
    <h2>🛠 Configuration
      <span style="margin-left: 0.5em;">
      <$ when={(isConnected())}>🔵</$>
      <$ when={(!isConnected())}>🔴</$>
    </span>
    </h2>
    <form name="configuration-form">
      <div class="row">
        <div class="col-4">
          <label for="address">Hôte / Adressse IP</label>
          <input name="address" type="text" required
            value={(state.address)} onChange={valueSet} />
          <label for="port">Port</label>
          <input name="port" type="text" pattern="\d+" placeholder="Exemple : 22"
            value={(state.port)} onChange={valueSet}/>
        </div>
        <div class="col-4">
          <label for="username">Identifiant</label>
          <input name="username" type="text" required
            value={(state.username)} onChange={valueSet}/>
        </div>
        <div class="col-4">
          <label for="key">Clé privée</label>
          <textarea name="key" placeholder="Please paste your private key"
            value={(state.key)} onChange={valueSet}/>
          <label for="password">Mot de passe clé</label>
          <input name="password" type="password" required value={(passphrase())}
            onInput={({target}) => setPassphrase(target.value)} />
        </div>
      </div>
      <button type="button" class="button outline primary" onClick={connect}>🔗 Connecter</button>
      <button type="button" class="button outline secondary" onClick={disconnect}>🔴 Déconnecter</button>
    </form>
  </div>
};

const OdooDockerSshAdminDatabases = () => {
  const [state, setState] = createLocalState(initialState);
  const valueSet = ({target}) => setState(target.name, target.value);

  const add = (e) => {
    e.preventDefault();
    if (state.database) {
      let database = {name: state.database, checked: false};
      setState(['databases', [...state.databases, database]], ['database', '']);
    }
  };
  const inverseCheck = () => {
    let databases = state.databases.map((db) => Object.assign({}, db));
    setState('databases', databases.map((db) => Object.assign(db, {checked: !db.checked})));
  };
  const allCheck = () => {
    let databases = state.databases.map((db) => Object.assign({}, db));
    setState('databases', databases.map((db) => Object.assign(db, {checked: true})));
  };
  const noCheck = () => {
    let databases = state.databases.map((db) => Object.assign({}, db));
    setState('databases', databases.map((db) => Object.assign(db, {checked: false})));
  };
  const toggle = ({target: {checked}}, name) => {
    setState('databases', db => db.name === name, {name: name, checked: checked});
  };
  const remove = (name) => {
    setState('databases', state.databases.filter(db => db.name  !== name));
  };

  return <div>
    <h2>📙 Bases de données</h2>
    <p>Merci de renseigner toutes les bases de votre domaine ici. Pour effectuer une installation ou mise à jour de module, sélectionnez les bases sur lesquelles agir.</p>
    <div class="row">
      <div class="col-12" >
      <button type="button" class="button outline" onClick={inverseCheck}>☑ Inverser la sélection</button>
      <button type="button" class="button dark" onClick={allCheck}>☑ Sélectionner tout</button>
      <button type="button" class="button dark" onClick={noCheck}>◻ Sélectionner aucun</button>
        <ul class="database-list">
          <$ each={ state.databases }>{ (database, index) =>
            <li>
              <input type="checkbox" checked={(database.checked)}
                onClick={(e) => toggle(e, database.name)} />
              <span>{(database.name)}</span>
              <button type="button" class="button outline"
                onClick={() => remove(database.name)}>X</button>
            </li>
          }
          </$>
        </ul>
      </div>
    </div>
    <div class="row">
      <div class="col-12" >
        <form name="database-form">
          <div class="row">
            <div class="col-8" >
              <input type="text" name="database" placeholder="Nom de la base de données"
                value={(state.database)} onInput={valueSet}/>
            </div>
            <div class="col-4" >
              <button type="submit" class="button outline primary"
                disabled={(!state.database)} onClick={add}>
                ➕ Ajouter
              </button>
            </div>
          </div>
        </form>
      </div>
    </div>
  </div>
};

const OdooDockerSshAdminActions = () => {
  const [state, setState] = createLocalState(initialState);

  const cmdFetch = (cmd) => {
    return () => {
      if (!isConnected()) {
        humane.log('Non connecté : impossible de lancer une commande.');
      } else {
        humane.log('Commande lancée, veuillez patienter.');
        fetch('/cmd/' + cmd)
          .then(response => response.json())
          .then(body => {
            humane.log('Commande terminée.');
            setState('serverlog', state.serverlog + body);
          })
      }
    };
  };

  const webStart = cmdFetch('webstart');
  const webStop = cmdFetch('webstop');
  const webRestart = cmdFetch('webrestart');
  const odooStart = cmdFetch('odoostart');
  const stop = cmdFetch('odoostop');
  const odooRestart = cmdFetch('odoorestart');
  const dbStart = cmdFetch('dbstart');
  const dbStop = cmdFetch('dbstop');
  const dbRestart = cmdFetch('dbrestart');

  return <div>
    <h2>🚩 Actions</h2>
    <div class="row">
      <div class="col">
        <button type="button" class="button clear" onClick={odooStart}>
          ⏩ Odoo : démarrer
        </button>
      </div>
      <div class="col">
        <button type="button" class="button clear" onClick={stop}>
          ⏹  Odoo : arrêter
        </button>
      </div>
      <div class="col">
        <button type="button" class="button clear" onClick={odooRestart}>
          🔄 Odoo : redémarrer
        </button>
      </div>
    </div>
    <div class="row">
      <div class="col">
        <button type="button" class="button clear" onClick={webStart}>
          ⏩ Frontal : démarrer
        </button>
      </div>
      <div class="col">
        <button type="button" class="button clear" onClick={webStop}>
          ⏹  Frontal : arrêter
        </button>
      </div>
      <div class="col">
        <button type="button" class="button clear" onClick={webRestart}>
          🔄 Frontal : redémarrer
        </button>
      </div>
    </div>
    <div class="row">
      <div class="col">
        <button type="button" class="button clear" onClick={dbStart}>
          ⏩ Moteur de base de données : démarrer
        </button>
      </div>
      <div class="col">
        <button type="button" class="button clear" onClick={dbStop}>
          ⏹  Moteur de base de données : arrêter
        </button>
      </div>
      <div class="col">
        <button type="button" class="button clear" onClick={dbRestart}>
          🔄 Moteur de base de données : redémarrer
        </button>
      </div>
    </div>
  </div>
};

const OdooDockerSshAdminModules = () => {
  const [state, setState] = createLocalState(initialState);
  const valueSet = ({target}) => setState(target.name, target.value);

  const checkedDatabases = (databases) => {
    let names = databases.filter((db) => db.checked).map((db) => db.name);
    return names.length ? names.join(', ') : 'Aucune base sélectionnée';
  };

  const odooCmd = (action) => {
    return () => {
      if (!isConnected()) {
        humane.log('Non connecté : impossible de lancer une commande Odoo.');
      } else {
        humane.log('Commande lancée, veuillez patienter.');
        fetch('/odooaction', {
          method: 'POST',
          body: JSON.stringify({
            stop: state.stop,
            databases: state.databases.filter((db) => db.checked).map((db) => db.name),
            modules: state.modules,
            action: action
          }),
          headers: {'Content-Type': 'application/json'}
        })
          .then(response => {
            if (response.status != 200) { humane.log('Erreur : voyez le retour serveur'); }
            return response.json();
          })
          .then(body => {
            humane.log('Commande terminée.');
            setState('serverlog', state.serverlog + body);
          })
      }
    };
  };

  return <div>
    <h2>🗄  Modules</h2>
    <form name="modules-form">
      <p>Bases sélectionnées : {checkedDatabases(state.databases)}</p>
      <div class="row">
        <div class="col-6">
          <label for="modules">Liste de modules, séparés par des virgules</label>
          <input name="modules" type="text" required placeholder="account,crm"
            value={(state.modules)} onInput={valueSet}/>
        </div>
        <div class="col-6">
          <label for="stop">❗ Arrêt serveur préalable ?</label>
          <input type="checkbox" name="stop" checked={(state.stop)}
            onChange={(e) => setState('stop', e.target.checked)} />
        </div>
      </div>
      <button type="button" class="button primary outline" onClick={odooCmd('install')}>
        Installer
      </button>
      <button type="button" class="button primary" onClick={odooCmd('update')}>
        Mettre à jour
      </button>
    </form>
  </div>
};

const OdooDockerSshAdminServerLog = () => {
  const [state, setState] = createLocalState(initialState);
  const serverlogClean = () => setState('serverlog', '');

  return <div>
    <h2>🖥  Retour serveur</h2>
    <div class="row">
      <div class="col-11">
        <textarea name="serverlog" class="serverlog" rows="20" readonly>{(state.serverlog)}</textarea>
      </div>
      <div class="col-1">
        <button type="button" onClick={serverlogClean}>💢 Nettoyer</button>
      </div>
    </div>
  </div>
};

const OdooDockerSshAdmin = () => {
  const [visibleTab, setVisibleTab] = createSignal('configuration');
  const getClassName = (name) => visibleTab() === name ? 'active' : '';

  return <>
    <h1>Odoo Docker SSH Admin</h1>
    <nav class="tabs is-full">
      <a onClick={() => setVisibleTab('configuration')} className={(getClassName('configuration'))}>
        🛠 Configuration
      </a>
      <a onClick={() => setVisibleTab('actions')} className={(getClassName('actions'))}>
        🚩 Actions
      </a>
      <a onClick={() => setVisibleTab('databases')} className={(getClassName('databases'))}>
        📙 Bases de données
      </a>
      <a onClick={() => setVisibleTab('modules')} className={(getClassName('modules'))}>
        🗄  Modules
      </a>
      <a onClick={() => setVisibleTab('serverlog')} className={(getClassName('serverlog'))}>
        🖥  Retour serveur
      </a>
    </nav>
    <$ when={(visibleTab() === 'configuration')}><OdooDockerSshAdminConfig /></$>
    <$ when={(visibleTab() === 'databases')}><OdooDockerSshAdminDatabases /></$>
    <$ when={(visibleTab() === 'modules')}><OdooDockerSshAdminModules /></$>
    <$ when={(visibleTab() === 'actions')}><OdooDockerSshAdminActions /></$>
    <$ when={(visibleTab() === 'serverlog')}><OdooDockerSshAdminServerLog /></$>
  </>
}
createRoot(() => document.body.appendChild(<OdooDockerSshAdmin />));
