import React, {useState, useRef, useEffect, useMemo} from 'react';
import {Button, Stack} from "react-bootstrap";
import 'bootstrap/dist/css/bootstrap.min.css';
import './App.css';
import * as d3 from 'd3'

function App() {
    const [enregistre, setEnregistre] = useState(false);
    const [text, setText] = useState("Les données ne sont pas enregistrées");
    const svgRef = useRef(null);
    const [donnees, setDonnees] = useState([]);
    const donneesRef = useRef(donnees);
    const [input, setInput] = useState('');
    const [emergencyNumber, setEmergencyNumber] = useState('');
    donneesRef.current = donnees;

    let ws = useMemo(() => {
        if (enregistre)
            return new WebSocket('ws://127.0.0.1:8080')
    }, [enregistre]);

    // Équivalent à componentDidMount plus componentDidUpdate :
    useEffect(() => {
        if (enregistre) {
            resizeLinearChart();
            setText("Enregistrement en cours")
            ws.onmessage = (event) => {
                const nouvelleDate = JSON.parse(event.data);
                console.log(nouvelleDate)
                var object = {date: new Date(JSON.parse(event.data).date), valeur: 1};
                donnees.push(object);
                setDonnees([...donnees]);

                //  }
            }
        } else {
            setText("Les données ne sont pas enregistrées")
        }

    }, [donnees, svgRef, enregistre]);

    const resizeLinearChart = () => {
        const hauteurRestante = document.documentElement.clientHeight - document.getElementById("selection").clientHeight - 20;
        const largeurRestante = document.getElementById("selection").clientWidth;
        let lineChart = LineChart(donnees, {
            x: d => d.date,
            y: d => d.valeur,
            yLabel: "↑ Daily valeur ($)",
            width: largeurRestante,
            height: hauteurRestante,
            color: "steelblue"
        })
        d3.select("svg").selectAll("*").remove();
        const svg = d3.select(svgRef.current)
            .attr("width", largeurRestante)
            .attr("height", hauteurRestante);

        svg.append(() => lineChart);

        const timer = setTimeout(() => {
            var object = {date: new Date(), valeur: 0};
            donneesRef.current.push(object);
            setDonnees([...donneesRef.current]);
        }, 1000);
        window.addEventListener('resize', resizeLinearChart);

    }


    const handleClick = () => {
        if (!enregistre)
            setEnregistre(true);
        else {
            setEnregistre(false);
            ws.close();
        }
    }

    const handleAdd = () => {

        ws.send(JSON.stringify({
            message: "emergency",
            data: input
        }))
        setEmergencyNumber(input);
        setInput('');

    }

    return (
        <>
            <head>
                <title>controlleur capteur</title>
                <script src="https://unpkg.com/react/umd/react.production.min.js" crossOrigin/>
                <script type="text/javascript" src="./d3.js" charSet="utf-8"></script>
                <script type="text/javascript" src="./d3-line-chart.js" charSet="utf-8"></script>

            </head>
            <div id="selection">
                <h1>Lancer l'enregistrement des données des capteurs</h1>
                <Stack gap={2} className="col-md-8 mx-auto mt-5">

                    <div className="row justify-content-around">
                        <div className="col-4">
                            <p>{text}</p>
                            <div className="text-center">
                                <button type="button" className="btn btn-outline-primary text-center"
                                        onClick={handleClick}>enregistrement
                                </button>

                            </div>
                        </div>
                        <div className="col-6">
                            <div className="input-group mb-3">
                                <div className="input-group-prepend">
                                    <button className="btn btn-outline-info" type="button" onClick={handleAdd}>Add
                                        emergency Number
                                    </button>
                                </div>

                                <input type="number" className="form-control" maxLength="10"
                                       placeholder="enter your number"
                                       onChange={(event) => {
                                           setInput(event.target.value)
                                       }}/>
                            </div>
                            <p className="text-muted"> Emergency Number
                                : {emergencyNumber}</p>
                        </div>
                    </div>


                </Stack>
            </div>
            <div id="affichage">
                {<svg ref={svgRef}/>}
            </div>
        </>
    );
}

// Copyright 2021 Observable, Inc.
// Released under the ISC license.
// https://observablehq.com/@d3/line-chart
function LineChart(data, {
    x = ([x]) => x, // given d in data, returns the (temporal) x-value
    y = ([, y]) => y, // given d in data, returns the (quantitative) y-value
    defined, // for gaps in data
    curve = d3.curveLinear, // method of interpolation between points
    marginTop = 20, // top margin, in pixels
    marginRight = 30, // right margin, in pixels
    marginBottom = 30, // bottom margin, in pixels
    marginLeft = 40, // left margin, in pixels
    width = 640, // outer width, in pixels
    height = 400, // outer height, in pixels
    xType = d3.scaleUtc, // the x-scale type
    xDomain, // [xmin, xmax]
    xRange = [marginLeft, width - marginRight], // [left, right]
    yType = d3.scaleLinear, // the y-scale type
    yDomain, // [ymin, ymax]
    yRange = [height - marginBottom, marginTop], // [bottom, top]
    yFormat, // a format specifier string for the y-axis
    yLabel, // a label for the y-axis
    color = "currentColor", // stroke color of line
    strokeLinecap = "round", // stroke line cap of the line
    strokeLinejoin = "round", // stroke line join of the line
    strokeWidth = 1.5, // stroke width of line, in pixels
    strokeOpacity = 1, // stroke opacity of line
} = {}) {
    // Compute values.
    const X = d3.map(data, x);
    const Y = d3.map(data, y);
    const I = d3.range(X.length);
    if (defined === undefined) defined = (d, i) => !isNaN(X[i]) && !isNaN(Y[i]);
    const D = d3.map(data, defined);

    // Compute default domains.
    if (xDomain === undefined) xDomain = d3.extent(X);
    if (yDomain === undefined) yDomain = [0, d3.max(Y)];

    // Construct scales and axes.
    const xScale = xType(xDomain, xRange);
    const yScale = yType(yDomain, yRange);
    const xAxis = d3.axisBottom(xScale).ticks(width / 80).tickSizeOuter(0);
    const yAxis = d3.axisLeft(yScale).ticks(height / 40, yFormat);

    // Construct a line generator.
    const line = d3.line()
        .defined(i => D[i])
        .curve(curve)
        .x(i => xScale(X[i]))
        .y(i => yScale(Y[i]));

    const svg = d3.create("svg")
        .attr("width", width)
        .attr("height", height)
        .attr("viewBox", [0, 0, width, height])
        .attr("style", "max-width: 100%; height: auto; height: intrinsic;");

    svg.append("g")
        .attr("transform", `translate(0,${height - marginBottom})`)
        .call(xAxis);

    svg.append("g")
        .attr("transform", `translate(${marginLeft},0)`)
        .call(yAxis)
        .call(g => g.select(".domain").remove())
        .call(g => g.selectAll(".tick line").clone()
            .attr("x2", width - marginLeft - marginRight)
            .attr("stroke-opacity", 0.1))
        .call(g => g.append("text")
            .attr("x", -marginLeft)
            .attr("y", 10)
            .attr("fill", "currentColor")
            .attr("text-anchor", "start")
            .text(yLabel));

    svg.append("path")
        .attr("fill", "none")
        .attr("stroke", color)
        .attr("stroke-width", strokeWidth)
        .attr("stroke-linecap", strokeLinecap)
        .attr("stroke-linejoin", strokeLinejoin)
        .attr("stroke-opacity", strokeOpacity)
        .attr("d", line(I));
    return svg.node();
}

export default App;