import React from 'react';
import PropTypes from 'prop-types';
import Graph from './Graph.js';
import {useAsync} from '../util.js';
import {Term, termTypes} from '../data/model.js';
import {symptomsSubgraph} from '../data/mock';

/**
 * Graphe de maladies et symptômes.
 *
 * @prop terms Termes à afficher.
 * @prop query Ensemble de termes recherchés par l’utilisateur.
 * @prop addQueryTerm Fonction de rappel pour ajouter un terme à la requête.
 * @prop removeQueryTerm Fonction de rappel pour ôter un terme de la requête.
 */
const DiseaseGraph = ({
    terms,
    query,
    addQueryTerm,
    removeQueryTerm,
}) =>
{
    const {nodes, edges} = useAsync({
        nodes: {},
        edges: [],
    }, symptomsSubgraph, terms);

    /**
     * Rendu d’un nœud du graphe.
     *
     * @param id Identifiant du nœud à afficher.
     */
    const render = id =>
    {
        const term = nodes[id];
        const isInQuery = query.some(({id: termId}) => termId === id);
        const isDisease = nodes[id].types.includes(termTypes.disease);

        return (
            <span
                className={[
                    'SearchResults_result',
                    isInQuery ? 'SearchResults_result-inQuery' : '',
                    isDisease ? 'SearchResults_result-disease' : '',
                ].join(' ')}
                title={
                    `Cliquez pour plus d’informations sur « ${term.name} »\n`
                    + `(Ctrl-clic pour ${
                        isInQuery
                            ? 'l’enlever de'
                            : 'l’ajouter à'
                    } la requête)`
                }
            >
                {nodes[id].name}
            </span>
        );
    };

    /**
     * Gère le clic sur un nœud du graphe.
     *
     * @param id Identifiant du nœud cliqué.
     * @param ev Événement DOM décrivant le clic.
     */
    const handleNodeClick = (id, ev) =>
    {
        const term = nodes[id];
        const queryIndex = query.findIndex(({id: termId}) => termId === id);

        if (!ev.ctrlKey)
        {
            // Clic normal : Ouverture de la ressource
            window.open(term.url, '_blank');
        }
        else if (queryIndex >= 0)
        {
            // Ctrl-clic : Retrait d’un terme déjà dans la requête
            removeQueryTerm(queryIndex);
        }
        else
        {
            // Ctrl-clic : Ajout d’un nouveau terme dans la requête
            addQueryTerm(term);
        }
    };

    return (
        <Graph
            nodes={Object.keys(nodes)}
            edges={edges}
            emptyMessage="Aucune maladie ne corresond à ces symptômes"
            render={render}
            onNodeClick={handleNodeClick}
        />
    );
};

DiseaseGraph.propTypes = {
    terms: PropTypes.arrayOf(Term).isRequired,
    query: PropTypes.arrayOf(Term).isRequired,
    addQueryTerm: PropTypes.func.isRequired,
    removeQueryTerm: PropTypes.func.isRequired,
};

export default DiseaseGraph;
