text: import axios from "axios";
  import React from "react";
  import WaveSurfer from "wavesurfer.js";
  import RegionsPlugin from "wavesurfer.js/dist/plugin/wavesurfer.regions.min.js";
  import TimelinePlugin from "wavesurfer.js/dist/plugin/wavesurfer.timeline.min.js";
  import { Helmet } from "react-helmet";
  import { withRouter } from "react-router-dom";
  
  import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
  import {
    faSearchMinus,
    faSearchPlus,
    faBackward,
    faForward,
    faPlayCircle,
    faArrowRight,
    faArrowLeft,
    faPauseCircle,
  } from "@fortawesome/free-solid-svg-icons";
  import Alert from "../components/alert";
  import { IconButton, Button } from "../components/button";
  import Loader from "../components/loader";
  
  class Annotate extends React.Component {
    constructor(props) {
      super(props);
  
      const projectId = Number(this.props.match.params.projectid);
      const dataId = Number(this.props.match.params.dataid);
  
      this.state = {
        isPlaying: false,
        projectId,
        dataId,
        afterId: -1,
        beforeId: -1,
        labels: {},
        labelsUrl: `/api/projects/${projectId}/labels`,
        dataUrl: `/api/projects/${projectId}/data/${dataId}`,
        neighboursUrl: `/api/projects/${projectId}/neighbours/${dataId}`,
        annotationUrl: `projects/${projectId}/data/${dataId}/annotate`,
        segmentationUrl: `/api/projects/${projectId}/data/${dataId}/segmentations`,
        isDataLoading: false,
        wavesurfer: null,
        zoom: 0,
        referenceTranscription: null,
        isMarkedForReview: false,
        selectedSegment: null,
        isSegmentDeleting: false,
        errorMessage: null,
        successMessage: null,
      };
  
      this.labelRef = {};
      this.transcription = null;
    }
  
    componentDidMount() {
      const { labelsUrl, dataUrl,neighboursUrl } = this.state;
      this.setState({ isDataLoading: true });
      const wavesurfer = WaveSurfer.create({
        container: "#waveform",
        barWidth: 2,
        barHeight: 1,
        barGap: null,
        mediaControls: false,
        plugins: [
          RegionsPlugin.create(),
          TimelinePlugin.create({ container: "#timeline" }),
        ],
      });
      this.showSegmentTranscription(null);
      this.props.history.listen((location, action) => {
        wavesurfer.stop();
      });
      wavesurfer.on("ready", () => {
        wavesurfer.enableDragSelection({ color: "rgba(0, 102, 255, 0.3)" });  
        if(!wavesurfer.loaded) {
          wavesurfer.loaded = true;
          wavesurfer.play();
          this.setState({
            isPlaying: true});
      }  
      });
      wavesurfer.on("region-in", (region) => {
        this.showSegmentTranscription(region);
      });
      wavesurfer.on("region-out", () => {
        this.showSegmentTranscription(null);
      });
      wavesurfer.on("region-play", (r) => {
        r.once("out", () => {
          wavesurfer.play(r.start);
          wavesurfer.pause();
        });
      });
  
      wavesurfer.on("region-click", (r, e) => {
        e.stopPropagation();
        this.setState({
          isPlaying: true,
          selectedSegment: r,
        });
        r.play();
      });
      wavesurfer.on("pause", (r, e) => {
        this.setState({ isPlaying: false });
      });
  
      axios
        .all([axios.get(labelsUrl), axios.get(dataUrl),axios.get(neighboursUrl)])
        .then((response) => {
          this.setState({
            isDataLoading: false,
            labels: response[0].data,
            afterId: response[2].data.after_id,
            beforeId: response[2].data.before_id,
          });
  
          const {
            reference_transcription,
            is_marked_for_review,
            segmentations,
            filename,
          } = response[1].data;
          //console.log("This was the reponse from the thing: ", response[1].data)
          const regions = segmentations.map((segmentation) => {
            return {
              start: segmentation.start_time,
              end: segmentation.end_time,
              data: {
                segmentation_id: segmentation.segmentation_id,
                transcription: segmentation.transcription,
                annotations: segmentation.annotations,
              },
            };
          });
  
          this.setState({
            isDataLoading: false,
            referenceTranscription: reference_transcription,
            isMarkedForReview: is_marked_for_review,
            filename,
          });
  
          wavesurfer.load(`/audios/${filename}`);
          wavesurfer.drawBuffer();
          const { zoom } = this.state;
          wavesurfer.zoom(zoom);
  
          this.setState({ wavesurfer });
          this.loadRegions(regions);
        })
        .catch((error) => {
          console.log(error);
          this.setState({
            isDataLoading: false,
          });
        });
    }
  
    loadRegions(regions) {
      const { wavesurfer } = this.state;
      //console.log(regions);
      if (regions.length>0){
        regions.forEach((region) => {
          wavesurfer.addRegion(region);
          
        });
  
        this.setState({ selectedSegment : regions[0]});
  
      }
      else{
        wavesurfer.addRegion({
            start: 0.01,
            end: 120.99,
            data: {
              segmentation_id: null,
              transcription: null,
              annotations: null,
            }
        });
        this.setState({
          isPlaying: true,
          selectedSegment: {
            start: 0.01,
            end: 120.99,
            data: {
              segmentation_id: null,
              transcription: null,
              annotations: null,
            }
        },
        });
      }
      }
  
    showSegmentTranscription(region) {
      this.segmentTranscription.textContent =
        (region && region.data.transcription) || "–";
    }
  
    handlePlay() {
      const { wavesurfer } = this.state;
      this.setState({ isPlaying: true });
      wavesurfer.play();
    }
  
    handlePause() {
      const { wavesurfer } = this.state;
      this.setState({ isPlaying: false });
      wavesurfer.pause();
    }
  
    handleForward() {
      const { wavesurfer } = this.state;
      wavesurfer.skipForward(5);
    }
  
    handleBackward() {
      const { wavesurfer } = this.state;
      wavesurfer.skipBackward(5);
    }
    handleNextAnnotation() {
      const { history } = this.props;
      const { projectId, afterId } = this.state;
      const path = `/projects/${projectId}/data/${afterId}/annotate`;
      history.replace({ pathname: "/empty" });
      setTimeout(() => {
        history.replace({ pathname: path });
      });
    }
  
    handlePreviousAnnotation() {
      const { history } = this.props;
      const { projectId, beforeId } = this.state;
      const path = `/projects/${projectId}/data/${beforeId}/annotate`;
      history.replace({ pathname: "/empty" });
      setTimeout(() => {
        history.replace({ pathname: path });
      });
    }
  
  
    handleZoom(e) {
      const { wavesurfer } = this.state;
      const zoom = Number(e.target.value);
      wavesurfer.zoom(zoom);
      this.setState({ zoom });
    }
  
    handleIsMarkedForReview(e) {
      const { dataUrl } = this.state;
      const isMarkedForReview = e.target.checked;
      this.setState({ isDataLoading: true });
  
      axios({
        method: "patch",
        url: dataUrl,
        data: {
          is_marked_for_review: isMarkedForReview,
        },
      })
        .then((response) => {
          this.setState({
            isDataLoading: false,
            isMarkedForReview: response.data.is_marked_for_review,
            errorMessage: null,
            successMessage: "Marked for review status changed",
          });
        })
        .catch((error) => {
          console.log(error);
          this.setState({
            isDataLoading: false,
            errorMessage: "Error changing review status",
            successMessage: null,
          });
        });
    }
  
    handleSegmentDelete() {
      const { wavesurfer, selectedSegment, segmentationUrl } = this.state;
      this.setState({ isSegmentDeleting: true });
      if (selectedSegment.data.segmentation_id) {
        axios({
          method: "delete",
          url: `${segmentationUrl}/${selectedSegment.data.segmentation_id}`,
        })
          .then((response) => {
            //console.log(selectedSegment.id);
            wavesurfer.regions.list[selectedSegment.id].remove();
            this.setState({
              selectedSegment: null,
              isSegmentDeleting: false,
            })
          })
          .catch((error) => {
            console.log(error);
            this.setState({
              isSegmentDeleting: false,
            });
          });
      } else {
        wavesurfer.regions.list[selectedSegment.data.segmentation_id].remove();
        this.setState({
          selectedSegment: null,
          isSegmentDeleting: false,
        });
      }
    }
  
    handleSegmentSave(e) {
      const { selectedSegment, segmentationUrl } = this.state;
      const { start, end } = selectedSegment;
  
      const {
        transcription,
        annotations,
        segmentation_id = null,
      } = selectedSegment.data;
  
      console.log(annotations);
  
      this.setState({ isSegmentSaving: true });
  
      if (segmentation_id === null) {
        axios({
          method: "post",
          url: segmentationUrl,
          data: {
            start,
            end,
            transcription,
            annotations,
          },
        })
          .then((response) => {
            const { segmentation_id } = response.data;
            selectedSegment.data.segmentation_id = segmentation_id;
            this.setState({
              isSegmentSaving: false,
              selectedSegment,
              successMessage: "Segment saved",
              errorMessage: null,
            });
          })
          .catch((error) => {
            console.log(error);
            this.setState({
              isSegmentSaving: false,
              errorMessage: "Mandatory(*) fields not filled",
              successMessage: null,
            });
          });
      } else {
        axios({
          method: "put",
          url: `${segmentationUrl}/${segmentation_id}`,
          data: {
            start,
            end,
            transcription,
            annotations,
          },
        })
          .then((response) => {
            this.setState({
              isSegmentSaving: false,
              successMessage: "Segment saved",
              errorMessage: null,
            });
          })
          .catch((error) => {
            console.log(error);
            this.setState({
              isSegmentSaving: false,
              errorMessage: "Error saving segment",
              successMessage: null,
            });
          });
      }
    }
  
    handleTranscriptionChange(e) {
      const { selectedSegment } = this.state;
      selectedSegment.data.transcription = e.target.value;
      this.setState({ selectedSegment });
    }
  
    handleLabelChange(key, e) {
      const { selectedSegment, labels } = this.state;
      selectedSegment.data.annotations = selectedSegment.data.annotations || {};
      if (labels[key]["type"] === "multiselect") {
        selectedSegment.data.annotations[key] = {
          label_id: labels[key]["label_id"],
          values: Array.from(e.target.selectedOptions, (option) => option.value),
        };
      } else {
        selectedSegment.data.annotations[key] = {
          label_id: labels[key]["label_id"],
          values: e.target.value,
        };
      }
      this.setState({ selectedSegment });
    }
  
    handleAlertDismiss(e) {
      e.preventDefault();
      this.setState({
        successMessage: "",
        errorMessage: "",
      });
    }
  
    render() {
      const {
        zoom,
        isPlaying,
        labels,
        isDataLoading,
        isMarkedForReview,
        referenceTranscription,
        selectedSegment,
        isSegmentDeleting,
        isSegmentSaving,
        errorMessage,
        successMessage,
        dataId,
      } = this.state;
      return (
        <div>
          <Helmet>
            <title>Annotate</title>
          </Helmet>
          <div className="container h-100">
            <div className="h-100 mt-5 text-center">
                <h4>Annotation Id : {dataId}</h4>
              {errorMessage ? (
                <Alert
                  type="danger"
                  message={errorMessage}
                  onClose={(e) => this.handleAlertDismiss(e)}
                />
              ) : null}
              {successMessage ? (
                <Alert
                  type="success"
                  message={successMessage}
                  onClose={(e) => this.handleAlertDismiss(e)}
                />
              ) : null}
              {isDataLoading ? <Loader /> : null}
              <div className="row justify-content-md-center my-4">
                <div ref={(el) => (this.segmentTranscription = el)}></div>
                <div id="waveform"></div>
                <div id="timeline"></div>
              </div>
              {!isDataLoading ? (
                <div>
                  <div className="row justify-content-md-center my-4">
                  <div className="col-1">
                      <IconButton
                        icon={faArrowLeft}
                        color="#6DB65B"
                        size="2x"
                        title="Previous Annotation"
                        onClick={() => {
                          this.handlePreviousAnnotation();
                        }}
                      />
                    </div>
  
                    <div className="col-1">
                      <IconButton
                        icon={faBackward}
                        size="2x"
                        title="Skip Backward"
                        onClick={() => {
                          this.handleBackward();
                        }}
                      />
                    </div>
                    <div className="col-1">
                      {!isPlaying ? (
                        <IconButton
                          icon={faPlayCircle}
                          size="2x"
                          title="Play"
                          onClick={() => {
                            this.handlePlay();
                          }}
                        />
                      ) : null}
                      {isPlaying ? (
                        <IconButton
                          icon={faPauseCircle}
                          size="2x"
                          title="Pause"
                          onClick={() => {
                            this.handlePause();
                          }}
                        />
                      ) : null}
                    </div>
                    <div className="col-1">
                      <IconButton
                        icon={faForward}
                        size="2x"
                        title="Skip Forward"
                        onClick={() => {
                          this.handleForward();
                        }}
                      />
                    </div>
                    <div className="col-1">
                      <IconButton
                        icon={faArrowRight}
                        color="#6DB65B"
                        size="2x"
                        title="Next Annotation"
                        onClick={() => {
                          this.handleNextAnnotation();
                        }}
                      />
                    </div>
                  </div>
                  <div className="row justify-content-center my-4">
                    {referenceTranscription ? (
                      <div className="form-group">
                        <label className="font-weight-bold">
                          Reference Transcription
                        </label>
                        <textarea
                          className="form-control"
                          rows="3"
                          cols="50"
                          disabled={true}
                          value={referenceTranscription}
                        ></textarea>
                      </div>
                    ) : null}
                  </div>
                  <div>
                      <div className="row justify-content-center my-4">
                        {Object.entries(labels).map(([key, value], index) => {
                          if (!value["values"].length) {
                            return null;
                          }
                          return (
                            <div className="col-3 text-left" key={index}>
                              <label htmlFor={key} className="font-weight-bold">
                                {key}
                              </label> <span style={{color: "red"}}>*</span>
  
                              <select
                                className="form-control"
                                name={key}
                                multiple={
                                  value["type"] === "multiselect" ? true : false
                                }
                                value={
                                  (selectedSegment &&
                                    selectedSegment.data.annotations &&
                                    selectedSegment.data.annotations[key] &&
                                    selectedSegment.data.annotations[key][
                                    "values"
                                    ]) ||
                                  (value["type"] === "multiselect" ? [] : "")
                                }
                                onChange={(e) => this.handleLabelChange(key, e)}
                                ref={(el) => (this.labelRef[key] = el)}
                              >
                                {value["type"] !== "multiselect" ? (
                                  <option value="-1">Choose Label Type</option>
                                ) : null}
                                {value["values"].map((val) => {
                                  return (
                                    <option
                                      key={val["value_id"]}
                                      value={`${val["value_id"]}`}
                                    >
                                      {val["value"]}
                                    </option>
                                  );
                                })}
                              </select>
                            </div>
                          );
                        })}
                      </div>
                      <div className="row justify-content-center my-4">
                        <div className="form-group">
                          <label className="font-weight-bold">
                            Annotator Feedback
                          </label>
                          <textarea
                            className="form-control"
                            rows="3"
                            cols="50"
                            value={
                              (selectedSegment &&
                                selectedSegment.data.transcription) ||
                              ""
                            }
                            onChange={(e) => this.handleTranscriptionChange(e)}
                            ref={(el) => (this.transcription = el)}
                          ></textarea>
                        </div>
                      </div>
                      <div className="row justify-content-center my-4">
                        <div className="col-2">
                          <Button
                            size="lg"
                            type="danger"
                            disabled={isSegmentDeleting}
                            isSubmitting={isSegmentDeleting}
                            onClick={(e) => this.handleSegmentDelete(e)}
                            text="Clear"
                          />
                        </div>
                        <div className="col-2">
                          <Button
                            size="lg"
                            type="primary"
                            disabled={isSegmentSaving}
                            onClick={(e) => this.handleSegmentSave(e)}
                            isSubmitting={isSegmentSaving}
                            text="Save"
                          />
                        </div>
                      </div>
                    </div>
                  <div className="row justify-content-center my-4">
                    <div className="form-check">
                      <input
                        className="form-check-input"
                        type="checkbox"
                        id="isMarkedForReview"
                        value={true}
                        checked={isMarkedForReview}
                        onChange={(e) => this.handleIsMarkedForReview(e)}
                      />
                      <label
                        className="form-check-label"
                        htmlFor="isMarkedForReview"
                      >
                        Mark for review
                      </label>
                    </div>
                  </div>
                </div>
              ) : null}
            </div>
          </div>
        </div>
      );
    }
  }
  
  export default withRouter(Annotate);
  