import React, { ChangeEvent, useState } from 'react'
import { TfiPlus } from 'react-icons/tfi';
import { Language, NameItem, NameType } from '../../../../api/models/Types';
import {  useQuery } from 'react-query';
import ErrorField from '../../../common/error/ErrorField';
import ErrorInput from '../../../common/error/ErrorInput';
import { languageQueryKey } from '../../../library/edit/language/LanguageListEditComponent';
import { GetLanguageList } from '../../../../api/LanguageApi';
import { DeepEqual } from '../../../../common/Helper';
import NameItemEditComponent, { IsLanguageValid, IsNameValid } from './NameItemEditComponent';

export interface INamesEditComponentProps{
	names: Array<NameItem> | null | undefined,
	dataLoadingError: Error | null,
	createName: (name: NameItem) => Promise<string | undefined>,
	editName: (name: NameItem, newValue: string | null, newLanguage: Language | null) => Promise<string | undefined>,
	deleteName: (name: NameItem) => Promise<string | undefined>,
	forceRefresh: () => void,
}

export default function NamesEditComponent(props: INamesEditComponentProps) {
	const { data: languagesData, isLoading: languagesIsLoading, isError: languagesIsError, error: languagesError } = useQuery(languageQueryKey, GetLanguageList);

	const [createNewNameError, setCreateNewNameError] = useState<string | null>(null);

	const [names, setNames] = useState<Array<NameItem>>([]);
	const [nameTypeSelected, selectNameTypeSelected] = useState<NameType>(NameType.Original);
	const [nameLanguageIdValue, setNameLanguageIdValue] = useState<[languageId: string | null, name: string | null]>();

	const selectLanguage = (id?: string | null) => {
		setNameLanguageIdValue(
			[
				(id == nameLanguageIdValue?.[0] ? null : id) ?? null,
				nameLanguageIdValue?.[1] ?? null,
			]
		);
	};

	const onNameChange = (event : ChangeEvent<HTMLInputElement>) => {
		setNameLanguageIdValue(
			[
				nameLanguageIdValue?.[0] ?? null,
				event.target.value ?? null,
			]
		);
	}

	const [editingName, SetEditingName] = useState<NameItem | null>(null);
	const SetEditing = (nameItem: NameItem, value: boolean) => {
		if (DeepEqual(nameItem, editingName) || !value){
			SetEditingName(null);
		}
		else{
			SetEditingName(nameItem);
		}
	};

	const [deletingName, SetDeletingName] = useState<NameItem | null>(null);
	const SetDeleting = (nameItem: NameItem, value: boolean) => {
		if (DeepEqual(nameItem, deletingName) || !value){
			SetDeletingName(null);
		}
		else{
			SetDeletingName(nameItem);
		}
	};

	React.useEffect(() => {
			setNameLanguageIdValue( [ null, null, ] );
			setNames( props.names ?? [] );
		}, [props]);
	
	return (
		<div className='card bg-body-tertiary p-0'>
			<div className='card-header'>
				<ul className="nav nav-underline">
					{
						React.Children.toArray(
							[
								{ type:NameType.Original, name: 'Оригинальное название' },
								{ type:NameType.OriginalInAnotherLanguage, name: 'Оригинальные на других языках' },
								{ type:NameType.Translation, name: 'Переведённые название' },
								{ type:NameType.Abbreviation, name: 'Аббревиатуры' },
							].map((tab) => 
								<li className='user-select-none nav-item' >
									<a className={'nav-link' + (tab.type == nameTypeSelected ? ' active' : '')} onClick={() => selectNameTypeSelected(tab.type)}>{tab.name}</a>
								</li>
							)
						)
					}
                </ul>
			</div>
			<div className='card-body'>
				{(!isTypeSingle(nameTypeSelected) || (isTypeSingle(nameTypeSelected) && !containsItems(names, nameTypeSelected))) &&
					<ErrorField error={createNewNameError}>
						<div className="input-group">
							<ErrorInput error={createNewNameError ?? (languagesError as Error | null)?.message}>
								<select className="form-select" aria-label="Язык названия" value={nameLanguageIdValue?.[0] ?? ''}
									disabled={languagesError != null || languagesData == null|| languagesData?.length == 0} onChange={(event) => selectLanguage(event.target.value)}>
									<option value={''} >Выберите язык названия</option>
									{!(languagesIsError || languagesIsLoading) && languagesData &&
										React.Children.toArray(
											languagesData.map((item) => 
												<option value={item.id}>
													{item.name} [{item.codeIso3}]
												</option>
											))
									}
									{/* <option value="2">Два</option> */}
								</select>
							</ErrorInput>

							<ErrorInput error={createNewNameError}>
								<input type="text" className="form-control" id="newAnimeTitleName" placeholder="Название" onChange={onNameChange} value={nameLanguageIdValue?.[1] ?? ''} />
							</ErrorInput>

							<ErrorInput error={createNewNameError} errorClassses={'btn-danger'}>
								{/* <button id='btn_add_name' type="submit" className='btn btn-primary' */}
								<button type="submit" className='btn btn-primary'
									disabled={!IsLanguageValid(nameLanguageIdValue?.[0]) || !IsNameValid(nameLanguageIdValue?.[1])}
									onClick={() => {
										if (IsLanguageValid(nameLanguageIdValue?.[0]) && IsNameValid(nameLanguageIdValue?.[1])){
											props.createName({
												language: languagesData?.find(q => q.id == nameLanguageIdValue![0]),
												value: nameLanguageIdValue![1],
												type: nameTypeSelected
											} as NameItem)
												.then(() => {
													setCreateNewNameError(null);
													setNameLanguageIdValue([ null, null ]);
													props.forceRefresh();
												})
												.catch((error: unknown) =>{
													setCreateNewNameError((error as Error)?.message);
													//console.error(error);
												});
										}
									}}>
										<span><TfiPlus /></span>
								</button>
							</ErrorInput>
						</div>
					</ErrorField>
				}

				{!isTypeSingle(nameTypeSelected) &&
					<hr />
				}

				{(!isTypeSingle(nameTypeSelected) || (isTypeSingle(nameTypeSelected) && containsItems(names, nameTypeSelected))) &&
					<>
						<ul className="list-group gap-2">
							{
								ShowNames(
									{
										names: names?.filter(q => q.type == nameTypeSelected) ?? [],
										languages: languagesData ?? [],
										isLoading: languagesIsLoading,
										isError: props.dataLoadingError != null,
										error: props.dataLoadingError,
										setDeleting: SetDeleting,
										isDeleting: (nameItem: NameItem | null) => DeepEqual(deletingName, nameItem),
										deleteName: props.deleteName,
										setEditing: SetEditing,
										isEdited: (nameItem: NameItem | null) => DeepEqual(editingName, nameItem),
										editName: props.editName,
										forceRefresh: props.forceRefresh
									}, languagesData) 
							}
						</ul>
					</>
				}

			</div>
		</div>
	)
}

type ShowGenresProps = {
	names: Array<NameItem>,
	languages: Array<Language>,
	isLoading: boolean,
	isError: boolean,
	error: Error | null,
	setDeleting: (nameItem: NameItem, value: boolean) => void,
	isDeleting: (nameItem: NameItem | null) => boolean,
	deleteName: (name: NameItem) => Promise<string | undefined>,

	setEditing: (nameItem: NameItem, value: boolean) => void,
	isEdited: (nameItem: NameItem | null) => boolean,
	editName: (name: NameItem, newValue: string | null, newLanguage: Language | null) => Promise<string | undefined>,
	forceRefresh: () => void,
}

function ShowNames(props: ShowGenresProps, languages: Array<Language> | undefined){
	if (props.isLoading){
		return (
			<>
				<div className="list-group-item placeholder rounded">1. SomeName</div>
				<div className="list-group-item placeholder rounded">2. SomeName</div>
				<div className="list-group-item placeholder rounded">3. SomeName</div>
			</>
		)
	}
	else if (props.isError){
		return (
			<li className="list-group-item card p-0">
				<div className='card-header bg-danger'>
					<h4 className='card-heading'>{props.error?.name ?? 'Unknown error'}</h4>
				</div>
				<div className='card-body bg-danger bg-opacity-50'>
					{/* Error occured during fetching items: */}
					<span>{props.error?.message ?? 'unknown'}</span>
				</div>
			</li>
		)
	}
	else{
		return React.Children.toArray(
			props.names.map((name: NameItem) => {
				return (
					<NameItemEditComponent
						name={name}
						languages={languages ?? []}
						// enabled={!item.deleted}
						enabled={true}
						setDeleting={props.setDeleting}
						isDeleting={props.isDeleting(name)}
						deleteName={props.deleteName}
						
						setEditing={props.setEditing}
						isEditing={props.isEdited(name)}
						editName={props.editName}
						forceRefresh={props.forceRefresh}
						/>
					
				);
			})
		)
	}
}

function isTypeSingle(type: NameType){
	return type === NameType.Original;
}

function containsItems(names: Array<NameItem>, type: NameType){
	return names.filter(q => q.type == type).length > 0;
}