import {useEffect, useReducer, useRef, useState} from "react";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faAdd, faPen, faTrashCan} from "@fortawesome/free-solid-svg-icons";
import proj4 from "proj4";
import {useFetch} from "../../hooks/useFetch.js";
import {MapContainer, Marker, TileLayer} from "react-leaflet";
import {SimpleReducer} from "../../utils/SimpleReducer.jsx";
import {useTranslation} from "react-i18next";

export function LocationEditor({data, setModal, sendData}) {
    const [state, dispatch] = useReducer(SimpleReducer, [])
    const [out_data, setOutData] = useState({})
    const {t} = useTranslation();

    useEffect(() => {
        if (data.training_location === null)
            return
        JSON.parse(data.training_location).forEach((d, index) => {
            dispatch({type: 'UPDATE_OR_ADD', payload: {id: index, data: d}})
        })
    }, [data.training_location]);

    sendData.current = (e) => {
        e.preventDefault();

        const formData = new FormData(e.target);
        dispatch({
            type: 'UPDATE_OR_ADD', payload: {
                id: Number(formData.get('id')),
                data: {
                    text: formData.get('loc_text'),
                    lat: Number(formData.get('loc_lat')),
                    lng: Number(formData.get('loc_lng'))
                }
            }
        })
    }

    useEffect(() => {
        setOutData(state.map(d => {
            return {text: d.data.text, lat: d.data.lat, lng: d.data.lng}
        }))
    }, [state]);

    return <div className="row mb-3">
        <input name="training_location" value={JSON.stringify(out_data)} readOnly hidden/>
        <span className="input-group-text">{t('lieuxDentraînements')}</span>
        <ul className="list-group form-control">
            {state.map((d, index) => {
                return <div key={index} className="input-group">
                    <input type="text" className="form-control" value={d.data.text} required
                           onChange={(e) => {
                           }}/>

                    <button className="btn btn-primary" data-bs-toggle="modal"
                            data-bs-target="#EditModal" onClick={e => {
                        e.preventDefault();
                        setModal(d);
                    }}>
                        <FontAwesomeIcon icon={faPen}/></button>
                    <button className="btn btn-danger"
                            onClick={() => dispatch({type: 'REMOVE', payload: d.id})}>
                        <FontAwesomeIcon icon={faTrashCan}/></button>
                </div>
            })}
            <div className="d-grid gap-2 d-md-flex justify-content-md-end">
                <button className="btn btn-success" data-bs-toggle="modal"
                        disabled={state.length >= 10}
                        data-bs-target="#EditModal" onClick={e => {
                    e.preventDefault();

                    let maxId = 0;
                    state.forEach((d) => {
                        if (d.id > maxId)
                            maxId = d.id;
                    })
                    setModal({id: maxId + 1, data: {text: "", lat: undefined, lng: undefined}});
                }}><FontAwesomeIcon icon={faAdd}/></button>
            </div>
        </ul>
    </div>
}

export function LocationEditorModal({modal, sendData}) {
    const [location, setLocation] = useState("")
    const [locationObj, setLocationObj] = useState({text: "", lng: undefined, lat: undefined})
    const [mapPosition, setMapPosition] = useState([46.652195, 2.430226])
    const {data, refresh} = useFetch(null)
    const map = useRef(null)
    const {t} = useTranslation();

    useEffect(() => {
        if (modal.data !== undefined) {
            setLocation(modal.data.text)
            setLocationObj(modal.data)
        }
    }, [modal])

    useEffect(() => {
        if (location.length < 3)
            return

        const delayDebounceFn = setTimeout(() => {
            refresh(`https://api-adresse.data.gouv.fr/search/?q=${encodeURI(location)}&type=housenumber&autocomplete=1&limit=5`)
        }, 500)
        return () => clearTimeout(delayDebounceFn)
    }, [location]);

    useEffect(() => {
        if (data?.features?.some((e) => e.properties.label === location)) {
            data.features.forEach((d) => {
                if (d.properties.label === location) {
                    const {lat, lng} = convertLambert93ToLatLng(d.properties.x, d.properties.y)
                    setLocationObj({text: d.properties.label, lng: lng, lat: lat})
                }
            })
        } else {
            setLocationObj({text: "", lng: undefined, lat: undefined})
        }
    }, [data]);

    useEffect(() => {
        if (locationObj.lat !== undefined) {
            setMapPosition([locationObj.lat, locationObj.lng])
            map.current?.setView([locationObj.lat, locationObj.lng], 19)
        } else {
            map.current?.setView([46.652195, 2.430226], 5)
        }

        const delayDebounceFn = setTimeout(() => {
            map.current.invalidateSize(false);
        }, 300)
        return () => clearTimeout(delayDebounceFn)
    }, [locationObj, modal])

    return <div className="modal fade" id="EditModal" tabIndex="-1" aria-labelledby="EditModalLabel"
                aria-hidden="true">
        <div className="modal-dialog">
            <form onSubmit={e => sendData.current(e)}>
                <div className="modal-content">
                    <div className="modal-header">
                        <h1 className="modal-title fs-5" id="EditModalLabel">{t('editionDeLadresse')}</h1>
                        <button type="button" className="btn-close" data-bs-dismiss="modal"
                                aria-label="Close"></button>
                    </div>
                    <div className="modal-body">
                        <input name="id" value={modal.id} readOnly hidden/>
                        <input name="loc_text" value={locationObj.text} readOnly hidden/>
                        <input name="loc_lat" value={locationObj.lat ? locationObj.lat : -142} readOnly hidden/>
                        <input name="loc_lng" value={locationObj.lng ? locationObj.lng : -142} readOnly hidden/>
                        <div className="row">
                            <div className="input-group mb-3">
                                <label className="input-group-text">{t('adresse')}</label>
                                <input className="form-control" aria-autocomplete="list" aria-expanded="true"
                                       placeholder="Chercher une adresse..." aria-label="Recherche" list="addr" value={location}
                                       onChange={e => setLocation(e.target.value)}/>
                            </div>
                            <div className="input-group mb-3">
                                <ul className="list-group">
                                    {data?.features && !data.features.some((e) => e.properties.label === location) && data.features.map((d, index) => {
                                        return <li key={index} className="list-group-item"
                                                   onClick={() => setLocation(d.properties.label)}>{d.properties.label}</li>
                                    })}
                                </ul>
                            </div>
                        </div>

                        <div className="row">
                            <MapContainer ref={map} center={mapPosition} zoom={13} scrollWheelZoom={true} style={{height: "30em"}}>
                                <TileLayer
                                    attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
                                    url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                                />
                                {locationObj.lat !== undefined && <Marker position={mapPosition}/>}
                            </MapContainer>
                        </div>
                    </div>
                    <div className="modal-footer">
                        <button type="submit" className="btn btn-primary" data-bs-dismiss="modal"
                                disabled={locationObj.lng === undefined}>{t('button.enregistrer')}
                        </button>
                        <button type="reset" className="btn btn-secondary" data-bs-dismiss="modal">{t('button.annuler')}</button>
                    </div>
                </div>
            </form>
        </div>
    </div>
}

proj4.defs("EPSG:9794", "+proj=lcc +lat_1=44 +lat_2=49 +lat_0=46.5 +lon_0=3 +x_0=700000 +y_0=6600000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs");

function convertLambert93ToLatLng(x, y) {
    const lambertPoint = proj4.toPoint([x, y]);
    const wgs84Point = proj4("EPSG:9794", "EPSG:4326", lambertPoint);
    return {lat: wgs84Point.y, lng: wgs84Point.x};
}
