import { CircularProgress } from "@mui/joy";
import React, {
  forwardRef,
  useImperativeHandle,
  useEffect,
  useRef,
  useState,
} from "react";
import { default as $ } from "jquery";
import Alert from '@mui/joy/Alert';
import Box from '@mui/joy/Box';
import Button from "@mui/joy/Button";
import Checkbox from "@mui/joy/Checkbox";
import jQuery from "jquery";
import { AutoComplete } from 'primereact/autocomplete';
import { api as API_URL } from '../config';

window.$ = window.jQuery = jQuery;
const theme = document.documentElement.getAttribute("data-theme")

document.addEventListener('set-theme', (e) => {
  const box = document.querySelector("[class*='lyrics-card-']")
  let removedClass = "lyrics-card-dark";
  let newTheme = e.detail;
  if (newTheme !== "light") {
    removedClass = "lyrics-card-light";
  }
  $(box).removeClass(removedClass)
  $(box).addClass(`lyrics-card-${newTheme}`);
});

export default function LyricSearch() {
  return (
    <div className="lyric-search">
    <h2 className="title">
    <span>Lyric Search</span>
    </h2>
    <div className="card-text my-4">
    <label>Search:</label>
    <LyricSearchInputField
              id="lyric-search-input"
              placeholder="Artist - Song" />
    <br />
    Exclude:<br />
    <div id="exclude-checkboxes">
    <UICheckbox id="excl-Genius" label="Genius" />
    <UICheckbox id="excl-LRCLib" label="LRCLib" />
    <UICheckbox id="excl-Cache" label="Cache" />
    </div>
    <div id="spinner" className="hidden">
    <CircularProgress
    variant="plain"
    color="primary"
    size="md"/></div>
    </div>
    <LyricResultBox/>
    </div>
  );
}

export function LyricSearchInputField(opts = {}) {
  const [value, setValue] = useState("");
  const [suggestions, setSuggestions] = useState([]);
  const [showAlert, setShowAlert] = useState(false);
  const autoCompleteRef = useRef(null);
  
  var search_toast = null;
  var ret_artist = null;
  var ret_song = null;
  var ret_lyrics = null;
  var start_time = null;
  var end_time = null;
  
  useEffect(() => {}, []);
  
  async function handleSearch() {
    if (autoCompleteRef.current) {
      autoCompleteRef.current.hide();
    }
    let validSearch = (value.trim() && (value.split(" - ").length > 1));
    let box = document.querySelector("[class*='lyrics-card-']")
    let spinner = $('#spinner');
    let excluded_sources = [];
    
    $("#exclude-checkboxes").find("input:checkbox").each(function () {
      if (this.checked) {
        let src = this.id.replace("excl-", "").toLowerCase();
        excluded_sources.push(src);
      }
    });
    
    if (validSearch) { 
      // define artist, song + additional checks
      let a_s_split = value.split(" - ", 2)
      var [search_artist, search_song] = a_s_split;
      search_artist = search_artist.trim();
      search_song = search_song.trim();
      if (! search_artist || ! search_song) {
        validSearch = false; // artist and song could not be derived
      }
    }
    
    if (!validSearch) {
      setShowAlert(true);
      setTimeout(() => { setShowAlert(false); }, 5000);
      $("#alert").removeClass("hidden");
      return;
    }
    if (!$("#alert").hasClass("hidden")) {
      setShowAlert(false);
      $("#alert").addClass("hidden");
    }
    $('#spinner').removeClass("hidden");
    $(box).addClass("hidden");
    //setTimeout(() => { $("#spinner").addClass("hidden"); alert('Not yet implemented.')}, 1000);
    search_toast = toast.info("Searching...", {style: { color: '#000000', backgroundColor: 'rgba(217, 242, 255, 0.8)'}});
    start_time = new Date().getTime()
    $.ajax({
      url: API_URL+'/lyric/search',
      method: 'POST',
      contentType: 'application/json; charset=utf-8',
      data: JSON.stringify({
        a: search_artist,
        s: search_song,
        excluded_sources: excluded_sources,
        src: 'Web',
        extra: true,
      })
    }).done((data, txtStatus, xhr) => {
      if (data.err || !data.lyrics) {
        $(spinner).addClass("hidden");
        return toast.update(search_toast, {
          type: "",
          render: `🙁 ${data.errorText}`,
          style: { backgroundColor: "rgba(255, 0, 0, 0.5)", color: 'inherit' },
          hideProgressBar: true,
          autoClose: 5000,
        })
      }
      end_time = new Date().getTime();
      let duration = (end_time - start_time) / 1000;
      ret_artist = data.artist;
      ret_song = data.song;
      ret_lyrics = data.lyrics;
      $(box).removeClass("hidden");
      $(spinner).addClass("hidden");
      $(box).html(`<span id='lyrics-info'>${ret_artist} - ${ret_song}</span>${ret_lyrics}`);
      toast.update(search_toast, {
        type: "",
        style: { backgroundColor: "rgba(46, 186, 106, 1)", color: 'inherit'  },
        render: `🦄 Found! (Took ${duration}s)`,
        autoClose: 2000,
        hideProgressBar: true
      });
    }).fail((jqXHR, textStatus, error) => {
      $(spinner).addClass("hidden");
      let render_text = `😕 Failed to reach search endpoint (${jqXHR.status})`;
      if (typeof jqXHR.responseJSON.detail !== "undefined") {
        render_text += `\n${jqXHR.responseJSON.detail}`;
      } 
      return toast.update(search_toast, {
        type: "",
        render: render_text,
        style: { backgroundColor: "rgba(255, 0, 0, 0.5)", color: 'inherit' },
        hideProgressBar: true,
        autoClose: 5000,
      })
    })
  }
  
  const handleKeyDown = (e) => {
    if (e.key !== "Enter") return;
    e.preventDefault();
    handleSearch();
  };
  
  const typeahead_search = (event) => {
    let query = event.query;
    $.ajax({
      url: API_URL+'/typeahead/lyrics',
      method: 'POST',
      contentType: 'application/json; charset=utf-8',
      data: JSON.stringify({
        query: query
      }),
      dataType: 'json',
      success: function (json) {
        return setSuggestions(json);
      }
    })
  };
  
  
  return (
    <div>
    <div id="alert">
    {showAlert && (
      <Alert
      color="danger"
      variant="solid"
      onClose={() => setShowAlert(false)}
      >
      You must specify both an artist and song to search.
      <br />
      Format: Artist - Song
      </Alert>
    )}
    </div>
    <AutoComplete
    theme="nano"
    size="40"
    scrollHeight="200px"
    autoFocus={true}
    virtualScrollerOptions={false}
    value={value}
    id={opts.id}
    ref={autoCompleteRef}
    suggestions={suggestions}
    completeMethod={typeahead_search}
    placeholder={opts.placeholder}
    onChange={(e) => { setValue(e.target.value)  }}
    onKeyDown={handleKeyDown}
    />
    <Button id="lyric-search-btn" onClick={handleSearch} className={"btn"}>
    Search
    </Button>
    </div>
  );
}

export const UICheckbox = forwardRef(function UICheckbox(opts = {}, ref) {
  const [checked, setChecked] = useState(false);
  const [showAlert, setShowAlert] = useState(false);
  let valid_exclusions = true;
  useImperativeHandle(ref, () => ({
    setChecked: (val) => setChecked(val),
    checked,
  }));
  
  const verifyExclusions = (e) => {
    let exclude_error = false;
    if (($("#exclude-checkboxes").find("input:checkbox").filter(":checked").length == 3)){
      $("#exclude-checkboxes").find("input:checkbox").each(function () {
        exclude_error = true;
        this.click();
      });
      if (exclude_error) {
        toast.error("All sources were excluded; exclusions have been reset.",
          { style: { backgroundColor: "rgba(255, 0, 0, 0.5)", color: 'inherit' } },
        );
      }
    }
  };
  return ( 
    <div> 
    <Checkbox
    id={opts.id}
    key={opts.label}
    checked={checked}
    label={opts.label}
    style={{ color: "inherit" }}
    onChange={(e) => {
      setChecked(e.target.checked);
      verifyExclusions();
    }}
    />
    </div>
  );
});


export function LyricResultBox(opts={}) {
  return (
    <Box className={`lyrics-card lyrics-card-${theme} hidden`} sx={{ p: 2 }}></Box>
  )
}