import hydrajs from 'hydrajs';
import { IContact } from 'hydrajs/src/models/contact';
import { IContactListParams } from 'hydrajs/types/src/models/contacts/contact';
import assign from 'lodash/assign';
import debounce from 'lodash/debounce';
import filter from 'lodash/filter';
import isEmpty from 'lodash/isEmpty';
import map from 'lodash/map';
import React, { useRef, useState } from 'react';
import { asyncContainer, Typeahead } from 'react-bootstrap-typeahead';

interface IProps {
    onSelect: (contacts: IContact[]) => any;
    placeholder?: string;
    contactListParams?: IContactListParams;
    disabled?: boolean;
    selectedContacts?: IContact[];
    className?: string;
    id?: string;
    typeAheadSize?: string;
    clearButton?: boolean;
    multiple?: boolean;
    debounceDelay?: number;
    name?: string;
    autoFocus?: boolean;
}
interface IContactSelected extends IContact {
    selectedLabel: string;
}
const AsyncTypeahead = asyncContainer(Typeahead);
const defaultProps: Partial<IProps> = {
    placeholder: 'Search contact by name or username',
    multiple: false,
    clearButton: false,
    autoFocus: false,
    className: '',
    name: '',
    id: ''
};
// https://github.com/ericgio/react-bootstrap-typeahead/blob/master/docs/Props.md

export default function ContactSelect(props: IProps) {
    const [options, setOptions] = useState<IContactSelected[]>([]);
    const [isLoadingOptions, setIsLoadingOptions] = useState<boolean>(false);
    const controllerRef = useRef<AbortController>(new AbortController());
    const getSelectedLabel = (contact: IContact): string => {
        if (!contact) { return undefined; }
        const userName = contact.internalSso || contact.ssoUsername || '';
        return contact.fullNameCustom ? `${contact.firstNameCustom} ${contact.lastNameCustom} (${userName})` : `${userName}`;
    };

    const getContactsSelected = (contacts: IContact[]): IContactSelected[] => {
        if (!contacts) { return []; }
        return map(filter(contacts, (c) => !!c), (contact) => assign({}, contact, { selectedLabel: getSelectedLabel(contact) }));
    };
    const onChange = async (contacts: IContact[]) => {
        if (props.onSelect) {
            props.onSelect(contacts);
        }
    };

    const onFocus = async (users: IContact[]) => {
        if (!props.selectedContacts && isEmpty(options)) {
            handleSearch('');
        }
    };

    const handleSearch = async (query: string | number) => {
        if (query == null) {
            return;
        }
        // Initialize Params
        const params: IContactListParams = {
            limit: 60
        };

        if (query) {
            params.nameLookup = query as string;
        }

        const queryParams: IContactListParams = !isEmpty(props.contactListParams)
            ? assign({}, props.contactListParams, params)
            : params;
        try {
            setIsLoadingOptions(true);
            if (controllerRef.current) { controllerRef.current.abort(); }
            controllerRef.current = new AbortController();
            const response = await hydrajs.contacts.getSFDCContacts(queryParams, controllerRef.current.signal);
            const newOptions = (response && response.items && response.items.length) ? getContactsSelected(response.items) : [];
            setOptions(newOptions);
            setIsLoadingOptions(false);
        } catch (e) {
            setIsLoadingOptions((e.name === 'AbortError'));
        }
    };
    const selectedContactWithLabel = getContactsSelected(props.selectedContacts);
    const renderMenuItemChildren = (option: IContactSelected) => (<span key={option.ssoUsername}>{option.selectedLabel}</span>);
    return (
        <div className={`${props.className} contact-select`} id={`${isEmpty(props.id) ? 'contact-select-typeahead-wrapper' : props.id}`}>
            <AsyncTypeahead
                id={`${props.id} contact-select-typeahead`}
                defaultInputValue=""
                clearButton={props.clearButton}
                isLoading={isLoadingOptions}
                options={options}
                selected={selectedContactWithLabel}
                onChange={onChange}
                onFocus={onFocus}
                labelKey="selectedLabel"
                onSearch={debounce(handleSearch, props.debounceDelay || 300)}
                maxResults={15}
                placeholder={props.placeholder}
                renderMenuItemChildren={renderMenuItemChildren}
                bsSize={props.typeAheadSize}
                useCache={false}
                minLength={0}
                disabled={props.disabled}
                multiple={props.multiple}
                className="react-select-custom"
                name={props.name}
                autoFocus={props.autoFocus}
            />
        </div>
    );
}

ContactSelect.defaultProps = defaultProps;
