/* eslint no-param-reassign: 0 */
import React, { useState, useEffect } from 'react';
import ToggleIcon from './toggle-icon.jsx';
import AthletePanel from './athlete-panel.jsx';

const nlp = require("spacy-nlp/src/nlp")
const fetch = require('node-fetch');
const io = require("socket.io-client");

import SpeechRecognition, { useSpeechRecognition } from 'react-speech-recognition';

let lastMentioned;



const defaultAthlete = {displayJersey: '', displayDraft: '', status: {name: ''}, team: {name: '', displayName: '', logos: [{href: ''}], color: '#000'}, statsSummary: {statistics: []}};
const defaultDbAthlete = {id: '', name: {first: '', last: '', display: ''}, position: '', jersey: '', height: 0, weight: 0, dateofbirth: '', college: ''};

const leagueSports = {
  mlb: 'baseball',
  nba: 'basketball',
  nfl: 'football'
}

const sportsLeagues = {
  baseball: 'mlb',
  basketball: 'nba',
  football: 'nfl'
}

const sportsTriggers = {
  baseball: new RegExp('\W' + [
    'baseball', 'RBI', 'base hits', 'at bat', 'ground ball','home run','batted','walks','pitch','strikeout','stolen bases','batting average','on base','slugging','slugger', 'batted',
    'pitcher', 'catcher', 'right field', 'left field', 'center field', 'short stop', 'foul ball', 'hitter'
  ].join('|')),
  basketball: new RegExp('\W' + [
    'basketball', 'point guard', 'shooting guard', 'small forward', 'power forward',
    'assist', 'shooting', 'shooter', 'rebound', 'free throw', 'technical foul', 'double double', 'triple double', 'flagrant', 'dribble', 'court'
  ].join('|')),
  football: new RegExp('\W' + [
    'football', 'quarterback', 'runningback', 'halfback', 'receiver', 'tight end', 'left tackle', 'right tackle', 'left guard', 'right guard', 'defensive end', 'left end', 'right end', 'defensive tackle', 'linebacker', 'safety', 'cornerback', 'kicker', 'punter',
    'completions','passing attempt','passing yards','touchdown','interception','sacks','fumble','QB rating', 'tackle', 'receptions', 'rushing'
  ].join('|'))
};


const Demo = props => {
  
  const //[rawMessages, setRawMessages] = useState([]),
        //[formattedMessages, setFormattedMessages] = useState([]),
        [audioSource, setAudioSource] = useState(null),
        [keywords, setKeywords] = useState(''),
        [error, setError] = useState(null),
        [currentAthlete, setCurrentAthlete] = useState(defaultAthlete),
        [dbAthlete, setDbAthlete] = useState(defaultDbAthlete),
        [socket, setSocket] = useState(null),
        [alternatives, setAlternatives] = useState([]);

    
  const {
    listening,
    interimTranscript,
    finalTranscript
  } = useSpeechRecognition({ commands: [] });
    
    //console.log('recognitioncheck', SpeechRecognition.getRecognition());
    
  const initSocket = () => {
    setSocket(io('http://localhost:3001'));
  }
  
  useEffect(() => {
    if (socket) {
      console.log('setup socket');
      socket.on('dbResponse', (results, started) => {
        console.log('yay', results, (new Date().getTime()-started));
        if (results.length)
          setDbAthlete(results[0]);
      });
      
      //socket.on('data', handleFormattedMessage);
      socket.on('error', handleError);
  
      socket.on('message', (frame, json) => handleRawMessage({ sent: false, frame, json }));
      socket.on('send-json', json => handleRawMessage({ sent: true, json }))
      socket.on('close', (code, message) => handleRawMessage({ close: true, code, message }));
    }
  }, [socket]);
  
  const reset = () => {
    if (audioSource) {
      stopTranscription();
    }
    //setRawMessages([]);
    //setFormattedMessages([]);
    setError(null);
  }

  const stopTranscription = () => {
    //if (stream) {
    //  stream.stop();
      
      // this.stream.removeAllListeners();
      // this.stream.recognizeStream.removeAllListeners();
    //}
    
    setAudioSource(null);
  };

  const handleMicClick = () => {
    if (audioSource === 'mic') {
      stopTranscription();
      SpeechRecognition.abortListening();
      console.log('STOP listening');
      //setListening(false);
      return;
    }
    
    SpeechRecognition.startListening({ continuous: true });
    //setListening(true);
    console.log('listening');
    
    reset();
    setAudioSource('mic');

    //this.handleStream(recognizeMicrophone(this.getRecognizeOptions()));
  };

  const handleRawMessage = async (msg) => {
    //setRawMessages = rawMessages.concat(msg);
  }

  useEffect(() => {
    //setFormattedMessages = formattedMessages.concat(msg);
    
    const text = finalTranscript;
    console.log('formatted? ' + new Date().getTime(), text);
    
    if (text) {
      //var text = "I think Tom Brady is great";
      //console.log(text);
      //const result = await nlp.parse_named_entities(text, ['word']);
      
      nlp.parse_named_entities(text, ["words"]).then(output => {
        
        if (output.length) {
          const mentioned = output[0].result[0];
          
          if (mentioned && mentioned.indexOf(' ') !== -1 && mentioned !== lastMentioned) {
            lastMentioned = mentioned;
            console.log('mentioned', mentioned);
            setCurrentAthlete(defaultAthlete);
            setDbAthlete(defaultDbAthlete);
            
            socket.emit('dbQuery', {name: mentioned, started: new Date().getTime()});
            var startLookup = new Date().getTime();
            
            fetch('https://www.googleapis.com/customsearch/v1?key=AIzaSyCtY0Ysdb7hL1o3d2eIkNFKQfzh6vg9l08&cx=d452d0da4f98a9c81&q=' + encodeURIComponent(mentioned))
            	.then(resp => resp.json())
            	.then(json => {
            	  
            	  console.log('lookup took', (new Date().getTime() - startLookup) + 'ms')
            	  if (json.items && json.items.length) {
            	    let found = false;
            	    let alts = [];
            	    for (let i=0; i<7; ++i) {
                	  const searchResult = json.items[i];
                	  console.log(searchResult.title, searchResult);
                	  
                	  if (searchResult.title.match('Stats, News, Bio | ESPN')) {
                	    const linkSplit = searchResult.link.split('/');
                	    const playerID = linkSplit[7];
                	    const playerLeague = linkSplit[3];
                	    const playerSport = leagueSports[playerLeague];
                	    
                	    if (found) {
                	      alts.push({
                	        id: playerID,
                	        sport: playerSport,
                	        league: playerLeague
                	      });
                	    }
                	    
                	    fetch('https://site.web.api.espn.com/apis/common/v3/sports/' + playerSport + '/' + playerLeague + '/athletes/' + playerID + '/')
                    	.then(resp => resp.json())
                    	.then(json => {
                    	  if (json && json.athlete) {
                    	    json.athlete.leagueInfo = json.league;
                      	  console.log(json.athlete);
                      	  setCurrentAthlete(json.athlete);
                    	  }
                    	});
                    	found = true;
                	  }
            	    }
            	    setAlternatives(alts);
            	  }
            	});
          }
        }
        //console.log(JSON.stringify(output[0].parse_tree, null, 2));
      });
      
    }
  }, [interimTranscript]);


  // cleans up the keywords string into an array of individual, trimmed, non-empty keywords/phrases
  const getKeywordsArr = () => {
    return keywords.split(',').map(k => k.trim()).filter(k => k);
  };

  // cleans up the keywords string and produces a unique list of keywords
  const getKeywordsArrUnique = () => {
    return keywords
      .split(',')
      .map(k => k.trim())
      .filter((value, index, self) => self.indexOf(value) === index);
  };

  const handleError = (err, extra) => {
    console.error(err, extra);

    setError(err.message || err);
  };
  
  useEffect(() => {
    initSocket();
  }, []);

  let micButtonClass = 'mic-button';
  if (!listening) {
    if (audioSource === 'mic')
      micButtonClass += ' mic-button--active';
    else
      micButtonClass += ' mic-button--ready';
  }
  else {
    micButtonClass += ' mic-button--disabled';
  }

  const err = error
    ? (
      <Alert type="error" color="red">
        <p className="base--p">
          {error}
        </p>
      </Alert>
    )
    : null;
  
  //const shouldRender = (dbAthlete.name.first || currentAthlete.status.name) ? 'true' : 'false'
  //console.log('render check ', shouldRender);

  return (
    <div>
      <div className="flex buttons">
        <button type="button" className={micButtonClass} onClick={handleMicClick}>
          <ToggleIcon listening={listening} />
        </button>
      </div>

      {err}

      {false &&
        <Tabs selected={0} style={{display: "none"}}>
          <Pane label="Text">
            <Transcript messages={messages} />
          </Pane>
          <Pane label="Keywords">
            <Keywords
              messages={messages}
              isInProgress={!!audioSource}
            />
          </Pane>
        </Tabs>
      }
      
      { (dbAthlete.name.first || currentAthlete.status.name) && <AthletePanel info={currentAthlete} dbInfo={dbAthlete} /> }
      
    </div>
  );
  
}

export default Demo;
