/**
 * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). All Rights Reserved.
 *
 * This software is the property of WSO2 LLC. and its suppliers, if any.
 * Dissemination of any information or reproduction of any material contained
 * herein in any form is strictly forbidden, unless permitted by WSO2 expressly.
 * You may not alter or remove any copyright or other notice from copies of this content.
 */

import { IdentifiableComponentInterface, SBACInterface } from "@wso2is/core/models";
import {
    Code,
    EmptyPlaceholder,
    Link,
    LinkButton,
    ListLayout,
    PrimaryButton,
    SegmentedAccordion,
    SegmentedAccordionTitleActionInterface
} from "@wso2is/react-components";
import { getEmptyPlaceholderIllustrations, history } from "apps/console/src/features/core";
import { RequestErrorInterface } from "apps/console/src/features/core/hooks/use-request";
import { AxiosError } from "axios";
import React, { Fragment, FunctionComponent, ReactElement, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { Grid, Header, Icon, Input } from "semantic-ui-react";
import { ExtendedFeatureConfigInterface } from "../../../../configs/models";
import { APIResourcesConstants } from "../../../api-resources/constants";
import { APIResourceInterface } from "../../../api-resources/models";
import { AuthorizedAPIListItemInterface } from "../../models";

/**
 * Prop types for the API resources list component.
 */
interface SubscribedAPIResourcesProps extends
    SBACInterface<ExtendedFeatureConfigInterface>, IdentifiableComponentInterface {
    /**
     * List of all API Resources
     */
    allAPIResourcesListData: APIResourceInterface[];
    /**
     * Error when fetching all API Resources
     */
    allAPIResourcesFetchRequestError: AxiosError<RequestErrorInterface>;
    /**
     * List of subscribed API Resources
     */
    subscribedAPIResourcesListData: AuthorizedAPIListItemInterface[],
    /**
     * Error when fetching subscribed API Resources
     */
    subscribedAPIResourcesFetchRequestError: AxiosError<RequestErrorInterface>;
    /**
     * is shown placeholder
     */
    isShownPlaceholder: boolean;
    /**
     * Is scopes available for update.
     */
    isScopesAvailableForUpdate: boolean;
    /**
     * Set remove subscribed API Resource
     */
    setRemoveSubscribedAPIResource: (subscribedAPIResource: AuthorizedAPIListItemInterface) => void;
    
}

/**
 * API Resources listing page.
 *
 * @param props - Props injected to the component.
 * @returns API Resources Page component
 */
export const SubscribedAPIResources: FunctionComponent<SubscribedAPIResourcesProps> = (
    props: SubscribedAPIResourcesProps
): ReactElement => {

    const {
        allAPIResourcesListData,
        allAPIResourcesFetchRequestError,
        subscribedAPIResourcesListData,
        subscribedAPIResourcesFetchRequestError,
        isScopesAvailableForUpdate,
        setRemoveSubscribedAPIResource,
        ["data-componentid"]: componentId
    } = props;

    /**
     * Check if the place holders should be shown.
     */
    const showPlaceHolders: boolean = allAPIResourcesListData?.length === 0 || 
        subscribedAPIResourcesListData?.length === 0 || allAPIResourcesFetchRequestError != null ||
        subscribedAPIResourcesFetchRequestError !=  null ;

    const { t } = useTranslation();

    const [ activeSubscribedAPIResource, setActiveSubscribedAPIResource ] = useState<string>(null);
    const [ searchQuery, setSearchQuery ] = useState<string>(null);
    const [ searchedSubscribedAPIResources, setSearchedSubscribedAPIResources ] = 
        useState<AuthorizedAPIListItemInterface[]>(null);

    /**
     * Initialize the subscribed API Resources list to the searched list.
     */
    useEffect(() => {
        if (subscribedAPIResourcesListData) {
            setSearchedSubscribedAPIResources(subscribedAPIResourcesListData);
        }
    }, [ subscribedAPIResourcesListData ]);

    /**
     * Navigate to the API Resources page.
     */
    const navigateToAPIResources = () => history.push(APIResourcesConstants.getPaths().get("API_RESOURCES"));

    /**
     * Placeholder for the subscribed API Resources list.
     */
    const getPlaceholders = (): ReactElement => {
        if (allAPIResourcesFetchRequestError || subscribedAPIResourcesFetchRequestError) {
            return (
                <EmptyPlaceholder
                    image={ getEmptyPlaceholderIllustrations().genericError }
                    imageSize="tiny"
                    title={ t("extensions:develop.applications.edit.sections.apiAuthorization.sections" +
                        ".apiSubscriptions.placeHolderTexts.errorText.title") }
                    subtitle={ [ t("extensions:develop.applications.edit.sections.apiAuthorization.sections" +
                        ".apiSubscriptions.placeHolderTexts.errorText.subtitles.1"),
                    t("extensions:develop.applications.edit.sections.apiAuthorization.sections" +
                        ".apiSubscriptions.placeHolderTexts.errorText.subtitles.0") ] }
                    data-componentid={ `${componentId}-all-empty-placeholder-icon` }
                />
            );
        } else if (allAPIResourcesListData && allAPIResourcesListData.length === 0) {
            return (
                <EmptyPlaceholder
                    image={ getEmptyPlaceholderIllustrations().emptySearch }
                    action={ (
                        isScopesAvailableForUpdate && 
                            ( <Link
                                data-componentid={ `${componentId}-link-api-resource-page` }
                                onClick={ navigateToAPIResources }
                                external={ false }
                            >
                                { t("extensions:develop.applications.edit.sections.apiAuthorization.sections" +
                                    ".apiSubscriptions.buttons.noAPIResourcesLink") }
                            </Link> )
                    ) }
                    imageSize="tiny"
                    subtitle={ [ t("extensions:develop.applications.edit.sections.apiAuthorization.sections" +
                        ".apiSubscriptions.placeHolderTexts.noAPIResources") ] }
                    data-componentid={ `${componentId}-sub-empty-placeholder-icon` }
                />
            );
        } else if (subscribedAPIResourcesListData && subscribedAPIResourcesListData.length === 0) {
            return (
                <EmptyPlaceholder
                    image={ getEmptyPlaceholderIllustrations().emptyList }
                    action={ (
                        isScopesAvailableForUpdate && 
                            ( <PrimaryButton
                                data-componentid={ `${componentId}-empty-placeholder-sub-api-resource-button` }
                                onClick={ () => null }
                            >
                                <Icon name="add" />
                                { t("extensions:develop.applications.edit.sections.apiAuthorization.sections" +
                                    ".apiSubscriptions.buttons.subAPIResource") }
                            </PrimaryButton> )
                    ) }
                    imageSize="tiny"
                    subtitle={ [ t("extensions:develop.applications.edit.sections.apiAuthorization.sections" +
                        ".apiSubscriptions.placeHolderTexts.emptyText") ] }
                    data-componentid={ `${componentId}-sub-empty-placeholder-icon` }
                />
            );
        } else if (searchedSubscribedAPIResources?.length === 0) {
            return (
                <EmptyPlaceholder
                    title={ t("extensions:develop.applications.edit.sections.apiAuthorization.sections" +
                        ".apiSubscriptions.placeHolderTexts.emptySearch.title") }
                    subtitle={ [ t("extensions:develop.applications.edit.sections.apiAuthorization.sections" +
                        ".apiSubscriptions.placeHolderTexts.emptySearch.subTitle.0"),
                    t("extensions:develop.applications.edit.sections.apiAuthorization.sections" +
                        ".apiSubscriptions.placeHolderTexts.emptySearch.subTitle.1") ] }
                    image={ getEmptyPlaceholderIllustrations().emptySearch }
                    action={
                        (<LinkButton onClick={ clearSearchQuery }>
                            { t("extensions:develop.applications.edit.sections.apiAuthorization.sections" +
                                ".apiSubscriptions.buttons.emptySearchButton") }
                        </LinkButton>)
                    }
                    imageSize="tiny"
                />
            );
        } else {
            return null;
        }
    };

    /**
     * Resolves the header of the subscribed API Resources list.
     */
    const resolveSubscribedAPIResourcesListHeader = (subscribedAPIResource: AuthorizedAPIListItemInterface): 
        ReactElement => {
        return (
            <Header
                as="h6"
                className="header-with-icon"
                data-componentId={ `${componentId}-${subscribedAPIResource.apiId}-heading` }
            >
                <Header.Content>
                    { subscribedAPIResource.apiDisplayName }
                    <Header.Subheader>
                        {
                            subscribedAPIResource.apiIdentifier
                                ? <Code withBackground>{ subscribedAPIResource.apiIdentifier }</Code>
                                : null
                        }
                    </Header.Subheader>
                </Header.Content>
            </Header>
        );
    };

    /**
     * Creates the actions of the subscribed API Resources list item. 
     */
    const createAccordionAction = (subscribedAPIResource: AuthorizedAPIListItemInterface):
        SegmentedAccordionTitleActionInterface[] => {

        return [ {
            disabled: !isScopesAvailableForUpdate,
            icon: "trash alternate",
            onClick: () => setRemoveSubscribedAPIResource(subscribedAPIResource),
            popoverText: t("extensions:develop.applications.edit.sections.apiAuthorization.sections" +
                ".apiSubscriptions.unsubscribeAPIResourcePopOver"),
            type: "icon"
        } ];
    };

    /**
     * Handle the click event of the subscribed API Resources list item.
     */
    const handleSubscribedAPIResourcesListItemClick = (subscribedAPIResource: AuthorizedAPIListItemInterface): void => {
        activeSubscribedAPIResource === subscribedAPIResource.apiId
            ? setActiveSubscribedAPIResource(null)
            : setActiveSubscribedAPIResource(subscribedAPIResource.apiId);
    };

    /**
     * Clear the search query.
     */
    const clearSearchQuery = (): void => {
        setSearchQuery("");
        setSearchedSubscribedAPIResources(subscribedAPIResourcesListData);
    };

    /**
     * Search the subscribed API Resources.
     */
    const searchSubscribedAPIResources = (event: React.ChangeEvent<HTMLInputElement>): void => {
        const query: string = event.target.value;

        if (query.length > 0) {
            // Filter the subscribed API Resources using `apiDisplayName`
            setSearchQuery(query);
            setSearchedSubscribedAPIResources(
                subscribedAPIResourcesListData?.filter((subscribedAPIResource: AuthorizedAPIListItemInterface) => {
                    return subscribedAPIResource.apiDisplayName.toLowerCase().includes(query.toLowerCase());
                })
            );
        } else {
            setSearchedSubscribedAPIResources(subscribedAPIResourcesListData);
        }
    };

    return (
        showPlaceHolders
            ? getPlaceholders()
            : (
                <Grid>
                    <Grid.Row columns={ 1 }>
                        <Grid.Column mobile={ 16 } tablet={ 16 } computer={ 12 }>
                            <ListLayout
                                showTopActionPanel={ true }
                                showPagination={ false }
                                onPageChange={ () => null }
                                totalPages={ 100 }
                                data-componentid={ `${componentId}-list-layout` }
                                totalListSize={ subscribedAPIResourcesListData?.length }
                                rightActionPanel={
                                    isScopesAvailableForUpdate &&
                                        (<PrimaryButton
                                            data-componentid={ `${componentId}-subcribe-api-resource-button` }
                                            size="medium"
                                            floated="right"
                                            onClick={ () => null }
                                        >
                                            <Icon name="add" />
                                            { t("extensions:develop.applications.edit.sections." +
                                                "apiAuthorization.sections.apiSubscriptions.buttons.subAPIResource") }
                                        </PrimaryButton>)
                                }
                                leftActionPanel={
                                    (<div className="advanced-search-wrapper aligned-left fill-default">
                                        <Input
                                            className="advanced-search with-add-on"
                                            data-componentid={ `${componentId}-list-search-input` }
                                            icon="search"
                                            iconPosition="left"
                                            onChange={ searchSubscribedAPIResources }
                                            placeholder={ t("extensions:develop.applications.edit.sections." +
                                                "apiAuthorization.sections.apiSubscriptions.search") }
                                            floated="right"
                                            size="small"
                                            value={ searchQuery }
                                        />
                                    </div>)
                                }
                            >
                                {
                                    searchedSubscribedAPIResources?.length !== 0
                                        ? (
                                            <SegmentedAccordion
                                                data-componentid={ `${componentId}-subscribed-api-resources` }
                                                viewType="table-view"
                                            >
                                                {
                                                    searchedSubscribedAPIResources?.map(
                                                        (subscribedAPIResource: AuthorizedAPIListItemInterface) => (
                                                            <Fragment key={ subscribedAPIResource.apiId }>
                                                                <SegmentedAccordion.Title
                                                                    id={ subscribedAPIResource.apiId }
                                                                    data-componentid={
                                                                        `${componentId}-${subscribedAPIResource.apiId}
                                                                                    -title`
                                                                    }
                                                                    active={ activeSubscribedAPIResource
                                                                        === subscribedAPIResource.apiId }
                                                                    accordionIndex={ subscribedAPIResource.apiId }
                                                                    onClick={ () =>
                                                                        handleSubscribedAPIResourcesListItemClick(
                                                                            subscribedAPIResource) }
                                                                    content={ (
                                                                        resolveSubscribedAPIResourcesListHeader(
                                                                            subscribedAPIResource)
                                                                    ) }
                                                                    hideChevron={ false }
                                                                    actions={ 
                                                                        createAccordionAction(subscribedAPIResource) 
                                                                    }
                                                                />
                                                                <SegmentedAccordion.Content
                                                                    active={ false }
                                                                    data-componentid={
                                                                        `${componentId}-${subscribedAPIResource.apiId}
                                                                                    -content`
                                                                    }
                                                                />
                                                            </Fragment>
                                                        )
                                                    )
                                                }
                                            </SegmentedAccordion>
                                        ) 
                                        : getPlaceholders()
                                }
                            </ListLayout>
                        </Grid.Column>
                    </Grid.Row>
                </Grid>
            )
    );

};

/**
 * Default props for the component.
 */
SubscribedAPIResources.defaultProps = {
    "data-componentid": "subscribed-api-resources"
};
