import React, { useState, useCallback, useEffect } from 'react';
import { Grommet } from 'grommet';
import { debounce } from 'lodash';
import { gql, useLazyQuery } from '@apollo/client';

import { Header } from './Header';
import { Search } from './Search';
import { Results } from './Results';
import { Artists, Artist } from '../interfaces';

const QUERY_ARTISTS = gql`
	query Artist($byName: String!) {
		queryArtists(byName: $byName) {
			name
			image
			id
			albums {
				name
				image
				id
			}
		}
	}
`;

export default function App() {
	const [inputValue, setInputValue] = useState('');
	const [getArtists, { data }] = useLazyQuery(QUERY_ARTISTS);
	const [artists, setArtists] = useState<Artists>([]);
	const [suggestions, setSuggestions] = useState<string[]>([]);
	const [selected, setSelected] = useState(false);

	// Debounce the database query
	// Based on: https://archive.is/wip/6JDqb
	const handleChange = (value: string) => {
		setInputValue(value);
	};

	const updateQuery = () => {
		getArtists({ variables: { byName: inputValue } });
	};

	const delayedQuery = useCallback(debounce(updateQuery, 200), [inputValue]);

	useEffect(() => {
		delayedQuery();
		// Cancel previous debounce calls during useEffect cleanup.
		return delayedQuery.cancel;
	}, [inputValue, delayedQuery]);

	const handleSelect = (suggestion: string) => {
		let updatedArtists: Artists = [];

		let suggestedArtists: Artists = data.queryArtists.slice(0, 5);

		// Find the selected artist and move it to index 0
		for (let i = 0; i < suggestedArtists!.length; i++) {
			if (suggestedArtists![i].name === suggestion) {
				let selectedArtist: Artists = suggestedArtists?.splice(i, 1);
				let otherArtists: Artists = suggestedArtists;
				updatedArtists = [...selectedArtist, ...otherArtists];
				break;
			}
		}

		setArtists(updatedArtists);
		setSelected(true);
	};

	const handleClick = (name: string) => {
		let updatedArtists: Artists = [];

		for (let i = 0; i < artists.length; i++) {
			if (artists[i].name === name) {
				let selectedArtist: Artists = artists.splice(i, 1);
				let otherArtists: Artists = artists;
				updatedArtists = [...selectedArtist, ...otherArtists];
				break;
			}
		}

		setArtists(updatedArtists);
	};

	useEffect(() => {
		if (data && data.queryArtists !== []) {
			// Limit artists to 5
			const updatedArtists = data.queryArtists.slice(0, 5);
			const updatedSuggestions: string[] = updatedArtists.map(
				(el: Artist) => {
					return el.name;
				},
			);
			setSuggestions(updatedSuggestions);
		}
	}, [data]);

	return (
		<Grommet theme={theme}>
			<Header>
				<h1>Spoti Search</h1>
			</Header>
			<Search
				inputValue={inputValue}
				handleChange={handleChange}
				suggestions={suggestions}
				handleSelect={handleSelect}
			/>
			{selected && (
				<Results artists={artists} handleClick={handleClick} />
			)}
		</Grommet>
	);
}

const theme = {
	global: {
		font: {
			family: 'Roboto',
			size: '18px',
			height: '20px',
		},
	},
};
