import { upperFirst } from 'lodash';
import AlertCircleIcon from 'mdi-react/AlertCircleIcon';
import MapSearchIcon from 'mdi-react/MapSearchIcon';
import * as React from 'react';
import { Route, Switch } from 'react-router';
import { combineLatest, merge, of, Subject, Subscription } from 'rxjs';
import { catchError, distinctUntilChanged, map, mapTo, startWith, switchMap } from 'rxjs/operators';
import { gql, graphQLContent } from '../../backend/graphql';
import { HeroPage } from '../../components/HeroPage';
import { isErrorLike } from '../../util/errors';
import { ExtensionAreaHeader } from './ExtensionAreaHeader';
export const registryExtensionFragment = gql `
    fragment RegistryExtensionFields on RegistryExtension {
        id
        publisher {
            __typename
            ... on User {
                id
                username
                displayName
                url
            }
            ... on Org {
                id
                name
                displayName
                url
            }
        }
        extensionID
        extensionIDWithoutRegistry
        name
        manifest {
            raw
            title
            description
        }
        createdAt
        updatedAt
        url
        remoteURL
        registryName
        isLocal
        viewerCanAdminister
    }
`;
const NotFoundPage = () => React.createElement(HeroPage, { icon: MapSearchIcon, title: "404: Not Found" });
/**
 * An extension area.
 */
export class ExtensionArea extends React.Component {
    constructor() {
        super(...arguments);
        this.state = {};
        this.componentUpdates = new Subject();
        this.refreshRequests = new Subject();
        this.subscriptions = new Subscription();
        this.onDidUpdateExtension = () => this.refreshRequests.next();
    }
    componentDidMount() {
        const routeMatchChanges = this.componentUpdates.pipe(map(({ match }) => match.params), distinctUntilChanged());
        // Changes to the route-matched extension ID.
        const extensionIDChanges = routeMatchChanges.pipe(map(({ extensionID }) => extensionID), distinctUntilChanged());
        // Changes to the global extensions settings.
        const globalExtensionsSettingsChanges = this.componentUpdates.pipe(map(({ extensions }) => extensions), distinctUntilChanged());
        // Fetch extension.
        this.subscriptions.add(combineLatest(extensionIDChanges, merge(this.refreshRequests.pipe(mapTo(false)), globalExtensionsSettingsChanges.pipe(mapTo(false)), of(false)))
            .pipe(switchMap(([extensionID, forceRefresh]) => {
            return this.props.extensions
                .forExtensionID(extensionID, registryExtensionFragment[graphQLContent])
                .pipe(catchError(error => [error]), map(c => ({ extensionOrError: c })), 
            // Don't clear old data while we reload, to avoid unmounting all components during
            // loading.
            startWith(forceRefresh ? { extensionOrError: undefined } : {}));
        }))
            .subscribe(stateUpdate => this.setState(stateUpdate), err => console.error(err)));
        this.componentUpdates.next(this.props);
    }
    componentWillReceiveProps(props) {
        this.componentUpdates.next(props);
    }
    componentWillUnmount() {
        this.subscriptions.unsubscribe();
    }
    render() {
        if (!this.state.extensionOrError) {
            return null; // loading
        }
        if (isErrorLike(this.state.extensionOrError)) {
            return (React.createElement(HeroPage, { icon: AlertCircleIcon, title: "Error", subtitle: upperFirst(this.state.extensionOrError.message) }));
        }
        // The URL, without the trailing "/-" that `this.props.match.url` includes on sub-pages.
        const url = this.props.match.url.replace(/\/-\/?$/, '');
        const context = {
            url,
            authenticatedUser: this.props.authenticatedUser,
            onDidUpdateExtension: this.onDidUpdateExtension,
            configurationCascade: this.props.configurationCascade,
            extension: this.state.extensionOrError,
            extensions: this.props.extensions,
            isLightTheme: this.props.isLightTheme,
        };
        return (React.createElement("div", { className: "registry-extension-area area--vertical" },
            React.createElement(ExtensionAreaHeader, Object.assign({}, this.props, context, { navItems: this.props.extensionAreaHeaderNavItems })),
            React.createElement("div", { className: "container pt-3" },
                React.createElement(Switch, null,
                    this.props.routes.map(({ path, render, exact, condition = () => true }) => condition(context) && (React.createElement(Route, { path: url + path, exact: exact, key: "hardcoded-key" // see https://github.com/ReactTraining/react-router/issues/4578#issuecomment-334489490
                        , 
                        // tslint:disable-next-line:jsx-no-lambda
                        render: routeComponentProps => render(Object.assign({}, context, routeComponentProps)) }))),
                    React.createElement(Route, { key: "hardcoded-key", component: NotFoundPage })))));
    }
}
//# sourceMappingURL=ExtensionArea.js.map