import { __esDecorate, __runInitializers } from "tslib";
import { html, LitElement, nothing } from 'lit';
import { property } from 'lit/decorators.js';
import { consume } from '@lit/context';
import { classMap } from 'lit/directives/class-map.js';
import { github, google, linkedin } from './icons.js';
import { organizationContext } from '../../../providers/organization.js';
export var State;
(function (State) {
    /**
     * The initial state (default).
     *
     * Next possible states:
     * - `Initialized`
     * - `Error`
     */
    State["Initializing"] = "initializing";
    /**
     * The state when an error occurred.
     * In this state, set the `errors` property to show error details.
     * There are no next possible states from here, the parent app has to reset the flow.
     */
    State["Error"] = "error";
    /**
     * State after the app initialization is complete.
     * It means that the app has read all necessary config but has not yet fetched invitation data.
     *
     * Next possible states:
     * - `ReadingStatus`
     */
    State["Initialized"] = "initialized";
    /**
     * The state when the application is fetching invitation data.
     * The component renders the loading indicator in this state.
     *
     * Next possible states:
     * - `Login`
     * - `Error`
     */
    State["ReadingStatus"] = "reading-status";
    /**
     * The main interaction state where the user can choose to log in (accept) or decline.
     *
     * Next possible states:
     * - `Rejecting`
     * - `InvitationAccepted`
     * - `InvitationDeclined`
     * - `Error`
     */
    State["Login"] = "login";
    /**
     * The state when the rejection request is being processed.
     *
     * Next possible states:
     * - `Rejected`
     * - `Error`
     */
    State["Rejecting"] = "rejecting";
    /**
     * The state when the invitation has been rejected by the user in the current session.
     *
     * There are no next possible states from here, the parent app has to reset the flow.
     */
    State["Rejected"] = "rejected";
    /**
     * The state when the invitation has been successfully accepted.
     * This state can be set after reading the invitation status that was already accepted previously.
     *
     * There are no next possible states from here, the parent app has to reset the flow.
     */
    State["InvitationAccepted"] = "invitation-accepted";
    /**
     * The state when the invitation is found to be deleted or invalid.
     *
     * There are no next possible states from here, the parent app has to reset the flow.
     */
    State["InvitationDeleted"] = "invitation-deleted";
    /**
     * The state when the invitation was already declined previously.
     *
     * There are no next possible states from here, the parent app has to reset the flow.
     */
    State["InvitationDeclined"] = "invitation-declined";
    /**
     * The state when the invitation has expired.
     *
     * There are no next possible states from here, the parent app has to reset the flow.
     */
    State["InvitationExpired"] = "invitation-expired";
})(State || (State = {}));
let InvitationScreen = (() => {
    let _classSuper = LitElement;
    let _state_decorators;
    let _state_initializers = [];
    let _state_extraInitializers = [];
    let _google_decorators;
    let _google_initializers = [];
    let _google_extraInitializers = [];
    let _linkedin_decorators;
    let _linkedin_initializers = [];
    let _linkedin_extraInitializers = [];
    let _github_decorators;
    let _github_initializers = [];
    let _github_extraInitializers = [];
    let _errors_decorators;
    let _errors_initializers = [];
    let _errors_extraInitializers = [];
    let _invitation_decorators;
    let _invitation_initializers = [];
    let _invitation_extraInitializers = [];
    let _organization_decorators;
    let _organization_initializers = [];
    let _organization_extraInitializers = [];
    return class InvitationScreen extends _classSuper {
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
            _state_decorators = [property({ type: String })];
            _google_decorators = [property({ type: Boolean })];
            _linkedin_decorators = [property({ type: Boolean })];
            _github_decorators = [property({ type: Boolean })];
            _errors_decorators = [property({ type: Array })];
            _invitation_decorators = [property({ type: Object })];
            _organization_decorators = [property({ type: Object, attribute: false }), consume({ context: organizationContext })];
            __esDecorate(this, null, _state_decorators, { kind: "accessor", name: "state", static: false, private: false, access: { has: obj => "state" in obj, get: obj => obj.state, set: (obj, value) => { obj.state = value; } }, metadata: _metadata }, _state_initializers, _state_extraInitializers);
            __esDecorate(this, null, _google_decorators, { kind: "accessor", name: "google", static: false, private: false, access: { has: obj => "google" in obj, get: obj => obj.google, set: (obj, value) => { obj.google = value; } }, metadata: _metadata }, _google_initializers, _google_extraInitializers);
            __esDecorate(this, null, _linkedin_decorators, { kind: "accessor", name: "linkedin", static: false, private: false, access: { has: obj => "linkedin" in obj, get: obj => obj.linkedin, set: (obj, value) => { obj.linkedin = value; } }, metadata: _metadata }, _linkedin_initializers, _linkedin_extraInitializers);
            __esDecorate(this, null, _github_decorators, { kind: "accessor", name: "github", static: false, private: false, access: { has: obj => "github" in obj, get: obj => obj.github, set: (obj, value) => { obj.github = value; } }, metadata: _metadata }, _github_initializers, _github_extraInitializers);
            __esDecorate(this, null, _errors_decorators, { kind: "accessor", name: "errors", static: false, private: false, access: { has: obj => "errors" in obj, get: obj => obj.errors, set: (obj, value) => { obj.errors = value; } }, metadata: _metadata }, _errors_initializers, _errors_extraInitializers);
            __esDecorate(this, null, _invitation_decorators, { kind: "accessor", name: "invitation", static: false, private: false, access: { has: obj => "invitation" in obj, get: obj => obj.invitation, set: (obj, value) => { obj.invitation = value; } }, metadata: _metadata }, _invitation_initializers, _invitation_extraInitializers);
            __esDecorate(this, null, _organization_decorators, { kind: "accessor", name: "organization", static: false, private: false, access: { has: obj => "organization" in obj, get: obj => obj.organization, set: (obj, value) => { obj.organization = value; } }, metadata: _metadata }, _organization_initializers, _organization_extraInitializers);
            if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
        }
        #state_accessor_storage = __runInitializers(this, _state_initializers, State.Initializing
        /**
         * When set it renders the Google login button. Disabled by default.
         * @attribute
         */
        );
        /**
         * This is the main state definition that controls what is rendered on the screen.
         * It can be one of the `State` enum values.
         *
         * @attribute
         */
        get state() { return this.#state_accessor_storage; }
        set state(value) { this.#state_accessor_storage = value; }
        #google_accessor_storage = (__runInitializers(this, _state_extraInitializers), __runInitializers(this, _google_initializers, false
        /**
         * When set it renders the LinkedIn login button. Disabled by default.
         * @attribute
         */
        ));
        /**
         * When set it renders the Google login button. Disabled by default.
         * @attribute
         */
        get google() { return this.#google_accessor_storage; }
        set google(value) { this.#google_accessor_storage = value; }
        #linkedin_accessor_storage = (__runInitializers(this, _google_extraInitializers), __runInitializers(this, _linkedin_initializers, false
        /**
         * When set it renders the GitHub login button. Disabled by default.
         * @attribute
         */
        ));
        /**
         * When set it renders the LinkedIn login button. Disabled by default.
         * @attribute
         */
        get linkedin() { return this.#linkedin_accessor_storage; }
        set linkedin(value) { this.#linkedin_accessor_storage = value; }
        #github_accessor_storage = (__runInitializers(this, _linkedin_extraInitializers), __runInitializers(this, _github_initializers, false
        /**
         * The list of errors to display.
         */
        ));
        /**
         * When set it renders the GitHub login button. Disabled by default.
         * @attribute
         */
        get github() { return this.#github_accessor_storage; }
        set github(value) { this.#github_accessor_storage = value; }
        #errors_accessor_storage = (__runInitializers(this, _github_extraInitializers), __runInitializers(this, _errors_initializers, void 0));
        /**
         * The list of errors to display.
         */
        get errors() { return this.#errors_accessor_storage; }
        set errors(value) { this.#errors_accessor_storage = value; }
        #invitation_accessor_storage = (__runInitializers(this, _errors_extraInitializers), __runInitializers(this, _invitation_initializers, void 0));
        /**
         * The invitation details retreived from the backend.
         * This property must be set for the component to function correctly.
         */
        get invitation() { return this.#invitation_accessor_storage; }
        set invitation(value) { this.#invitation_accessor_storage = value; }
        #organization_accessor_storage = (__runInitializers(this, _invitation_extraInitializers), __runInitializers(this, _organization_initializers, void 0));
        /**
         * The fetched organization details for which the invitation is valid.
         *
         * This property consumes the `organizationContext`.
         */
        get organization() { return this.#organization_accessor_storage; }
        set organization(value) { this.#organization_accessor_storage = value; }
        /**
         * Dispatches the authentication event for the selected provider.
         *
         * @param provider The authentication provider to use.
         */
        dispatchAuth(provider) {
            this.dispatchEvent(new CustomEvent('authenticate', {
                detail: { provider },
                bubbles: false,
                composed: false,
            }));
        }
        authenticateGoogle() {
            this.dispatchAuth('google');
        }
        authenticateGithub() {
            this.dispatchAuth('github');
        }
        authenticateLinkedin() {
            this.dispatchAuth('linkedin');
        }
        /**
         * Handles the click on the "Open organization" button after accepting the invitation.
         */
        handleAcceptedOpen() {
            this.dispatchEvent(new CustomEvent('open', {
                bubbles: false,
                composed: false,
            }));
        }
        /**
         * Handles the click on the "Decline" button to reject the invitation.
         */
        handleReject() {
            this.dispatchEvent(new CustomEvent('reject', {
                bubbles: false,
                composed: false,
            }));
        }
        render() {
            const classes = {
                'slide': true,
                'login-slide': true,
                'error': [
                    State.Error,
                    State.InvitationDeclined,
                    State.InvitationDeleted,
                    State.InvitationDeclined,
                    State.InvitationExpired,
                ].includes(this.state),
            };
            return html `
      <div class="content">
        <div class="${classMap(classes)}">${this.renderPage()}</div>
      </div>
    `;
        }
        renderPage() {
            switch (this.state) {
                case State.Initializing:
                    return this.renderCheckingUser();
                case State.Error:
                    return this.renderError();
                case State.Initialized:
                    // This is only an intermediate state before fetching data
                    return this.renderCheckingUser();
                case State.ReadingStatus:
                    return this.renderCheckingUser();
                case State.Login:
                    return html `${this.renderInto()} ${this.renderLoginForm()}`;
                case State.Rejecting:
                    return this.renderRejecting();
                case State.Rejected:
                    return this.renderRejected();
                case State.InvitationAccepted:
                    return this.renderInvitationAccepted();
                case State.InvitationDeclined:
                    return this.renderInvitationDeclined();
                case State.InvitationDeleted:
                    return this.renderInvitationDeleted();
                case State.InvitationExpired:
                    return this.renderInvitationExpired();
                default:
                    return html `<p>Unknown state.</p>`;
            }
        }
        renderCheckingUser() {
            return html `<div class="login">
      <p class="body-large">Loading...</p>
      <ui-progress indeterminate class="login-progress"></ui-progress>
    </div>`;
        }
        renderInto() {
            const { invitation } = this;
            const name = invitation?.name;
            return html ` <div class="intro">
      <h1 class="display-small">${name ? html `Hi ${name}` : 'Welcome to API Now!'}</h1>
      <p class="body-large">You've been invited to join an organization.</p>
    </div>`;
        }
        renderLoginForm() {
            return html `
      <div class="login">
        <p class="body-large">To respond to the invitation, please log in.</p>
        <div class="login-option">${this.renderGoogleButton()}</div>
        <div class="login-option">${this.renderGithubButton()}</div>
        <div class="login-option">${this.renderLinkedinButton()}</div>
        <div class="login-option">
          <ui-button class="decline" color="text" @click="${this.handleReject}">Decline invitation</ui-button>
        </div>
      </div>
    `;
        }
        renderRejecting() {
            return html `<div class="login">
      <h1 class="display-medium">Thank you for responding</h1>
      <p class="body-large">We will let them know you were not the intended recipient.</p>
      <ui-progress indeterminate class="login-progress"></ui-progress>
    </div>`;
        }
        renderRejected() {
            return html `<div class="login">
      <h1 class="display-medium">Thank you for responding</h1>
      <p class="body-large">We've let them know you were not the intended recipient.</p>
    </div>`;
        }
        renderError() {
            const { errors = [] } = this;
            return html `<div class="login">
      <h1 class="display-medium">Responding error</h1>
      <p class="body-large">An error occurred while processing your request.</p>
      <ul>
        ${errors.map((error) => html `<li>${error}</li>`)}
      </ul>
    </div>`;
        }
        renderInvitationAccepted() {
            return html `<div class="login">
      <h1 class="display-medium">Invitation accepted</h1>
      <p class="body-large">You have successfully accepted the invitation.</p>
      <ui-button class="open" color="filled" @click="${this.handleAcceptedOpen}">Open organization</ui-button>
    </div>`;
        }
        renderInvitationDeclined() {
            const { invitation } = this;
            const time = invitation?.respondedAt;
            let info;
            if (time) {
                const d = new Date(time);
                info = html `<p class="body-large">
        You declined the invitation <relative-time datetime="${d.toISOString()}">${d.toLocaleString()}</relative-time>.
      </p>`;
            }
            else {
                info = html `<p class="body-large">You have declined the invitation.</p>`;
            }
            return html `<div class="login">
      <h1 class="display-medium">Invitation declined</h1>
      ${info}
      <p class="body-large">You can safely close this page.</p>
    </div>`;
        }
        renderInvitationDeleted() {
            const { invitation } = this;
            const time = invitation?.deletedInfo?.time;
            let info;
            if (time) {
                const d = new Date(time);
                info = html `<p class="body-large">
        The invitation has been deleted
        <relative-time datetime="${d.toISOString()}">${d.toLocaleString()}</relative-time>.
      </p>`;
            }
            else {
                info = html `<p class="body-large">The invitation has been deleted.</p>`;
            }
            return html `<div class="login">
      <h1 class="display-medium">Invitation deleted</h1>
      ${info}
      <p class="body-large">You can safely close this page.</p>
    </div>`;
        }
        renderInvitationExpired() {
            const { invitation } = this;
            const time = invitation?.expiresAt;
            let info;
            if (time) {
                const d = new Date(time);
                info = html `<p class="body-large">
        The invitation expired <relative-time datetime="${d.toISOString()}">${d.toLocaleString()}</relative-time>.
      </p>`;
            }
            else {
                info = html `<p class="body-large">The invitation has expired.</p>`;
            }
            return html `<div class="login">
      <h1 class="display-medium">Invitation expired</h1>
      ${info}
      <p class="body-large">You can safely close this page.</p>
    </div>`;
        }
        renderGoogleButton() {
            if (!this.google) {
                return nothing;
            }
            return html `<ui-button class="auth-button" color="outlined" @click="${this.authenticateGoogle}"
      >${google} Google</ui-button
    >`;
        }
        renderGithubButton() {
            if (!this.github) {
                return nothing;
            }
            return html `<ui-button class="auth-button" color="outlined" @click="${this.authenticateGithub}"
      >${github} Github</ui-button
    >`;
        }
        renderLinkedinButton() {
            if (!this.linkedin) {
                return nothing;
            }
            return html `<ui-button class="auth-button" color="outlined" @click="${this.authenticateLinkedin}"
      >${linkedin} LinkedIn</ui-button
    >`;
        }
        constructor() {
            super(...arguments);
            __runInitializers(this, _organization_extraInitializers);
        }
    };
})();
/**
 * An App screen (HTML Element) allowing the user to accept an invitation to join an organization.
 *
 * This component handles the UI for invitation acceptance flow.
 * It does not implement the actual invitation logic but dispatches events. However, the state can be set
 * via the `state` property to reflect the current status.
 *
 * The parent app has to handle the invitation acceptance logic and update the state accordingly.
 *
 * When it comes to the user flow, the user can either accept or decline the invitation. To accept the
 * initivation the user has to log in through one of the supported providers (Google, GitHub, LinkedIn).
 * After successful login, the invitation is accepted. If the user declines the invitation, the invitation
 * is rejected immediately.
 *
 * @fires authenticate - Dispatched when the user clicks on one of the authentication buttons.
 *                       The detail object `CustomEvent<{ provider: AuthProviders }>` contains the selected provider.
 * @fires reject - Dispatched when the user clicks the "Decline" button.
 * @fires open - Dispatched when the user clicks the "Open organization" button
 *               after a successful acceptance (state `InvitationAccepted`).
 *
 * @example
 * ```html
 * <invitation-screen
 *   .state="${this.invitationState}"
 *   .invitation="${this.invitationData}"
 *   ?google="${true}"
 *   @authenticate="${this.handleAuth}"
 *   @reject="${this.handleReject}"
 * ></invitation-screen>
 * ```
 */
export default InvitationScreen;
//# sourceMappingURL=InvitationScreen.js.map